I have a bean A that's annotated as Component. I am creating a map in Spring Config XML with the bean A as one of the values in the map. Is there anyway i can avoid creating the bean A in the config xml and just refer as it is annotated as Component.
Thanks.
All annotated components will be available with the same class name (camelCase) by default. I think you can use that name in the XML file.
<property name="taskList">
<list>
<ref bean="componetClass1" />
<ref bean="componetClass2" />
<ref bean="componetClass3" />
<ref bean="componetClass4" />
</list>
</property>
In this case ComponentClass1 etc are the class names which are annotated with #Component annotation.
Related
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;
Inside a web application, I'm using dozer mapper (5.3.2) to perform some object to object mappings.
DozerBeanMapper is instantiated using spring bean definition. Mapping file is provided as property in the spring context xml.
<bean id="idmToBoMPersonMapper" class="org.dozer.DozerBeanMapper" lazy-init="false" scope="singleton" >
<property name="mappingFiles" value="config/IiIdmToBoMPersonMapping.xml"/>
</bean>
Mapping is working, but according to logs, instance of DozerBeanMapper is created every time the code uses the mapper.
INFO DozerBeanMapper:166 - Initializing a new instance of dozer bean mapper.
This is concerns me, I'd expect the mapper to be created once and only once.
I have tried to explicitly use scope="singleton" in the spring bean configuration, but that is not helping either.
Any suggestions for me to try?
I would be better to use the Spring integration with Dozer instead, namely the DozerBeanMapperFactoryBean, see here the documentation for further details:
<bean class="org.dozer.spring.DozerBeanMapperFactoryBean">
<property name="mappingFiles"
value="classpath*:/*mapping.xml"/>
<property name="customConverters">
<list>
<bean class=
"org.dozer.converters.CustomConverter"/>
</list>
</property>
<property name="eventListeners">
<list>
<bean class="org.dozer.listeners.EventListener"/>
</list>
</property>
<property name="factories">
<map>
<entry key="id" value-ref="bean-factory-ref"/>
</map>
</property>
</bean>
I'm working with SpringFramework and Java. I use Spring xml files to define the flow of the architecture and also the beans that will be used in the Java part.
I have two beans of the same class in my xml file, but they have different arguments for the constructor:
<bean id="beanA" class="Class" >
<constructor-arg><value>valueA1</value></constructor-arg>
<constructor-arg><value>ValueA2</value></constructor-arg>
</bean>
<bean id="beanB" class="Class" >
<constructor-arg><value>valueB1</value></constructor-arg>
<constructor-arg><value>valueB2</value></constructor-arg>-->
</bean>
Is there a way to set one of the beans as default in order to #Autowired it from Java? And, when I want to use the non default bean, apply the #Qulifier("beanName") annotation.
try primary attribute, eg
<bean id="b1" class="test.B" />
<bean id="b2" class="test.B" />
<bean id="b3" class="test.B" primary="true" />
this guarantees that b3 bean will be injected here
public class Test {
#Autowired
B b;
...
Finally I used a the next thing: I have a setter (setClassValue(Class classValue)) in the java code for the class I want to use. Then, I set the property autowire-candidate to false in the bean that it's not going to be the default one:
<bean id="beanA" class="Class" autowire-candidate="false">
<constructor-arg><value>valueA1</value></constructor-arg>
<constructor-arg><value>valueA2</value></constructor-arg>
</bean>
<bean id="beanB" class="Class" >
<constructor-arg><value>valueB1</value></constructor-arg>
<constructor-arg><value>valueB2</value></constructor-arg>
</bean>
Then, in the xml file where I'm defining the bean of the class that is going to #Autowired the Class, I use the java setClassValue(Class classValue) method on this way:
<bean id="classThatAutowire" class="ClassThatAutowire" >
<property name="classValue" ref="beanA" />
</bean>
In the Java code yo will have #Autowired the beanB and then, set the beanA. It's not the best practice, but it works.
<bean id="cObject" scope="request" class="x.y.z.CClass"/>
<bean id="bObject" scope="request" class="x.y.z.BClass"/>
<bean id="aObject" scope="request" class="x.y.z.AClass">
<constructor-arg ref="bObject" />
<property name="cRef" ref="cObject" />
</bean>
aObject.cRef is not getting set for some reason. Note that constructor-arg and property are used in the same definition. I have not seen an example / post with similar feature.
On same sources my colleague discover:
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'service.MenuService#0'
defined in class path resource [spring-beans/integrator.xml]:
Could not resolve matching constructor (hint: specify index/type/name
arguments for simple parameters to avoid type ambiguities)
while my host, test and production servers have no such error.
With:
<bean class="service.MenuService">
<constructor-arg index="0" type="java.lang.String" value="#{user}"/>
<constructor-arg index="1" type="java.lang.String" value="#{password}"/>
<constructor-arg index="2" type="java.lang.String" value="#{uri}"/>
<property name="system" value="OPRT"/>
<property name="client" value="OPRT"/>
</bean>
while there are only one 3-args constructor in bean.
The reason to use constructor - it perform some additional actions on non-Spring library by invoking init() method. And set args as fields.
So I change spring-beans.xml to:
<bean class="service.MenuService" init-method="init">
<property name="login" value="#{user}"/>
<property name="password" value="#{password}"/>
<property name="httpsUrl" value="#{uri}"/>
<property name="system" value="OPRT" />
<property name="client" value="OPRT" />
</bean>
Take attention to init-method= part.
UPDATE After all I wrote simple XML config and step through Spring source code in debugger. Seems that with Spring 3.x it's possible to combine constructor-arg and property in XML bean definition (check doCreateBean in AbstractAutowireCapableBeanFactory.java, which call createBeanInstance and populateBean next).
See also https://softwareengineering.stackexchange.com/questions/149378/both-constructor-and-setter-injection-together-in-spring/
Mixing <constructor-arg> and <property> is generally a bad idea.
There is only one good reason for using <constructor-arg>, and that is to create immutable objects.
However, your objects are not immutable if you can set their properties. Don't use <constructor-arg>. Redesign the class, use an initializer method annotated with #PostConstruct if you need to apply some logic at bean creation time.
I want to define in my Spring XML context a bean that has a property of the type List of classes: i.e. List<Class<?>> classes
How do I send that bean a number of classes, say java.lang.String and java.lang.Integer?
The list needs not be reusable, i.e. I will not refer to it in another bean.
With Spring, the simplest possibility usually works.....
<property name="classes">
<list>
<value>java.lang.String</value>
<value>java.lang.Integer</value>
</list>
</property>
<property name="classes">
<list>
<bean class="java.lang.Class" factory-method="forName">
<constructor-arg value="java.lang.String"/>
</bean>
</list>
</property>
Something like that...