Any way to use Spring #Value annotations for non-singleton beans? - java

Currently I use the following method to inject properties into beans:
app.properties:
SingletonBean.valueA=this is a value
spring.xml:
<context:property-placeholder location="classpath:app.properties"/>
<context:component-scan base-package="..."/>
SingletonBean.java:
#Component
public class SingletonBean {
#Value("${SingletonBean.valueA}")
private String valueA;
}
This works great and is extremely convenient to be able to keep all my configs in a single, simple properties file. Is there any way I could extend this to work with multiple Beans of the same class? I need to do the following, with the 2 beans having different properties:
#Autowired private SampleBean beanA;
#Autowired private SampleBean beanB;
I know I can use the #Qualifier(name=...) annotation to support the following xml:
<bean id="beanA" class="SampleBean">
<property name="key1" value="A1"/>
<property name="key2" value="A2"/>
</bean>
<bean id="beanB" class="SampleBean">
<property name="key1" value="B1"/>
<property name="key2" value="B2"/>
</bean>
But with this I am forced to use old style setters in my SampleBean class, where I would prefer to use the newer #Value annotations.
Anyone know of a way to accomplish what I want that remains most consistent with how I am currently injecting my other beans?
The simple solution is just to inject all of the properties into the bean that utilizes the 2 SampleBean instances and create them with new instead. In my real code however there are actually 3 instances, each with 15 or so properties. This is much more cruft and repetition than I would like.

Related

Spring annotation component

