Populate spring bean property using annotations only, at run-time - java

I have a bean Parent with just one property attr.
class Parent
{
String attr;
public void doStuff(){
//stuff
}
public String getAttr() {
return attr;
}
public void setAttr(String attr) {
this.attr=attr;
}
}
I have three beans that extend this Parent bean.
My spring.xml looks like this-
<bean id="parent" class="Parent"/>
<bean id="child1" parent="parent">
<property name="attr" value="Sample value 1"/>
</bean>
<bean id="child2" parent="parent">
<property name="attr" value="Sample value 2"/>
</bean>
<bean id="child3" parent="parent">
<property name="attr" value="Sample value 3"/>
</bean>
I want to do the same thing using annotations.
Problem is that I have to do this storefront and all the beans in my controller are declared as -
#Resource
#Qualifier("child1")
Parent child1;
Is there a way I can add the property to the child beans using annotations or any other approach in controller i.e. without using spring.xml?
Is there a way of doing this using the #Value annotation. Problem is that I don't have a static value that comes from a property file. I have 3 different value for 3 different beans.

Shouldn’t this work, if you have three different values in your properties file
see post here
#Value(“${child1.attr}”)
#Value(“${child2.attr}”)
#Value(“${child3.attr}”)

Related

Single JavaConfig class for multiple beans of same type with dependencies

