I have two PropertyPlaceholderConfigurer beans in my project.
Bean A: (Defined as XML)
<bean id="propertyConfigurer" class="org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg ref="configurationEncryptor" />
<property name="order" value="0" />
<property name="locations">
<list>
<value>classpath:/app-dev.properties</value>
<value>classpath:/common-dev.properties</value>
</list>
</property>
</bean>
Bean B: (Defined as Java Config)
#Bean(name = "customPropertiesUtil")
public static CustomPropertiesUtil customPropertiesUtil(StandardPBEStringEncryptor configurationEncryptor) {
CustomPropertiesUtil customPropertiesUtil = new CustomPropertiesUtil ();
customPropertiesUtil.setSystemPropertiesModeName("SYSTEM_PROPERTIES_MODE_OVERRIDE");
customPropertiesUtil.setLocation(new ClassPathResource("mail-dev.properties"));
customPropertiesUtil.setOrder(1);
customPropertiesUtil.setIgnoreUnresolvablePlaceholders(false);
customPropertiesUtil.setStandardPBEStringEncryptor(configurationEncryptor);
return customPropertiesUtil;
}
The bean configurationEncryptor is defined in XML as:
<bean id="configurationEncryptor" class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config" ref="environmentVariablesConfiguration" />
</bean>
Bean B is created in a #Configuration class.
The odd thing is, if I remove the parameter injection shown in Bean B, everything works as expected. However, I need the encryptor to resolve some encrypted properties and the only way it is NOT NULL is to inject it using parameter injection. (see Why is an #Autowired field within a #Configuration class null?)
My question is how come, having a bean injected into the #Bean (Bean B) method cause Bean A to fail?
I'm trying to inject the uploadDao in the bean DemoHandler (XML below). But as expected it is Null. The question is how do I inject the DAO correctly.
Right now, there is a method call from WebUploadServiceImpl to DemoHandler and I can add 1 more parameter and send the value I need from uploadDao, but then that method is reused for multiple java classes and all those methods need to be refactored and that new param will not be relevant to the other classes.
Is there a way to get uploadDao to inject in DemoHandler? Any help is much appreciated. Thanks
Spring XML:
<bean id="wuService" class="com.abcd.service.WebUploadServiceImpl">
<property name="uploadDao" ref="uploadDao" />
<property name="webHandlers">
<set>
<bean class="com.abcd.service.handler.DemoHandler" />
</set>
</property>
</bean>
Code:
public class DemoHandler {
private UploadDao uploadDao;
public List handleM(...) {
...
Period period = uploadDao.anyMethod(..); --- Null here
}
}
If DemoHandler needs to set a dao, why don't you do something like this ...
<bean id="uploadDao" class="whatever.dao.UploadDaoImpl"/>
<bean id="wuService" class="com.abcd.service.WebUploadServiceImpl">
<property name="uploadDao" ref="uploadDao" />
<property name="webHandlers">
<set>
<bean class="com.abcd.service.handler.DemoHandler">
<property name="uploadDao" ref="uploadDao" />
</bean>
</set>
</property>
</bean>
You just need to replicate the injection mechanism already used in WebUploadServiceImpl. You haven't shown that code, I donĀ“t know if you use #Autowired, a set method or any other possibility.
I have this:
<bean class="...">
<constructor-arg name="beans">
<list>
<ref bean="beanA" />
<ref bean="beanB" />
</list>
</constructor-arg>
</bean>
I want to configure the list via a properties file, something like:
Properties file:
beans=beanA,beanB
XML file:
<bean class="...">
<constructor-arg name="beans">
<list refs="${beans}" />
</constructor-arg>
</bean>
Is something like this possible with Spring?
Edit: Just to give some context in case there are alternative solutions to the problem, this is for an application that has to write to multiple databases, and I want to configure which databases are enabled in the properties file, so that I don't have to maintain separate XML files for dev/production.
My first though is to use a FactoryBean where you inject the property ${beans} and the application context. Then in the factory bean, you loop on on every bean id/name and you call the context to retrieve the bean by name/id. Then you constructs your bean with your constructor and the list you have just built.
use annotation i.e.
#Value("${beans}")
private Class<? extends YourBean>String[] beanList;
I have the following setup:
<bean id="b1" class="SomeClass">
<property name="foo" ref="foo1"/>
</bean>
<bean id="b2" class="SomeClass">
<property name="foo" ref="foo2"/>
</bean>
<bean id="foo1" class="FooClass">
<constructor-arg index="0"><ref bean="dataSource1"/></constructor-arg>
...other constructor args
</bean>
<bean id="foo2" class="FooClass">
<constructor-arg index="0"><ref bean="dataSource2"/></constructor-arg>
...other constructor args
</bean>
Is there a way I can avoid duplicating the FooClass? What I want to do in bean b1 and b2 is add the reference to FooClass but specify the data source all other constructor arguments are the same.
Thanks
Jim
If you want some member of your class to be dynamically initialized\populated on every call to the corresponding getter, you can try the Lookup Method Injection. Read pp. 3.3.4.1 here.
So even if the class that contains the dynamic member was created in scope=singletone (the default for spring bean container) every time you will acces the field that has a lookup method assigned, you will get an appropriate object according to the business logic implemented inside the lookup method.
Also, I found a good example in Spring documentation - I think it is very clear. Take a look at "3.4.6.1 Lookup method injection"
what you are doing here is , autowiring class with constructure, as aviad said , you can use setter and getter method for your datasource injections
<bean id="foo" class="FooClass">
<constructor-arg index="0">datasource</constructor-arg>
...other constructor args
</bean>
<bean>your datasource bean1</bean>
<bean>your datasource bean2</bean>
and in your implementation you can set your data source as below
#Autowire
private FooClass foo;
foo.setDataSource(datasourcebean1);
you fooClass
public void FooClass(Datasource datasource){
private Datasource datasource;
public void setDatSource(Datasource datasource);
public Datasource getDataSource();
}
EDIT- as per spring documentation, you can pass constructor argument if that doesnt change in terms of its value. But in your case for FooClass you want to pass different datasource at different occasion (hope i get it correctly), so in this case you need to just pass datasouce instance either datasource 1 or datasource 2 during spring initialization, as spring will expect constructor argument while initialing FooClass. later during runtime pass different datasource and set your datasource using setter method.
bean spring config
<bean id="foo" class="FooClass">
<constructor-arg index="0" ref="datasource1"></constructor-arg>
...other constructor args
</bean>
public class FooClass(){
// on spring initialization, it will inject datasource1
public void FooClass(DataSource dataSource){
}
have your setter and getter method for datasource
}
where in your calling service
public class dataBaseInvoke(){
public Datasource datasource2
public FooClass fooClass;
inside method{
fooClass.setDatasource(datasource2);
fooClass.addFoo();
}
}
Considering your implementation, you may want to go for the Bean Definition Inheritance.
From Spring documentation:
A bean definition can contain a lot of configuration information,
including constructor arguments, property values, and
container-specific information such as initialization method, static
factory method name, and so on. A child bean definition inherits
configuration data from a parent definition. The child definition can
override some values, or add others, as needed. Using parent and child
bean definitions can save a lot of typing. Effectively, this is a form
of templating.
Basically what it says is that you could have a kind of "Template for your Bean Definition" mark it as abstract and use it in other compatible beans as parent to inherit those configurations.
This sample was taken from spring documentation:
<bean id="inheritedTestBean" abstract="true"
class="org.springframework.beans.TestBean">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
So at this point this bean isn't instantiated and will be used for bean definition inheritance purpose only.
<bean id="inheritsWithDifferentClass"
class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBean" init-method="initialize">
<property name="name" value="override"/>
<!-- the age property value of 1 will be inherited from parent -->
</bean>
Here you could see that org.springframework.beans.DerivedTestBean is used to instantiate the bean but it will use all definition of the parent, plus, it will override the property name. The class doesn't needs to be specified on the parent, but if specified on the parent (inheritedTestBean) and not on the child (inheritsWithDifferentClass) the parent class will be used to instantiate the child. Not everything is inherited as we can see here:
A child bean definition inherits constructor argument values, property
values, and method overrides from the parent, with the option to add
new values. Any initialization method, destroy method, and/or static
factory method settings that you specify will override the
corresponding parent settings.
The remaining settings are always taken from the child definition:
depends on, autowire mode, dependency check, singleton, scope, lazy
init.
Here is a sample using your classes:
<!-- the way you are already using it -->
<bean id="b1" class="SomeClass">
<property name="foo" ref="foo1"/>
</bean>
<!-- if you use it just once, you could declare it inside the bean that uses it -->
<bean id="b2" class="SomeClass">
<property name="foo">
<bean id="foo1" class="FooClass" parent="foo">
<constructor-arg index="0"><ref bean="dataSource1"/></constructor-arg>
</bean>
</property>
</bean>
<!-- here no class definition, only the default configuration -->
<bean id="foo" abstract="true">
<!-- constructor arg 0 is defined only on child beans -->
<constructor-arg index="1" value="whatever1" />
<constructor-arg index="2" value="whatever2" />
<constructor-arg index="3" value="whatever3" />
<constructor-arg index="4" value="whatever4" />
</bean>
<bean id="foo2" class="FooClass">
<constructor-arg index="0"><ref bean="dataSource2"/></constructor-arg>
</bean>
Use abstract bean
<bean id="foo" class="FooClass">
// Set all properties except datasoure
<property name="..." />
</bean>
<bean id="foo1" parent="foo">
<property name="datasource" ref="ds1" />
</bean>
<bean id="foo2" parent="foo">
<property name="datasource" ref="ds2" />
</bean>
Of course you have to use empty contructor instantiation and expose FooClass properties with accessors. If you don't need foo1 and foo2 in other places go for inner beans.
I have two child classes(PermanentEmployee and ContractEmployee) of Employee class.
I want spring to inject the dependencies under TextEditor1 by type . Along with this i want to inject the PermanentEmployee depndency under TextEditor1.
similarily want to inject the contractEmployee dependency under TextEditor2. Rest should be injected
automatically by type?
<bean id="textEditor1" class="com.TextEditor" autowire="byType">
<property name="employee" ref="permanentEmployee" />
</bean>
<bean id="textEditor2" class="com.TextEditor" autowire="byType">
<property name="employee" ref="contractEmployee" />
</bean>
<bean id="permanentEmployee" class="com.PermanentEmployee" >
</bean>
<bean id="contractEmployee" class="com.ContractEmployee">
</bean>
But i get the error Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: saying two match are found ?
Update :- i also tried below but it didn't work either
<bean id="textEditor1" class="com.TextEditor" autowire="byType">
<qualifier type="permanentEmployee"/>
</bean>
I think that's because those two com.PermanentEmployee and com.ContractEmployee are implementing another interface like com.Employee?
That way, Spring will recognize those same type and can't choose which bean Spring have to auto-wire into the bean.
So you might need to add those byName, not byType in this case.
If you change those injection with #Autowired annotation or #Resource annotation, you can use #Qualifier( for Autowired ) or name property of Resource annotation to specify bean name.