I need a bean like this
<bean id="studentWithSchool" class="com.model.Student" scope="prototype">
<property name="school">
<bean class="com.model.School" scope="prototype"/>
</property>
</bean>
This is OK.
My problem is I have the student returning from a method from a different bean.
I usually load the bean like this when is a property.
<property name='beanProperty' value='#{anotherBean.getBeanProperty()}'/>
But in this case I need the new bean itself being set from the other bean method (School object is returned from another bean method).
This is what I try, and of course this is wrong:
<bean id="studentWithSchool" class="com.model.Student" scope="prototype" value='#{anotherBean.getBeanProperty()}'>
<property name="school">
<bean class="com.model.School" scope="prototype"/>
</property>
</bean>
Is there any workaround?
If I understand you correctly, the studentWithSchool is created and returned by a method in anotherBean. If that's the case, you can use a factory-method:
<bean id="studentWithSchool" factory-bean="anotherBean" factory-method="getBeanProperty" scope="prototype" />
I believe you are trying to use factory patter with Spring . For that you can use factory bean from spring.
<bean id="studentWithSchool" factory-bean="anotherBeanStaticFactory" factory- method="createBeanProperty" scope="prototype"
<property name="school">
<bean class="com.model.School" scope="prototype"/>
</property>
For more detail you can use below link :-
http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/beans/factory/BeanFactory.html
Related
I need to pass currentDate as String to my sendMetaStatsTask tasklet appended in subject .
Now, if I create a bean with scope="step" using following xml
<bean id="sendMetaStatsTask" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter" scope="step">
<property name="targetObject">
<bean class="com.nextag.catalog.springbatch.tasklets.GenerateReportFromQueriesTasklet">
<property name="mailTo" value="#{jobParameters['MAIL_TO']}"/>
<property name="mailFrom" value="#{jobParameters['MAIL_FROM']?:'wizereporter#nextag.com'}"/>
<property name="mailSubject" value="#{jobParameters['PARTNER_DOMAIN']+' Affiliate Seller Report - '+ currentDate.toString()}"/>
</bean>
</property>
<property name="targetMethod" value="execute"/>
</bean>
<bean id="fastDateFormat" class="org.apache.commons.lang.time.FastDateFormat" factory-method="getInstance">
<constructor-arg value="dd/MM/yyyy"/>
</bean>
<bean id="currentDate" class="java.util.Date" factory-bean="fastDateFormat" factory-method="format" scope="step">
<constructor-arg>
<bean class="java.util.Date"/>
</constructor-arg>
</bean>
It throws :-
Error creating bean with name 'currentDate' defined in BeanDefinition
defined in file
[/home/nextag/Apache6/tomcat/webapps/nextag/WEB-INF/classes/META-INF/spring/batch/jobs/seller-meta-stats-logging-job.xml]:
Initialization of bean failed; nested exception is
java.lang.IllegalStateException: Cannot create scoped proxy for bean
'scopedTarget.currentDate': Target type could not be determined at the
time of proxy creation.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
However, it works fine in case I use prototype .
Need to ask why it is not working in step scope, am I missing something ?
You need to tell the bean currentDate scope proxy so any injection is only valid to scope step. A good explanation is here
<bean id="fastDateFormat" class="org.apache.commons.lang.time.FastDateFormat" factory-method="getInstance">
<constructor-arg value="dd/MM/yyyy"/>
</bean>
<bean id="currentDate" class="java.util.Date" factory-bean="fastDateFormat" factory-method="format" scope="step">
<aop:scoped-proxy/>
<constructor-arg>
<bean class="java.util.Date"/>
</constructor-arg>
</bean>
I want to populate a value of my spring bean with the return value of a method. Is there any way I can do this?
<bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestinationName"
value="#Value#returned#by#method" />
I already have a bean of the class which has the method in my application context.
<bean id=xyz class=path.to.xyz>
</bean>
Please note that the value that I want to inject is not a variable, but return value of a method.
You can use factory-bean and factory-method:
<bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestinationName">
<bean factory-bean="xyz" factory-method="methodName" />
</property>
</bean>
If the method you want to call takes parameters you can pass them in using constructor-arg
<bean factory-bean="xyz" factory-method="methodName">
<constructor-arg index="0" value="firstParameter" />
<constructor-arg index="1" ref="someOtherBean" />
</bean>
This can be achieved with Spring expression language
<bean id="b1" class="B1">
</bean>
<bean id="b2" class="B2">
<property name=xxx" value="#{b1.xxx}" />
</bean>
you can just do
<bean id="JmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestinationName"
value="#{className.methodName()}" />
The spring container will call the geter method for that property
Note: you woudl have to autowire path.to.xyzConfig using #autowire
References 1 : Look for this : 6.4 Expression support for defining bean definitions
This question could help
In short, you could use a factory method to return the value you want.
Suppose I have my own bean which contains another beans hardcoded.
How to join this with Spring configuration?
First way is to use factory-method:
<bean id="bean1" class="myClass1"/>
<bean id="bean1.member" factory-bean="bean1" factory-method="getMember"/>
<bean id="bean2" class="myClass2">
<property name="collaborator" ref="bean1.member"/>
</bean>
Another way is to use EL:
<bean id="bean1" class="myClass1"/>
<bean id="bean2" class="myClass2">
<property name="collaborator" value="#{bean1.member}"/>
</bean>
In latter case Spring does not realize the dependency. Anyway, Bean Graph in Eclipse displays beans unrelated.
Are there better ways? May be I may implement some interface with MyClass1 so that it will treated as container or context?
You should create a separate bean for bean1.member and inject it into bean1
<bean id="bean3previouslyMember" class="myCompoundBean"/>
<bean id="bean1" class="myClass1">
<property name="member" ref="bean3previouslyMember"/>
</bean>
<bean id="bean2" class="myClass2">
<property name="collaborator" ref="bean3previouslyMember"/>
</bean>
Unless myClass1 is not modifiable and has no setter, this is generally what we do.
Short question: If I have class that impelemnts FactoryBean interface, how can I get from FactoryBean object itself instead of FactoryBean.getObject()?
Long question: I have to use 3-rd party Spring based library which is hardly use FactoryBean interface. Right now I always must configure 2 beans:
<!-- Case 1-->
<bean id="XYZ" class="FactoryBean1" scope="prototype">
<property name="steps">
<bean class="FactoryBean2">
<property name="itemReader" ref="aName"/>
</bean>
</property>
</bean>
<bean id="aName" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.ABC"/>
</property>
</bean>
<!-- Case 2-->
<bean id="XYZ2" class="FactoryBean1" scope="prototype">
<property name="steps">
<bean class="FactoryBean2">
<property name="itemReader" ref="aName2"/>
</bean>
</property>
</bean>
<bean id="aName2" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.QWE"/>
</property>
</bean>
Actyually defintion of a bean with name "XYZ" (compare with "XYZ2") never will be changed, but because of factory nature I must copy the code for each configuration.
Definition of a bean with name "aName" always will be new (i.e. each configuration will have own objectContext value).
I would like to simplify the configuration have a single factory bean (remove "XYZ2" and rid of link to "aName"):
<bean id="XYZ" class="FactoryBean1" scope="prototype">
<property name="steps">
<bean class="FactoryBean2"/>
</property>
</bean>
<bean id="aName" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.ABC"/>
</property>
</bean>
<bean id="aName2" class="com.package.ClassName1" scope="prototype">
<property name="objectContext">
<bean class="com.package.QWE"/>
</property>
</bean>
Unfortunately, it's not as simple as I expect. I suppose to glue factory (i.e. XYZ bean from the example) with necessary objects (i.e. "aName", "aName2") at runtime.
The approach doesn't work because when I ask Spring for FactoryBean object it returns to me FactoryBean.getObject() which impossible to instanciate at that time because of missing itemReader value.
I hope that SpringSource foresee my case I can somehome "hook" FactoryBean.getObject() call to provide all necessary properties at runtime.
Another complexity that disturb me a bit it's chains of Factories (Factory1 get an object from Factory2 that I have to "hook" at runtime).
Any ideas will be appreciated.
It's the & (ampersand), not the At-symbol, see Spring Framework documentation: Customizing instantiation logic using FactoryBeans
<property name="factoryBean" ref="&theFactoryBean" />
You can get the factory bean itself using the & syntax in the spring config:
<property name="factoryBean" ref="&theFactoryBean" />
as opposed to:
<property name="createdBean" ref="theFactoryBean" />
Is it possible to set the property of one bean by reading the property of another bean? For instance, suppose I had:
class A {
void setList(List list);
}
class B {
List getList();
}
I would like Spring to instantiate both classes, and call A's setList method, passing in the result of calling B's getList method. The Spring configuration might look something like:
<bean id="b" class="B"/>
<bean id"a" class="A">
<property name="list" ref="b" ref-property="list"/>
</bean>
Alas, this made-up XML does not work.
Why not just inject B into A? Because I do not want to introduce the extra dependency. A is only dependent List, not on B.
in addition to #Kevin's answer if you are using spring 3.0 it is possible to do this with the new spring expression language
<bean id="a" class="A">
<property name="list"
value="#{b.list}"/>
</bean>
spring 3.0 documentation
There are a couple of ways. Here is one:
<bean id="b" class="B"/>
<bean id="a" class="A">
<property name="list">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetObject" ref="b"/>
<property name="propertyPath" value="list"/>
</bean>
</property>
</bean>
Also see the <util:property-path/> element
If you are trying to do the same for a constructor then do this.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg type="javax.sql.DataSource" value="#{jdbc.dataSource}">
</constructor-arg>
</bean>
Here "jdbc" is as mentioned below that has property "dataSource" with getter and setter and initilized as:
<bean id="jdbc" class="com.la.activator.DataSourceProvider">
<property name="myDataSourcePool" ref="dsPoolService"/>
</bean>