BeanInstantiationException:Cannot convert type from java.lang.String to required type --- idref tag - spring

I am new to spring and trying to understand the functionality of the idref tag
My config file is pasted here:
<bean id="AudioSystembean" class="com.springexample.AudioSystem">
<property name="price" value="200"/>
</bean>
<bean id="Vehicle1" class="com.SpringExample.Vehicle1">
<property name="vehicleType" value="CAR" />
<property name="audioSystem" >
<idref bean = "AudioSystembean" />
</property>
</bean>
When I am executing the code I am getting the error as : "BeanInstantiationException:Cannot convert type from java.lang.String to required type :com.SpringExampl.AudioSystem" [I dont remember the exact exception - I have the code at home]
If I use ref instead of idref it is working fine.
I tried google to understand about idref but could not get much information..
What am I doing wrong here?

In a Spring context, <idref> is used to pass the name of the referenced bean, rather than the bean itself (which is what <ref> does). So in your example:
<property name="audioSystem" >
<idref bean = "AudioSystembean" />
</property>
The audioSystem system property will be injected with the name of the AudioSystembean, i.e. the String "AudioSystembean".
This is not what you need here, though, you need the <ref> element, which passes a reference to the bean itself.

Related

Spring - how to reference another property within the same bean?

I have the following definition in my configuration:
<bean class="com.project.TimerBean">
<property name="delay" value="30000" />
<property name="interval" value="60000" />
<property name="invokeThis" value="com.project.TargetClass" />
<property name="receiver" value="XYZ" />
<property name="args" value="#{interval}" />
</bean>
I would like to set the value of args to the same value as interval (in this case, 60000) without having to hard-code the value. However, the above snippet doesn't seem to work. How should I change this?
# syntax (Spel Expressions) are supposed to work the way you wrote it. You need to replace
#{interval} to #{beanId.interval}.
For example, if the id of the bean you are creating is timerBean, #{timerBean.interval} is supposed to work. You cannot refer to a property directly even if it is a part of the bean definition.
It only works if the property you are referring to is a part of another bean.
<bean id="beanA" class="org.BeanA">
<property name="prop1" value="1000" />
</bean>
<bean id="beanB" class="org.BeanB">
<property name="prop2" value = "#{beanA.prop1}" />
<property name="prop3" value = "#{beanB.prop2}" />
</bean>
In the above example, prop2 gets initialised from prop1 correctly. But prop3 gets initialised to null.
If you look at AbstractAutowireCapableBeanFactory class and method,
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs)
you can see that all the property values in a single bean definition are looped over and values are parsed. After all the values have been successfully parsed, only then they are set on the bean instance. In the above beanA and beanB example when prop3's value is getting parsed, spring looks for the value of prop2 on beanB which is not yet set and hence returns null.
AFAIK, there is no way around this except the way suggested by #Alex
PS: I am using spring version 4.1.6.RELEASE
Move interval value "60000" to the property file
yourVariableName = 60000
and change to:
<property name="interval" value="${yourVariableName}" />
<property name="args" value="${yourVariableName}" />

Dependency Injection returned results of bean init-method

I have two simple beans. In the first bean it calls a init-method and return string value.
Now I want to this returned string from first bean init-method , inject to my second bean
helloWorldBean3 property newKey. Please advise me on how to implement this requirement.
<bean id="helloWorldBean2" init-method="loadKey"
class="com.java.snippets.enterprise.services.HelloWorld2">
<property name="key" value="${key.supportiveFile}" />
<bean id="helloWorldBean3"
class="com.java.snippets.enterprise.services.HelloWorld">
<property name="newKey" ref="???" />
</bean>
Try using Spring EL like so:
<bean id="helloWorldBean3"
class="com.java.snippets.enterprise.services.HelloWorld">
<property name="newKey" value=""#{helloWorldBean2.loadKey()}"" />
</bean>

custom thymeleaf dialect registration causing exception

in applicationContext.xml
<bean id="templateEngine"
class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="org.test.custom.CustomDialact" />
</set>
</property>
</bean>
Stacktrace:
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'additionalDialects' of bean class [org.thymeleaf.spring3.SpringTemplateEngine]: Bean property 'additionalDialects' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1042)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:902)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:57)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1424)
... 50 more
i don't know but it was fixed after restarting machine. but mean while i find another solution
by extend a custom class with HashSet and in constructor add custom dialect in it and declare it in xml. provide it reference to additionalDialects . thats it .it will start running . it think it is problem related to generics as spring sometimes supply empty type
like HashSet<V> .

Spring DI : session vise object creation using aop proxy for inherited class

In my project i have used struts2 and spring. Spring is used just for DI. I am having all my actions created by sessions and so as model beans via spring DI. Now I want to use inheritance for my class which will be generated through aop based proxy and it will be per session. Coding goes as below.
<bean id="common.EshopDefaultAction" class="com.common.actions.EshopDefaultAction" scope="session" >
<property name="site" ref="master.site" />
<property name="menu" ref="master.menu" />
<property name="indexDAO" ref="common.indexDAO" />
<property name="categoryDAO" ref="master.categoryDAO" />
<property name="productDAO" ref="master.productDAO" />
</bean>
<bean id="common.IndexAction" parent="common.EshopDefaultAction" class="com.common.actions.IndexAction" scope="session">
<property name="indexInfo" ref="common.indexInfo" />
<aop:scoped-proxy />
</bean>
both actions are having pairs of setters and getters.
I want to have site,menu, indexDAO, categoryDAO, productDAO objects created by session for all of its child like IndexAction just shown above. Right now it creates different objects for EshopDefaultAction and IndexAction.
Adding <aop:scoped-proxy /> to EshopDefaultAction bean definition gives error like
Invalid property 'targetBeanName' of bean class [com.common.actions.IndexAction]:
Bean property 'targetBeanName' is not writable or has an invalid setter method.
Does the parameter type of the setter match the return type of the getter?

char[] to String Conversion in Spring configuration

I have bean A that returns an attribute as char[] and another bean that expects an attribute as String and I would like to inject the attribute from bean A to bean B.
When I do this:
<bean id="B" class="....">
<property name="password" value="#{A.password}" />
</bean>
<bean id="A" class="...">
</bean>
The error I'm getting is:
Cannot convert value of type [char[]] to required type [java.lang.String] for property 'password': no matching editors or conversion strategy found
Any idea how to resolve this?
Perhaps by using an expression language syntax?
Perhaps by registering some sort of a converter like org.springframework.beans.propertyeditors.CharArrayPropertyEditor in the configuration before injecting the char[] attribute?
Looks like this will work:
<property name="password" value="#{new java.lang.String(A.password)}" />

Resources