0

I'm learning Spring only using the documentation. I got confused when idref came into picture. My understanding is in order to define a property in a bean we need to use the "property" tag with "name" and "value" attributes. "name" should be exactly the name we give for the property in the POJO and "value" can be any primitive datatype. If we need to map it to a separate bean then we should use the "ref" attribute instead. This "ref" attribute must hold the "id" of the bean we refer to.

Now as per the documentation we have a snippet that shows "value" attribute referring to another bean. The documentation recommends the use of "idref" instead. When I tried this real time , I get the following exception.

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'theClientBean' defined in class path resource [ConstructorInjectionDemo.xml]: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'com.javagrasp.dependencies.TheTargetBean' for property 'targetName'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.javagrasp.dependencies.TheTargetBean] for property 'targetName': no matching editors or conversion strategy found

Bean Definition:

<bean id="theTargetBean" class="com.javagrasp.dependencies.TheTargetBean"/>

<bean id="theClientBean" class="com.javagrasp.dependencies.TheClientBean">
<property name="targetName">
    <idref bean="theTargetBean" />
</property>
</bean>

Class details:

ClientBean class:

public class TheClientBean  {

private TheTargetBean targetName;

public void setTargetName(TheTargetBean targetName) {
    this.targetName = targetName;
}
}

TargetBean Class:

package com.javagrasp.dependencies;
public class TheTargetBean {

}

Also:

What does the below line means , do I need to name the property always in some convention ?

17:44:22.270 [main] DEBUG org.springframework.beans.BeanUtils - No property editor [com.javagrasp.dependencies.TheTargetBeanEditor] found for type com.javagrasp.dependencies.TheTargetBean according to 'Editor' suffix convention
Vinodh Thiagarajan
  • 758
  • 3
  • 9
  • 19
  • 1
    http://stackoverflow.com/questions/1767831/ref-vs-idref-attributes-in-spring-bean-declaration . Please refer this. – ArunM Apr 22 '15 at 05:19

2 Answers2

0

Since IdRef passes the name of the bean your bean should like this

public class TheClientBean  {

    private String targetName;

   //Name of the Bean is passed here.
    public void setTargetName(String targetName) {
      this.targetName = targetName;
   }
}
ArunM
  • 2,274
  • 3
  • 25
  • 47
0

"idref" is completely different from "ref" . It is easy to get confused . I thought this is best explained with an example rather than lines and lines of text .

Consider any two classes with ONLY String as properties { NOT REFERENCES}

package com.imran.beanwrapper;

public class IdrefOne {

String first;

public String getFirst() {
    return first;
}

public void setFirst(String first) {
    this.first = first;
}

}

package com.imran.beanwrapper;

public class IdrefTwo {

String second;

public String getSecond() {
    return second;
}

public void setSecond(String second) {
    this.second = second;
}

}

xml:

<bean id="one" 
class="com.imran.beanwrapper.IdrefOne">
<property name="first" value="hai first"/>
</bean>

<bean id="two" 
class="com.imran.beanwrapper.IdrefTwo">

<property name="second">
<idref bean="one"/>
</property>
</bean>

</beans>

Main class : 
ApplicationContext context=new 

ClassPathXmlApplicationContext
("wrapperTest.xml");
    
IdrefOne 
one=context.getBean("one",IdrefOne.class);
    
IdrefTwo 
two=context.getBean("two",IdrefTwo.class);
    
System.out.println(one.getFirst());
System.out.println(two.getSecond());

ouput:

hai first

one


Did u notice the output of System.out.println(two.getSecond()) ?

one
which is equal to "id value" of the first bean namely com.imran.beanwrapper.IdrefOne ( Not equal to bean itself or string value of dependency of bean. Avoid confusion)

Note that the both classes (IdrefOne , IdrefTwo )must have string as dependencies not Object subclasses as dependencies i.e, reference classes

If in the above code if our pojo classes have Object subclasses as dependencies the above code will end up with an exception

Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.imran.beanwrapper.IdrefOne' for property '': no matching editors or conversion strategy found

So, we can conclude for the above code setup with strings as dependencies for the pojo classes IdrefOne , IdrefTwo. The code

<property name="second">
<idref bean="one"/>
</property>

produces same results as the following code

<property name="second" value="one">
</property>

With first XML snippet using 'idref' , if a bean named "one" is not found in the container an exception is thrown. With second xml snippet , u can give Any String value as u want to 'value' attribute . So the question is why not use the regular "value" which is generally used and avoid all the this confusion ?

Answer is in the spring documentation: https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html#beans-idref-element

The first form is preferable to the second, because using the 'idref' tag allows the container to validate at deployment time that the referenced, named bean actually exists. In the second variation, no validation is performed on the value that is passed to the targetName property of the client bean. Typos are only discovered (with most likely fatal results) when the client bean is actually instantiated. If the client bean is a prototype bean, this typo and the resulting exception may only be discovered long after the container is deployed.

A common place (at least in versions earlier than Spring 2.0) where the 'idref' element brings value is in the configuration of AOP interceptors in a ProxyFactoryBean bean definition. Using 'idref' elements when you specify the interceptor names prevents you from misspelling an interceptor id.