Configuring Spring Bean to Re-Use Its Own Properties? - java

I'm fairly new to Spring and I need a bean that has two properties -- the second of which is an inline bean that references the first property. Something like this:
<bean id="aBean" class="com.sample.Bean">
<property name="propertyOne" value="something" />
<property name="propertyTwo">
<bean class="com.sample.AnotherBean">
<property name="propertyThree" ref="propertyOne />
</bean>
</property>
</bean>
Making propertyOne its own bean isn't an option here. What would be the best way to accomplish this? Thanks!

Only way that I can think of would be to create a bean for your common property and refer to this common property in both Bean and AnotherBean - any reason why this is not an option for you?
Any other way would not work, because of the dependency graph - aBean is dependent on Another Bean and so AnotherBean would get instantiated before aBean and would not be able to refer to a child bean property.
If there had not been this dependency, you could have used Spring-EL to refer to the property:
<property name="propertyThree" value="${aBean.propertyOne}"/>

You can create "propertyOne" as a separate bean.
and reference that from aBean , and your inline bean.
<bean id="propertyOne" class="java.lang.String">
<constructor-arg><value>"blabla"</value></constructor-arg>
</bean>
<bean id="aBean" class="com.test.SimpleBean">
<property name="name" ref="firstProperty" />
<property name="newBean">
<bean class="com.test.OtherSimplwBean">
<property name="otherName" ref="propertyOne" />
</bean>
</property>

Related

Create Freemarker Configuration bean in Spring, together with parameter

I am having trouble creating a "freemarker.template.Configuration" bean and setting global shared variables in this instance of the Configuration. Something like:
<bean id="conf" class="freemarker.template.Configuraton">
<property name="sharedVariable" >
**??**
</property>
</bean>
Is this possible?
I can't use FreeMarkerConfigurer instead of Configurer because I am using servlets (full stack of Spring MVC) as controllers in my project. Is there any way to convert a FreemarkerConfigurer into a Configurer?
The problem stems from that shared variables is not a JavaBean property... but, accidentally, Configuration has a setAllSharedVariables(TemplateHashModelEx) method, that's technically a property, so something like this should work (I haven't tried it and my Spring XML is rusty... tell me if there are typos in it):
<bean id="conf" class="freemarker.template.Configuraton">
<property name="allSharedVariables">
<bean class="freemarker.template.SimpleHash">
<constructor-arg>
<map>
<entry key='someVarName' value='someValue' />
<entry key='otherVarName' value-ref='valueBeanId' />
</map>
</constructor-arg>
</bean>
</property>
</bean>

What is the best way of extending spring application context?

I need to extend spring applicatioContext xml file with new beans definitions and then add references to them to list, which is a property of one bean:
Basic applicationContext xml file:
<bean id="myBean" class="com.example.MyBean">
<property name="providers">
<list>
<ref bean="provider1">
</list>
</property>
</bean>
<bean id="provider1" class="com.example.Provider">
Depends on instance of application I have different providers, so I need to add them to the list. Now I have the additional beans definitions in database and use BeanFactoryPostProcessor to add them to the context and then add references to them to the list of providers. But I use #Transactional annotation on myBean and automatic transaction management (tx:annotation-driven) and because of using BeanFactoryPostProcessor the transaction annotations are not processed.
So I need another way to extend the application context and then the list of providers. What can I use?
My idea is to have xml file which at the beginning is empty and then fill it by data from database and then import it somehow in applicationContext. Is it possible?
Thanks for your help
You can override or extend the bean definitions in multiple ways. In short, here is one way..
main Application Context xml:
<bean id="myBaseBean" class="com.example.MyBean" abstract="true">
<property name="providers">
<list merge="true">
<ref bean="provider1" />
</list>
</property>
</bean>
<!-- default bean definition -->
<bean id="myBean" parent="myBaseBean">
<property name="providers">
<list merge="true">
</list>
</property>
</bean>
<bean id="provider1" class="com.example.Provider">
Some extendedApplication Context xml:
<bean id="myBean" parent="myBaseBean">
<property name="providers">
<list merge="true">
<ref bean="someOtherProvider" />
</list>
</property>
</bean>
<!-- bean definition of some other provider -->
This is nothing to do with Transactions You have to handle the transactions as usual for every other bean.
NOTE: All the application context files will be loaded/override based on the order of the file names you mention while creating the ApplicationContext.
Use #PostConstruct method in your MyBean class that loads and fills provider list from database.
#PostConstruct
public void initialize() {
providers.addAll(providerService.findAll());
}
Put all database related code into Service/Dao class and annotate it with #Transactional annotation

Common value configuration in Spring XML