I'm having some problems understanding how to use annotations, especially with beans.
I have one component
#Component
public class CommonJMSProducer
And I want to use it in another class and i thought I could do that to have a unique object
public class ArjelMessageSenderThread extends Thread {
#Inject
CommonJMSProducer commonJMSProducer;
but commonJMSProducer is null.
In my appContext.xml I have this :
<context:component-scan base-package="com.carnot.amm" />
Thanks
You have to configure Spring to use this autowiring feature:
<context:annotation-config/>
You can find the details of annotation-based config here.
ArjelMessageSenderThread also have to be managed by Spring otherwise it won't tamper with its members since it does not know about it.
OR
if you cannot make it a managed bean then you can do something like this:
ApplicationContext ctx = ...
ArjelMessageSenderThread someBeanNotCreatedBySpring = ...
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(
someBeanNotCreatedBySpring,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT, true);
OR
as others pointed out you can use annotations to use dependency injection on objects which are not created by Spring with the #Configurable annotation.
It depends on how you create instances of ArjelMessageSenderThread.
If ArjelMessageSenderThread is a bean that should be created by spring you just have to add #Component (and make sure the package is picked up by the component scan).
However, since you extend Thread, I don't think this should be a standard Spring bean. If you create instances of ArjelMessageSenderThread yourself by using new you should add the #Configurable annotation to ArjelMessageSenderThread. With #Configurable dependencies will be injected even if the instance is not created by Spring. See the documentation of #Configurable for more details and make sure you enabled load time weaving.
I used XML instead of annotations. This seemed difficult for not a big thing. Currently, I just have this more in the xml
<bean id="jmsFactoryCoffre" class="org.apache.activemq.pool.PooledConnectionFactory"
destroy-method="stop">
<constructor-arg name="brokerURL" type="java.lang.String"
value="${brokerURL-coffre}" />
</bean>
<bean id="jmsTemplateCoffre" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="jmsFactoryCoffre" />
</property>
</bean>
<bean id="commonJMSProducer"
class="com.carnot.CommonJMSProducer">
<property name="jmsTemplate" ref="jmsTemplateCoffre" />
</bean>
And another class to get the bean
#Component
public class ApplicationContextUtils implements ApplicationContextAware {
Thanks anyway

Spring injecting one property dynamically

I am new to Spring and i am stuck with a scenario where i need help.
My Scenario is i have a bean definition for some specific module like this.
<bean name="ruleEngineAction" class="com.xxxxx.yyyy.UserAction" scope="prototype">
<property name="userManager">
<ref bean="userManager" />
</property>
<property name="userDto">
<ref bean="userDto" />
</property>
</bean>
now within this bean i want to use one more property but that depends on the application flow like
<property name="roleManager">
<ref bean="roleManager">
</property>
so should i include this property with in the bean definition itself or i can do it dynamically in code because i don't want this property to be used a lot.
Please suggest me the right and efficient approach.
From what I understood from question, there is only one bean of type roleManager but the usage of roleManager is based on application flow.
In this scenario, I would recommend you to inject roleManager to ruleEngineAction as you would do with any other bean but use the bean only when it is necessary.
It is a bad practice to needless dependency to spring in normal classes like adding reference to applicationContext for fetching the bean dynamically at runtime.
Whether or not, you inject this bean, it'll anyways be created by Spring. Why not just include the property in your UserAction and whether to use it or not, can be decided in your class. No harm in having the bean injected, because you'll anyways use it for some scenarios.
Had the scenario been like, the object won't be created, if you don't inject/use, then it would make sense to consider this situation, but since Spring will create the object anyways, it really shouldn't be a problem to just inject it.
Well you need to add new property with getter and setter in your class com.xxxxx.yyyy.UserAction for roleManager like :
class UserAction {
// your previous properties userManager, userDto, etc.
private RoleManager roleManager; // assuming interface/class as RoleManager for roleManager
// getter and setter for roleManager
// your other action methods which will use roleManager
}
There is no problem if you inject also.Whenever you access that class only it will create the object of that class.

Spring Java Config using Autowired caused NPE

I am having difficulty understanding why something in Spring Java Config using #Autowired does not work.
First, I am trying to move all my #Autowired annotations in the Java Config classes. This has the effect of making my "POJOs" back into real POJOs. I can then not only test them easily outside of a Spring context, but can also use mock objects easily and readily.
So I first tried this:
#Configuration
public class Module3ConfigClass {
#Autowired
private Module1Bean1 module1Bean1;
#Autowired
private Module2Bean1 module2Bean1;
#Bean
public Module3Bean1 module3Bean1() {
return new Module3Bean1(module1Bean1, module2Bean1);
}
}
However, when the Module3Bean1 constructor is invoked, both passed in Beans are null. If you didn't follow my made up naming convention above, both of those beans would be created by a separate Java Config configuration file. Also note that everything is wired up correctly - I know this because everything works perfectly when the #Autowired tags are on the corresponding private member fields inside of Module3Bean1.
FWIW, I tried adding an #DependsOn annotation to module3Bean1() method, but had the same results. I guess I just would really like to understand this behavior, is it correct (I suspect it is, but why)?
Finally, I found an acceptable workaround shown here:
#Configuration
public class Module3ConfigClass {
#Bean
#Autowired
public Module3Bean1 module3Bean1(Module1Bean1 module1Bean1, Module2Bean1 module2Bean1) {
return new Module3Bean1(module1Bean1, module2Bean1);
}
}
This seems fine to me, but if anyone would care to comment on it, that would be welcome as well.
I think you came across same problem I just had. In my case problem was invalid xml configuration. In my module B I had config like :
<beans>
<context:component-scan base-package="com.moduleB"/>
<import resource="classpath:applicationContext-moduleA.xml"/>
</beans>
In moduleA context I placed "context:annotation-config" annotation.
When I change import/context order to :
<beans>
<import resource="classpath:applicationContext-moduleA.xml"/>
<context:component-scan base-package="com.moduleB"/>
</beans>
Autowiring for configuration class properties started to work.
We had the same issue and came to the conclusion that the error arose because we had a circular dependency where a BeanPostProcessor was involved.
A PropertyPlaceholderConfigurer (a BeanPostProcessor) has been configured to set its propertiesArray property with the help of another bean:
<bean id="globalPropertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
lazy-init="false" depends-on="javaLoggingConfigurer">
<property name="locations">
<list>
<value>classpath:config/host/${env.instance}.properties</value>
<value>WEB-INF/config/host/${env.instance}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
<property name="propertiesArray" value="#{springPropertyFinder.findProperties()}" />
</bean>
The used springPropertyFinder bean to set the propertiesArray is not a BeanPostProcessor but a "normal" bean that gathers all Properties instances with:
public Properties[] findProperties() {
Map<String, Properties> propertiesMap = applicationContext.getBeansOfType(Properties.class);
for (String title : propertiesMap.keySet()) {
PropertiesLoggerUtil.logPropertiesContent(logger, "Springcontext Properties ("+title+")", propertiesMap.get(title));
}
return propertiesMap.values().toArray(new Properties[propertiesMap.size()]);
}
The #Configuration class contained a bean of type Properties
So our assumption is that the #Configuration class has been created without being processed by the ConfigurationClassPostProcessor (also a BeanPostProcessor), because the PropertyPlaceholderConfigurer depends on the springPropertyFinder, which depends on the properties bean in the #Configuration class. The order of the BeanPostProcessors is probably not setup right under these circumstances.
This described setup worked in XML, but not with Java config.

How to generate proxy class from interface using pure annotations in Spring 3?

currently I'm creating proxy classes from interfaces with spring 3 xml config like this:
<bean id="abstractDaoTarget" class="mypackage.GenericDaoImpl" abstract="true" />
<bean id="abstractDao" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true" />
<bean id="personDao" parent="abstractDao">
<property name="proxyInterfaces">
<value>mypackage.CustomerDao</value>
</property>
<property name="target">
<bean parent="abstractDaoTarget">
</bean>
</property>
</bean>
Note that I have only one interface named PersonDao and NO implementation of this interface. The above xml snippet works fine, I can create an 'instance' of the interface.
My Question is how can I achieve this with pure Spring 3 annotations without the above xml snippet?
Is it possible without xml?
Have a look at Spring Data JPA. Here's an introductory tutorial. They are doing pretty much exactly what you are.
Are you looking for an way to generate Beans with an factory completely written in Java without xml? - Then use #Configuration to annotate the class and #Bean to annotate the method that creates the bean. 3.11.1 Basic concepts: #Configuration and #Bean
If this is not what you mean, then have a look at the code of Hades. This is a project that do the same think like (I guess) you. Creating DAOs from Interfaces.

Can spring container inject collaborators using custom methods?

Normally dependencies are injected via setters by the following configuration (http://static.springsource.org/sprin...beans-beanname) :
<bean id="exampleBean" class="examples.ExampleBean">
<!-- setter injection using the nested <ref/> element -->
<property name="beanOne"><ref bean="anotherExampleBean"/></property>
<!-- setter injection using the neater 'ref' attribute -->
<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
Lets say the class examples.ExampleBean has a collection listeners objects, and the method addListener(SomeListenerInterface) is the only possible way add listeners. Can I inject listeners declaratively in xml like its done with property setters?
You could probably conjure up some baroque mechanism for doing this all in XML, but the cleanest way to do this is to use a FactoryBean. You write a class which implement FactoryBean, and which is responsible for constructing and configuring your target object (see Spring docs). Your FactoryBean would have the required getters/setters/autowiring, and injects them into the target object.
This is often the cleanest way to handle non-javabeans in Spring, particularly if you cannot modify the target class.
Here goes property Element definition
Property elements correspond to JavaBean setter methods exposed by the bean classes.
To get your goal, you can use #Autowired annotation. It works even when using an arbitrary name
#Autowired
public void inject(SomeListenerInterface someListenerInterface) {
this.someListenerInterface = someListenerInterface;
}

Categories