Spring #Value is always null - java

I'm using spring in my app and I have a .properties file which has some values defined.
In a java class there is a String value:
#Value("${test}")
public String value;
The point is that if I inject this value in beans definition:
<bean id="customClass" class="package.customClass.CustomClassImpl">
<property name="value" value="${test}"></property>
</bean>
It works fine, but if I use #Value, there is always a null... Why is that happening?
And no, I'm not doing any "new" no instantiate "customClass", I get it with context.getBean("customClass).
EDIT: I have configured a property placeholder in the context:
<bean id="properties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:config.properties</value>
<value>classpath:constants.properties</value>
</list>
</property>
</bean>
Thanks in advance.

Remember, your class need a stereotype annotation like #Component or #Service

If you are creating spring boot application and your goal is to provide configuration parameter(s) via (application).properties there is a way to do it without explicit #Value declaration.
Create YourClassProperties with annotation #ConfigurationProperties("some.prefix"):
#ConfigurationProperties("my.example")
public class MyClassProperties {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
Add defined properties to (application).properties:
my.example.foo=bar
And then, in your application you can autowire needed properties...
#Autowired
private MyClassProperties myClassProperties;
... and use them as you would any other properties:
LOG.info("Value of the foo: {}", myClassProperties.getFoo());

Solve, you need to enable annotation config in configuration file: <context:annotation-config/>

You need to declare your .properties file using #PropertySource. Not sure it's doable using xml config.
Also, are you sure about this "$", it's "#" in this example :
http://forum.spring.io/forum/spring-projects/container/61645-value-and-propertyplaceholderconfigurer

Related

SpEL: get current bean name during bean instantiation

I am attempting to use SpEL to get the name of the bean currently being instantiated to allow multiple beans of same class to be created with different properties supplied by #PropertySource. I am hoping for something like the following:
public class SampleBean {
#Value("${#{CurrentBeanName}.val}")
private String val
}
Other bean:
public class OtherBean {
#Autowired
#Qualifier(name="BeanA")
SampleBean beanA;
#Autowired
#Qualifier(name="BeanB")
SampleBean beanB;
}
properties file:
BeanA.val=VALUE A
BeanB.val=VALUE B
If I add beanName=BeanA to my properties file, I am able to get this to work with
#Value("${${beanName}.val}")
Any ideas on what to do for #{BeanName}? If this is impossible then so be it, but if it works it would be much cleaner than my current solution.
EDIT:
Or any way to pass a constant from the xml bean definition to SpEL? example:
<bean id="BeanA" class="...">
<property name="prefix" value="BeanA"/>
</bean>
java:
public class SampleBean {
#Value("${#{prefix}.val}")
private String val
}
Any sort of attribute or anything would work
EDIT2:
This is trivial in old XML based config
spring.xml:
<bean id="beanA" class="SampleBean">
<property name="val" value="${BeanA.val}"/>
</bean>
<bean id="beanB" class="SampleBean">
<property name="val" value="${BeanB.val}"/>
</bean>
SampleBean.java:
public class SampleBean {
private String val;
public void setVal (String val) {
this.val = val;
}
}
However when switching to the new #Value annotations to get rid of all the setters, it seems non-singletons with diff properties aren't supported (i.e. no way to dynamically filter #Value arguments on bean creation)
No; it is not possible to reference the current bean.
EDIT
To address your comment below, the Java Configuration equivalent of
<bean id="BeanA" class="com.my.Foo">
<property name="prefix" value="BeanA"/>
</bean>
is
#Bean
public Foo BeanA() {
Foo a = new Foo();
a.setPrefix("BeanA");
}
although, by convention, you'd probably name it beanA.
If you have singleton bean types you could just use a static final variable for the name and then reference that. But the bigger issue is that you will be breaking the Spring inversion of control principals if you begin depending on Spring bean names, which is why this sort of thing isn't done. Pretty much want to focus on creating modules and domains for your project. If you begin accessing components coming from the Spring Context directly (such as the bean name) you will find that your modules will become brittle, hard to change and very hard to reason about as they begin to depend on behaviour from seemingly unrelated modules, such as the Spring Dependency Injection Framework. Although you may have a valid use-case for doing this you just need to be very very careful.

spring injection without constructor and setter

I have the question. If my class has dependency like:
public class Test {
public Depend depend;
//Here methods
}
And it does not have setter for Depend property or constructor with Depend as argument, and it has no annotation for Spring but has xml config like:
<bean id="depend" class="xxx.Depend"></bean>
<bean id="test" class="xxx.Test">
<property name="depend" ref="depend" />
</bean>
Is it possible to inject Depend into Test using such config (actually his config does not work. I just wonder - can I change smth to make it work not using annotations or setter/constructor)?
It is not possible without using annotations.
Your current configuration needs some simple changes to make this work. Annotate the depend field with #Autowired and enable component scanning.
Here's a detailed explanation: http://www.mkyong.com/spring/spring-auto-scanning-components/
Yes it is possible without annotations, but you would need to create a TestBeanFactory and then create an object of Test and set Depend yourself before returning it.
<bean id="depend" class="xxx.Depend"></bean>
<bean id="testFactory" class="xxx.TestFactory">
<property name="depend" ref="depend" />
</bean>
<bean id="test" factory-bean="testFactory" factory-method="createTest">
</bean>
Then your test factory would look something like this.
public class TestFactory {
private Depend depend;
public setDepend(Depend depend) {
this.depend = depend
}
public Test createTest() {
Test test = new Test();
test.depend = this.depend;
return test;
}
}

#Resource returns null for a bean of class String

I am new to Spring and I have the following problem:
I have the following bean:
<bean id="lastName" class="java.lang.String">
<constructor-arg value="Johnson"/>
</bean>
Then, in my class RegisterPerson, I have the following
#Configurable
public class RegisterPerson
#Resource(name="lastName")
private String lastName;
then in my method displayName(){
System.out.println(lastName)
}
lastName is null.
I looked for some examples, but couldn't find anything similar to my problem. Any advice or suggestions will be appreciated.
Thanks!
The best way to inject String into your class is declare properties configurer in your Spring XML: something like this:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath:/cfg/yourPropsFile.properties</value>
</list>
</property>
</bean>
If you are using annotations make sure that you have these lines in your spring file:
<context:annotation-config/>
<context:component-scan base-package="com.your.app"/>
Then just add that string you want to be injected in your spring bean into that file, for e.g.:
my.prop=Johnson
Then inject it in your controller using #Value annotation:
#Value("${my.prop}")
private String lastName;
This is assuming that your value needs to be configurable.
Otherwise if you need to inject String value as you are trying to do now, please note that by default using #Configurable annotation autowiring won't work. To enable autowiring you need to enable it using: #Configurable(autowire = Autowire.BY_NAME), but it shouldn't be used unless you really need it. #Configurable annotation is mostly used with AspecJ, which is not what you are trying to achieve here.
So define your class with #Component and using:
#Autowired
#Qualifier("lastName")
private String lastName;
will solve your problem.
You should use Autowired and Qualifier annotation..
#Autowired
#Qualifier("lastName")
private String lastName;
Try this configuration
public class Test {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("app-context.xml");
String s = (String) context.getBean("lastName");
}
}