I have several Spring beans in which one of the property value for all of them are same String value. Is there a way where I can define this String in XML at one place and refer it in all beans at property value settings?
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
<bean id="nextBean" class="test.NextBean">
<property name="property2" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
How to set commonValue in a seperate place and refer it in both places?
Try like this.
<bean id="commonConfig" abstract="true">
<property name="commonField" value="CommonValue"></property>
</bean>
<bean id="class1" class="com.dataclass.Class1" parent="commonConfig">
<property name="field1" value="value1"></property>
</bean>
<bean id="class2" class="com.dataclass.Class2" parent="commonConfig">
<property name="field2" value="value2"></property>
</bean>
Class1 & Class2 having one common field name "commonField", parent attribute is use for this common purpose only.
In Spring this is called bean definition inheritance(this is not java class inheritance, above example Class1 & n Class not inheriting in their respective java file.)
For more detail, look at Spring doc's link.
I've never tried it before, but this should work
<bean id="commonProp" class="java.lang.String">
<constructor-arg name="original" value="yourString"></constructor-arg>
</bean>
Then, in every bean you need to reference it:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" ref="commonProp"></property>
</bean>
You can define your string properties in some "init_constants.properties" file. Then you should load properties file in spring xml:
<bean id="properties"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
<value>classpath:mail.properties</value>
<value>classpath:init_constants.properties</value>
</list>
</property>
</bean>
And after that you can inject this properties using xml:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="{$prop1}"></property>
<property name="commonProperty" value="commonValue"></property>
</bean>
or in code using #Value annotation:
#Value(value="${prop1}")
private String property1;
Well If commonValue is string then you can put it in properties file and read it using #Value annotation.

How to inject a Spring bean id into another Spring Configured Bean?

I want to be able to pass a bean ID into another bean by reference. So if I have this:
<bean id="specialName" class="my.SpecialBean"/>
<bean id="referenceBean" class="my.ReferenceBean">
<property name="refId" value="<specialName.name>"/>
</bean>
public class ReferenceBean {
// The spring injected value of this should be 'specialName'
public String refId;
// getter & setter for refId
}
The reason I need this, it that ReferenceBean is actually a route builder in Camel and it directs messages to SpecialBean through the Spring Registry. I'm new to Spring and Camel, so if this is an ill conceived questions, my apologies.
You can use Spring-EL -
<bean id="specialName" class="my.SpecialBean"/>
<bean id="referenceBean" class="my.ReferenceBean">
<property name="refId" value="#{specialName.name}"/>
</bean>
Why not just put the id statically into refId there? It will not change later so why should you do something complicated here?
<bean id="specialName" class="my.SpecialBean"/>
<bean id="referenceBean" class="my.ReferenceBean">
<property name="refId" value="specialName"/>
</bean>
What about:
<bean id="specialName" class="my.SpecialBean" />
<bean id="referenceBean" class="my.ReferenceBean">
<property name="refId" ref="specialName" />
</bean>
This way your bean should be injected (provided you change the String attribute in my.SpecialBean.
Then you can get any attribute you want.
You could use the idref element (see Spring XML Beans Schema):
<bean id="specialName" class="my.SpecialBean"/>
<bean id="referenceBean" class="my.ReferenceBean">
<property name="refId">
<idref bean="specialName"/>
</property>
</bean>

Is there a shorthand for creating a String constant in Spring context XML file?

I need to define a string value in Spring context XML file that is shared by multiple beans.
This is how I do it:
<bean id="aSharedProperty" class="java.lang.String">
<constructor-arg type="java.lang.String" value="All beans need me :)"/>
</bean>
Creating a java.lang.String bean by passing a constructor argument of java.lang.String seems kludgy.
Is there a shortcut?
I know this property can be passed using PropertyOverrideConfigurer, but I want to keep this property within the XML file.
You can use PropertyPlaceholderConfigurer and keep values in xml:
<context:property-placeholder properties-ref="myProperties"/>
<bean id="myProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="aSharedProperty">All beans need me :)</prop>
</props>
</property>
</bean>
Then you reference it with:
<bean id="myBean" class="my.package.MyClass">
<property name="someField" value="${aSharedProperty}"/>
</bean>
A shorthand to the solution proposed by mrembisz goes like this:
<context:property-placeholder properties-ref="myProperties"/>
<util:properties id="myProperties">
<prop key="aSharedProperty">All beans need me :)</prop>
</util:properties>
You may be able to use the following:
<bean id="abstractParent" abstract="true">
<property name="sharedProperty" value="All child beans need me" />
</bean>
<bean id="bean1" class="MyClass1" parent="abstractParent">
...non-shared properties...
</bean>
<bean id="bean2" class="MyClass2" parent="abstractParent">
...non-shared properties...
</bean>
However, that relies on the property having the same name, so may not be applicable for you.
Something I've used in the past is SpEL to make sure that a bean has the same value as another:
<bean id="myBean" class="xxx.yyy.Foo" >
<property name="myProperty" value="1729" />
</bean>
<bean id="copyCat" class="xxx.yyy.Bar" >
<property name="anotherProperty" value="#{myBean.myProperty}" />
</bean>
I have found this to be particularly useful when setting the value did something other than a simple assignment.

Categories

Resources