Would it be possible to convert this config to a single #Configuration class? I need to pick the values for Car from property files
<bean name="VW" class="com.app.car">
<property name="cost" value="${vw.cost}"/>
<property name="power" value="${vw.power}"/>
</bean>
<bean name="Merc" class="com.app.car">
<property name="cost" value="${merc.cost}"/>
<property name="power" value="${merc.power}"/>
</bean>
<bean name="FirstCar" class="com.app.cart">
<property name="car" ref="VW"/>
</bean>
<bean name="SecondCar" class="com.app.cart">
<property name="car" ref="Merc"/>
</bean>
I know we can define different classes fro VW and Marc and then refer #Autowire them to a parent #Configuration class. Wondering if there is a solution involving defining all these beans in a single class. I tried using #Value for parameters for devAppConfig as below
vw(#Value("vw.cost") String cost, #Value("vw.power") String power)
merc(#Value("merc.cost") String merc, #Value("merc.power") String power)
But these methods have input parameters. Having 2 different objects of the same type that need to be instantiated with different property values and injected as dependencies is the goal
You can use Spring Profiles, so you can have a property file o bean for each enviroment.
Spring Profiles provide a way to segregate parts of your application
configuration and make it only available in certain environments. Any
#Component or #Configuration can be marked with #Profile to limit when
it is loaded You can see more here
http://www.baeldung.com/spring-profiles
http://www.mkyong.com/spring/spring-profiles-example/
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

What is the meaning of <property> tag in [servlet-name]-servlet.xml of Spring Web MVC?

I got the following bean declearation in my [servlet-name]-servlet.xml of my Dynamic Web Project using Spring Web MVC?
I have read quite a lot of documents but stil couldnt understand what is the purpose of having those property tags?
<bean name="abcController" parent="defController"
class="abcController">
<constructor-arg ref="staticService" />
<property name="commandClass" value="abcCommand" />
<property name="property2" value="search" />
<property name="property3" value="true" />
<property name="formView" value="/someValue" />
</bean>
I know that the property could a field in abcController class, but there is no such a field named formView in abcController class!
Does anyone could help me out?
That xml file is used to create fields without having those fields coded in the file itself.
// This is used to Start the ApplicationContext Container and to get the Bean of AbcCotroller
ApplicationContext context =
new ClassPathXmlApplicationContext("[servlet-name]-servlet.xml");
abcController obj = (abcController) context.getBean("abcController");
You could later on use the beans in your code:
obj.getFormView(); //this will return '/somevalue'
//Bean.java
public class SampleBean{
private String message;
public void setMessage(String message){
this.message=message; //setter injection
}
public void ShowMessage(){
system.out.println("Message"+message);
}
}
//Main.java
Class Main{
public Static Void Main(String args[]){
//TO Start the ApplicationContext container
ApplicationContext applicationcontext = new ClassPathXmlApplicationCOntext("Spring.xml");
//To Read the SampleBean
Object o=applicationcontext .getBean("SampleBean");
SampleBean sampleBean=(SampleBean)o;
//Invoke the Method
sampleBean.ShowMessage();
}
}
//Spring.Xml
// you need to configure some more nameSpace which are required for Spring and Xml
<bean id="sampleBean" class="SampleBean">
<property name="message" value="this is the use of property Tag"/>
</bean>
//output :This is the use or Property Tag
explanation: when we want to perform Setter Injection we go for the Property
Tag
In spring we have some dependency injections like setter,constructor,interface,lookup method injection
when we use the Setter Injection first Dependent class object is create and next the dependency class object is created

Java Spring Injection String

How do I inject a String into a class. I Have seen plenty of examples of how to inject a class but can't find any for a String.
An example: If your field is called "name" and your class is called "Person" you can use setter injection like this:
<bean id="personBean" class="example.Person">
<property name="name" value="Paul" />
</bean>
It should be as simple as that. You will obviously need setter methods in your Person class for name.
Let Spring know where to find your properties file (in this case myProperties.properties):
<!-- Spring will replace ${} keys with values from the file used by the propertyConfigurer -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="location" value="classpath:myProperties.properties"/>
</bean>
In your class, you can inject like this:
#Value("${web.theme}")
private String theme;
In this case, the property defined bye "web.theme" in myProperties.properties will be injected into the "theme" member variable. But you can also inject in the constructor or setter as well.
If you don't want to use annotations, you can use it in your xml file as well.

How can I inject a property value into an annotation configured spring mvc 3.0 controller

First: I'm using Spring 3.0
I have a problem when configuring my controller class. The controller uses a web service which I want to define the endpoint address using a .properties file.
#Controller
public class SupportController {
#Value("#{url.webservice}")
private String wsEndpoint;
...
In my application context xml-file, I've defined this:
<context:property-placeholder location="/WEB-INF/*.properties" />
I've been reading the documentation, trying different approaches (like adding prefix systemProperties.),but I keep getting an error message telling me that it doesn't exist.
Field or property 'url' cannot be
found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
Ok. I've figured it out.
Now, in the controller:
#Value("#{settings['url.webservice']")
Then in the context configuration I have this "helper bean":
<util:properties id="settings"
location="/WEB-INF/supportweb.properties"></util:properties>
This should work, too:
#Value("${url.webservice}")
private String wsEndpoint;
I have this configuration and it works fine:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
and I iniejct the property in this way
#Value("${root.log.level}")
private String prop;
the field is correctly initialized to "DEBUG" value.
you should check that the
<context:property-placeholder location="/WEB-INF/*.properties" />
is defined in webmvc-config.xml where you create instances of the #Controllers

How to modify beans defined in a spring container

I have two xml files defining beans for the springframework (version 2.5.x):
containerBase.xml:
<beans>
<bean id="codebase" class="com.example.CodeBase">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
</list>
</property>
</bean>
</beans>
... and
containerSpecial.xml:
<beans>
<import resource="containerBase.xml" />
</beans>
Now I want to adjust the property sourceCodeLocations of bean codebase within containerSpecial.xml. I need to add a second value src/generated/productive.
A simple approach is to override the definition of codebase in containerSpecial.xml and add both values, the one from containerBase.xml and the new one:
containerSpecial.xml:
<beans>
<import resource="containerBase.xml" />
<bean id="codebase" class="com.example.CodeBase">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
<value>src/generated/productive</value>
</list>
</property>
</bean>
</beans>
Is there a way to extend the list without redefining the bean?
EDIT 2009-10-06:
The purpose of this is to have a shared standard container containerBase that is used by a lot of different projects. Each project can override/extend some properties that are special for that project in its own containerSpecial. If the project doesn't override, it's using the defaults defined in containerBase.
You could use a BeanFactoryPostProcessor to change the bean's metadata before the Spring container instantiates the CodeBase bean. For example:
public class CodebaseOverrider implements BeanFactoryPostProcessor {
private List<String> sourceCodeLocations;
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
CodeBase codebase = (CodeBase)beanFactory.getBean("codebase");
if (sourceCodeLocations != null)
{
codebase.setSourceCodeLocations(sourceCodeLocations);
}
}
public void setSourceCodeLocations(List<String> sourceCodeLocations) {
this.sourceCodeLocations = sourceCodeLocations;
}
}
Then in contextSpecial.xml:
<beans>
<import resource="context1.xml" />
<bean class="com.example.CodebaseOverrider">
<property name="sourceCodeLocations">
<list>
<value>src/handmade/productive</value>
<value>src/generated/productive</value>
</list>
</property>
</bean>
</beans>
Yes. A bean definition can have a "parent" attribute that references a parent bean definition. The new "child" definition inherits most of the properties of the parent and any of those properties can be overridden.
See Bean Definition Inheritance
Also you can use Collection Merging to merge the list property definition from the parent and child bean definitions. This way you can specify some list items in the parent bean definition and add more items to it in the child bean definition.
Is there a way to define the list in a properties or other configuration before hand?
It seems like the app configuration and wiring are tightly coupled. From my experience, if it is hard to do something in Spring, likely there is a different easier way to do it.
3 approaches:
Simple: have two lists defaultSourceCodeLocations and additionalSourceCodeLocations and have your accessor methods check both of these (or combine them). I've seen this done in some frameworks - a default list of handlers is populated then additional user created ones are added...
More complicated but keeps the original class clean: You could then create a CodeBaseModifier class. This would have a init-method to alter an injected instance of the bean.
<bean id="codebaseModifier" class="com.example.CodeBase" init-method="populateCodeBase">
<property name="sourceCodeLocations" ref="codebase"/>
<property name="additionalSourceCodeLocations">
<list>
<value>src/handmade/productive</value>
</list>
</property>
</bean>
If you wanted to make this really generic you could make a bean modifier that would do this by reflection. Be careful of the ordering if use this approach. Dependent beans of CodeBase would have to make sure this class was instantiated first (with depends on)
3 A variation on 2... Instead of directly creating a CodeBase class instead create a factory that returns a populated bean. This factory could then be configured with Spring in a similar fashion to 2. Have a defaultSourceCodeLocations and additionalSourceCodeLocations
Unless you need a lot of extensible properties I would go with option 1.
In Spring 3.0, you can specify merge="true" on the 'list' tag. See http://forum.springsource.org/archive/index.php/t-97501.html for details.

Categories

Resources