Spring problems injecting Clock as a constructor argument - java

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” />

Related

Ambiguity of constructor arguments in Spring

I've got an error saying about type ambiguity:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'blankRestoreFromRecycleUiOperation' defined in URL: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)
Here is my spring xml mapping:
<bean id="blankRestoreFromRecycleUiOperation" class="BlankRestoreFromRecycleUiOperation">
<constructor-arg index="0" value="blankTab"/>
<constructor-arg index="1" value="false"/>
</bean>
My java class:
public class BlankRestoreFromRecycleUiOperation implements RestoreFromRecycleUiOperationAware {
private String tab;
private boolean green;
public BlankRestoreFromRecycleUiOperation(String tab, boolean green) {
this.tab = tab;
this.green = green;
}
}
So, the other similar questions says about proper constructor arguments indexing and naming but here I guess I missed something else. Also before posting I tried adding arguments type like this:
<bean id="blankRestoreFromRecycleUiOperation" class="BlankRestoreFromRecycleUiOperation">
<constructor-arg index="0" type="java.lang.String" value="blankTab"/>
<constructor-arg index="1" type="boolean" value="false"/>
</bean>
Then got the same error.
Could you specify either the correct way to do so or missing parts? Thanks for your answers in advance.
Solved: the problem was related to IDE and gradle versions. There was 2 separated and different versions of Spring caused whole app work wrong. Anyway thanks for your answers.
try this:
<bean id="blankRestoreFromRecycleUiOperation" class="ua.com.profitsoft.bo.report.mtsbu.ui.operation.impl.BlankRestoreFromRecycleUiOperation">
<constructor-arg type="java.lang.String">
<value>blankTab</value>
</constructor-arg>
<constructor-arg type="boolean">
<value>true</value>
</constructor-arg>
</bean>
just try in your XML mapping in class = "com.jwt.spring.BlankRestoreFromRecycleUiOperation">
maybe it helps because this type of error are called injection type ambiguities.
I hope it will help.

Spring Context: It's possible to define variables (not properties) in a XML and use it in runtime to obtain specific referenced beans?

I don't have much experience working with Spring Context and I don't know if this is possible...I'm trying to set into a Spring XML file a variable to define a bean reference (not a property).
Now I have a specidific xml:
keyIntegrator-key1.xml
<import resource="classpath:/events/key-events.xml" />
<context:annotation-config />
<bean id="keyIntegrator" class="com.emulated.KeySimulator" >
<property name="readList">
<list>
<bean class="com.emulated.ListEventGenerator">
<property name="eventList">
<ref bean="key-1-ok"/>
</property>
</bean>
</list>
</property>
</bean>
All the keys were defined in another xml file (key-events.xml).
I have to load in Java runtime the bean "keyIntegrator" with only one key, that is a input parameter in the Java program (I use the param to decide the xml file to load)
My question is if it's possible to define a variable inside the xml file and get the referenced bean using this variable:
Something like this:
keyIntegrator-generic.xml
<import resource="classpath:/events/key-events.xml" />
<context:annotation-config />
<bean id="keyIntegrator" class="com.emulated.KeySimulator" >
<property name="readList">
<list>
<bean class="com.emulated.ListEventGenerator">
<property name="eventList">
<ref bean="key-{inputKeyParam}-ok"/>
</property>
</bean>
</list>
</property>
</bean>
In the Java program I will need to pass the param to get the bean, something like this:
keySimulatorBean = (KeySimulator) context.getBean("keyIntegrator", "1");
There any way possible to make this ?
Thank you very much!
Thank you very much, it worked for me :)
I setted the system property value in the Java code:
System.setProperty("inputKeyParam", "1");
It is possible to do using Spring Expression Language.
For example reference to the bean can be defined using system property
<ref bean="key-#{systemProperties.inputKeyParam}-ok"/>
It will allow to reference different beans depending on provided VM option value, e.g. -DinputKeyParam=1

Conditional initialization of classes in spring

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.

Spring bean property define

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.

How do I create a spring bean for a Java double primitive?

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
}

Categories

Resources