Common value configuration in Spring XML - java

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.

Related

How to declare the spring bean during its initialization

I need to do something like this.
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.example.Converter1"/>
<bean class="com.example.Converter2"/>
<bean id="converter3" class="com.example.Converter3"/>
<bean id="converter4" class="com.example.Converter4">
<property name="conversionService" ref="converter3"/>
</bean>
<bean id="converter5" class="com.example.Converter5">
<property name="conversionService" ref="converter4"/>
</bean>
</set>
</property>
</bean>
I want to use converter3 bean into converter4 bean via #Autowired annotation. Can I do this or it is bad way for programming?
Please, help me to solve this problem?
It's not 100% clear what you want, but in case you mean to inject instance of converter3 into converter4 class using #Autowired it's OK.

Is there a way to get all registered message-converters?

I would like to somehow inject all HttpMessageConverter instances registered in Spring-MVC. I can successfully inject all that have been registered via.
private HttpMessageConverter[] converters;
#Autowired
public void setConverters(HttpMessageConverter[] converters) {
this.converters = converters;
}
However this only injects if the converter was registered inside the context (i.e. if defined outside of <annotation-driven>).
I did figure I would try using <beans:ref inside the <annotation-driven><message-converters> but it is not supported in spring-web 3.1.
Is there some class I can inject that may have a property I could use to get converters? Ideally I'd like to see the order in the filter chain they are registered in too.
You are right, the message converters are directly instantiated within the RequestMappingHandlerAdapter registered using the <mvc:annotation-driven/> xml tag, and the message-converters subtag explicitly expect the bean to be defined inline.
However, a workaround is to define the handler adapter and inject in the converters this way:
<bean name="handlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService"></property>
<property name="validator">
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
</bean>
</property>
</bean>
</property>
<property name="messageConverters">
<list>
<ref bean="byteArrayConverter"/>
<ref bean="jaxbConverter"/>
<ref bean="jsonConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
</list>
</property>
</bean>
<bean name="byteArrayConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
<bean name="jaxbConverter" class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean name="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean name="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="useSuffixPatternMatch" value="false"></property>
</bean>
Spring puts all the converters behind an implementation of org.springframework.core.convert.ConversionService . You need to inject an instance of that interface into your class, you can read more in the spring documentation (including an example of how to inject it).
You can try injecting a bean of type RequestMappingHandlerAdapter but depending on your configuration, you might not have an instance!

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>

How to access data in another spring bean using current spring bean

I am new to Spring and I have a small requirement.
<bean name="triangle" class="com.thomson.learn.spring.triangle">
<property name="name" ref="dataSource" />
</bean>
<bean id="dataSource" class="java.lang.String">
<property name="name" value="easy" />
</bean>
I have written beans as shown above. I need to access the value easy from the bean with id="triangle", but when I try doing this I get a exception. Can someone please suggest how to overcome this problem?
Try the following:
<bean name="triangle" class="com.thomson.learn.spring.triangle">
<property name="name" ref="dataSource" />
</bean>
<bean id="dataSource" class="com.thomson.learn.spring.shape">
<property name="name" value="easy" />
</bean>
where com.thomson.learn.spring.triangle and com.thomson.learn.spring.shape must exist as classes in your project. your String class bean couldn't have worked because String has no name property (getName() method getter) to access.
If it is going to be String(s) that you want to inject into all of your beans you can refer properties from a property file and use <context:property-placeholder location="location to .properties"/>
or you can define properties in the configuration xml with <util:properties />
Example for property-placeholder
<bean id="appDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/> // Refered from property file
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="classpath:jdbc.properties"/>
A String does not have a property 'name', so you can't instantiate one the way you are trying to. Moreover, you don't need to, as you can use it directly as the value, e.g.:
<bean name="triangle" class="com.thomson.learn.spring.triangle">
<property name="name" value="easy" />
</bean>
Edit in reply to your comment:
If "name" is of type shape, then you need to inject a shape here...
<bean name="triangle" class="com.thomson.learn.spring.triangle">
<property name="name" ref="shape" />
</bean>
<bean name="shape" class="com.thomson.learn.spring.shape">
<!-- configure properties here -->
</bean>
The objects wired by Spring are supposed to be JavaBeans. What this means in practice is that they have a no-argument constructor and a set of properties, each of which has both a getter and a setter. When you write a definition such as above, Spring uses the setters to set properties you defined in the configuration file.
For instance if Shape was a class as such:
package com.thomson.learn.spring.Shape;
class Shape {
private String name;
public Shape() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Then you could wire it with the following:
<bean id="myShape" class="com.thomson.learn.spring.Shape">
<property name="name" value="blah" />
</bean>
Which really translates to Spring executing the following at runtime:
Shape myShape = new Shape();
shape.setName("blah");
That's all there is to it, except that properties can also be more complex instances of other classes of course, which is why you can use ref to refer to another bean for a property.
P.S.: Spring can use reflection to inject values in many cases, so it doesn't actually need a setter, but most people implement their beans this way for various reasons.

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