How to load configuration parameters from XML files into Spring MVC Controllers?

I've noticed that I can load a config parameter into a bean using something like this in application-context.xml:
<beans:bean id="foo" class="com.foo.FooBean">
<beans:property name="foo" value="${foo}" />
</beans:bean>
What about if I want to access the foo value in a Controller without instantiating a bean? Is there a way to do that?
You can use the #Value annotation with util:properties
<util:properties id="props" location="classpath:com/foo/bar/props.properties"/>
And in your controller class, assuming you have a property with key 'foo':
#Value("#{props.foo}")
public void setFoo(String foo) {
this.foo = foo;
}
You can use PropertyPlaceholderConfigurer
Please refer to this link to read more about it
http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/beans.html#beans-factory-placeholderconfigurer

How can I inject a property value into an annotation configured spring mvc 3.0 controller

First: I'm using Spring 3.0
I have a problem when configuring my controller class. The controller uses a web service which I want to define the endpoint address using a .properties file.
#Controller
public class SupportController {
#Value("#{url.webservice}")
private String wsEndpoint;
...
In my application context xml-file, I've defined this:
<context:property-placeholder location="/WEB-INF/*.properties" />
I've been reading the documentation, trying different approaches (like adding prefix systemProperties.),but I keep getting an error message telling me that it doesn't exist.
Field or property 'url' cannot be
found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
Ok. I've figured it out.
Now, in the controller:
#Value("#{settings['url.webservice']")
Then in the context configuration I have this "helper bean":
<util:properties id="settings"
location="/WEB-INF/supportweb.properties"></util:properties>
This should work, too:
#Value("${url.webservice}")
private String wsEndpoint;
I have this configuration and it works fine:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
and I iniejct the property in this way
#Value("${root.log.level}")
private String prop;
the field is correctly initialized to "DEBUG" value.
you should check that the
<context:property-placeholder location="/WEB-INF/*.properties" />
is defined in webmvc-config.xml where you create instances of the #Controllers

Categories

Resources