I have two class A and B . A is parent and B is child class.
am calling the class B methods.but class b accessing the methods of A.and i want to set a property in class A. So defined the property like
<bean name="b" class="com.dao.B" parent="parent">
<property name="utility" ref="utility"/>
</bean>
<bean class="com.dao.A" id="parent">
<property name="utility" ref="utility"/>
</bean>
and in the class A have a property named utility and with a setter...
when i try to get the instance i got null...
can u help me to set that
As A has a public setter of field utility then you can directly set property of object in class A from B like.
<bean name="b" class="com.dao.B">
<property name="utility" ref="utility"/>
</bean>
here utility is in class A with public setter and we are set value in B bean.
Do not use parent attribute, try this
<bean id="b" class="com.dao.B" >
<property name="utility" ref="utility"/>
</bean>
<bean id="a" class="com.dao.A">
<property name="utility" ref="utility"/>
</bean>
Is A a parent (in spring means) of B?
If not, just remove parent="parent" and id="parent" and you will be fine.
Read spring docs about abstract beans definition and use of parent.
Related
I have a class that takes a java.time.Clock object as a constructor argument.
I am having problems defining this as a bean in the applicationContext.xml file:
TimeTracker.java
public class TimeTracker{
public final Clock clock;
public TimeTracker(Clock clock){
this.clock = clock;
}
applicationContext.xml
<bean id="timeTracker"
class="com.tracker.TimeTracker">
<constructor-arg type="java.time.Clock" value=""/>
</bean>
The error I am having is: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
Try it like this:
<bean class=“java.time.Clock” factory-method=“java.time.Clock.systemDefaultZone” name=“clock”/>
<bean id="timeTracker"
class="com.tracker.TimeTracker">
<constructor-arg ref=“clock”/>
</bean>
The value attribute is for primitive types only.
You need to instantiate a clock and use it as a reference. Something similar to:
<bean id="clock" class="java.time.clock"/>
<bean id="timeTracker"
class="com.tracker.TimeTracker">
<constructor-arg type="java.time.Clock" ref="clock"/>
</bean>
Try,
<bean id="timeTracker" class="com.tracker.TimeTracker">
<constructor-arg>
<bean class="java.time.Clock" factory-method="java.time.Clock.systemUTC" />
</constructor-arg>
</bean>
The solution from Strelok nearly works but it failed for me as you do not need to define the full path of the factory method. It is relative to the factory Class so if you type factory-method=“java.time.Clock.systemDefaultZone” it will look for a method in java.time.Clock.java.time.Clock.systemDefaultZone().
<bean id="systemClock" class="java.time.Clock" factory-method="systemUTC" />
<bean id="timeTracker" class="com.tracker.TimeTracker">
<constructor-arg type="java.time.Clock" ref="systemClock"/>
</bean>
To makes things worse the Spring exception is not especially helpful.
Strelok's answer almost works, it should be -
<bean name=“clock” class=“java.time.Clock” factory-method=“systemDefaultZone” />
I have a service which refers to a single source.
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref="DataSource1" />
</bean>
<bean id="DataSource1" class="com.source.impl.DataSource1">
<constructor-arg ref="DBDataSource"/>
<constructor-arg value="xyz"/>
</bean>
<bean id="DataSource2" class="com.source.impl.DataSource2">
<constructor-arg ref="MsgDataSource"/>
<constructor-arg value="xyz"/>
</bean>
Now if i want to perform a conditional check and my service should be able listen to particular source based on a input variable something like below.
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref=" $VARIABLE == true ? DataSource1 : DataSource2" />
</bean>
I did tried SPEL however no luck. I am beginner in spring. Any help will be appreciated.
Thanks.
There are many solutions. Here are two: You can use profiles for this. Define two profiles, define the DataSource beans with the same name but different profiles. (docs)
Alternatively, you can use a single bean and a static factory method (docs).
<bean id="DataSource" class="com.source.impl.DataSourceFactory"
factory-method="createInstance"/>
Inside of DataSourceFactory.createInstance(), you can check the flag and then create the correct data source in plain Java.
The latter is a bit easier to understand, IMO. Using profiles allows you to keep everything in XML (but you should really consider switching to the Java Configuration). The drawback with profiles is that you must not forget to activate at least one of the bean won't be defined.
A third option is to use three XML files and then modify the list of XML files that should be parsed when you pass it to the ApplicationContext. But that only works if you have control over this part of the code.
Assuming you are using Spring 3.1 or later, Spring Profiles may be the best solution.
Using the example of Production and Dev/QA environments, common bean declarations go in a shared file
<beans>
<bean id="XYZService" class="com.services.impl.DataService1">
<constructor-arg ref="DataSource" />
</bean>
</beans>
A separate configuration contains production references
<beans profiles="prod">
<bean id="DataSource" class="com.source.impl.DataSource1">
<constructor-arg ref="DBDataSource"/>
<constructor-arg value="xyz"/>
</bean>
</beans>
Another contains dev references
<beans profile="dev">
<bean id="DataSource" class="com.source.impl.DataSource2">
<constructor-arg ref="MsgDataSource"/>
<constructor-arg value="xyz"/>
</bean>
</beans>
To activate the given profile add -Dspring.profiles.active=prod to your JVM arguments
You can find more info here
Another approach uses factory methods.
<bean id="DataSource" class="com.source.impl.DataSourceFactory" factory-method="getInstance">
<constructor-arg value="#{VARIABLE}" />
</bean>
The above fragment assumes that you want your factory method to explcitly invoke the constructor of each of your services. If you dead set on using Spring to create the instances you can pass each datasource implementation as constructor arguments and use the constructor method as a simple dispatcher.
You need something like this:
<constructor-arg
ref="#{systemProperties.variable == 'true' ? 'DataSource1' : 'DataSource2'}" />
where "variable" is set like -Dvariable=true.
In my Spring-Module.xml I have two beans:
<bean id="two_num" class="main.java.com.shen.Generator">
<property name="length" value="8" />
<property name="categories" value="3" />
...
</bean>
<bean id="six_num" class="main.java.com.shen.Generator">
<property name="length" value="6" />
<property name="categories" value="1" />
<property name="numeric" value="numeric" />
...
</bean>
And I instantiate my class like so:
ApplicationContext context = new ClassPathXmlApplicationContext("Spring-Module.xml");
Generator obj = (Generator) context.getBean("two_num");
For some reasons, java is always instantiating my second bean despite me explicitly saying that I want the bean "two_num". If I were to flip the order around, and have "six_num"'s bean above "two_num", it would get the bottom bean. :| What's going on? I'm so confused. Is my method for selecting a specific bean wrong?
EDIT: after adding one more bean to it this is what I get when I run my program:
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#e949f69: defining beans [two_num,six_num,four_num]; root of factory hierarchy
And as expected, when I call a print method in my class, I can see that the current object is instantiated with the information dicated in four_num, and not "two_num"
Certainly remove static modifiers on your fields, as already suggested.
Also, if you want 'singletons' modify your XML:
<bean id="two_num" class="main.java.com.shen.Generator" scope="singleton">
<property name="length" value="8" />
<property name="categories" value="3" />
...
</bean>
So you'll only get a single instance of each bean. You'll still get multiple instances of Generator, but only one per bean.
Based on comments, I can only assume that the Generator class looks something like this
public class Generator {
private static length;
private static categories;
//getters/setters
}
Given that i dont have a full class to work with, i can only recommend removing the static modifier as it would contradict the way you want to use the class.
here is some code from a post here that would explain my question:
Interface:
package org.better.place
public interface SuperDuperInterface{
public void saveWorld();
}
Implementation:
package org.better.place
import org.springframework.stereotype
public class SuperDuperClass implements SuperDuperInterface{
public void saveWorld(){
System.out.println("Done");
}
}
Client:
package org.better.place
import org.springframework.beans.factory.annotation.Autowire;
public class SuperDuperService{
private SuperDuperInterface superDuper;
public void doIt(){
superDuper.saveWorld();
}
public void setSuperDuper(SuperDuperInterface superDuper) {
this.superDuper = superDuper;
}
}
My question is - how can I configure the beans in the spring config? I don't want to use #Autowired and other annotations.
I guess it will be something like this:
<bean id="superService" class="org.better.place.SuperDuperService">
<property name="superDuper" ref="superWorker"
</bean>
<bean id="superWorker" class=?????? parent=???????? >
</bean>
You will have to instantiate the implementing class, of course:
<bean id="superWorker" class="org.better.place.SuperDuperClass"/>
You would only need the parent attribute if you wanted to create multiple beans with common properties that you don't want to repeatedly declare, so you move it to an abstract parent bean definition that the concrete bean definitions can reference.
Assuming the SuperDuperClass has some properties:
<bean id="superWorkerPrototype" abstract="true"
class="org.better.place.SuperDuperClass">
<property name="prop1" value="value1"/>
<property name="prop2" value="value2"/>
</bean>
<bean id="superWorker1" parent="superWorkerPrototype"
class="org.better.place.SuperDuperClass">
<property name="prop3" value="foo"/>
</bean>
<bean id="superWorker2" parent="superWorkerPrototype"
class="org.better.place.SuperDuperClass">
<property name="prop3" value="bar"/>
</bean>
Which would result in both instances having the same values for prop1 and prop2, but different ones for prop3.
You can just give the implementation class's fully qualified name, and its not required to give parent attribute. Spring will automatically find if it can assign an instance of SuperDuperClass to the superDuper field of SuperDuperService
<bean id="superWorker" class="org.better.place.SuperDuperClass" >
</bean>
I'd like to create a spring bean that holds the value of a double. Something like:
<bean id="doubleValue" value="3.7"/>
Declare it like this:
<bean id="doubleValue" class="java.lang.Double">
<constructor-arg index="0" value="3.7"/>
</bean>
And use like this:
<bean id="someOtherBean" ...>
<property name="value" ref="doubleValue"/>
</bean>
It's also worth noting that depending on your need defining your own bean may not be the best bet for you.
<util:constant static-field="org.example.Constants.FOO"/>
is a good way to access a constant value stored in a class and default binders also work very well for conversions e.g.
<bean class="Foo" p:doubleValue="123.00"/>
I've found myself replacing many of my beans in this manner, coupled with a properties file defining my values (for reuse purposes). What used to look like this
<bean id="d1" class="java.lang.Double">
<constructor-arg value="3.7"/>
</bean>
<bean id="foo" class="Foo">
<property name="doubleVal" ref="d1"/>
</bean>
gets refactored into this:
<bean
id="propertyFile"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:my.properties"
/>
<bean id="foo" class="Foo" p:doubleVal="${d1}"/>
Why don't you just use a Double? any reason?
Spring 2.5+
You can define bean like this in Java config:
#Configuration
public class BeanConfig {
#Bean
public Double doubleBean(){
return new Double(3.7);
}
}
You can use this bean like this in your program:
#Autowired
Double doubleBean;
public void printDouble(){
System.out.println(doubleBean); //sample usage
}