Question

I have two beans, SimpleBean and ArgumentBean, I am trying to wire beans through factory method and trying to replace the bean in same bean definition ( I know its pretty bad idea to do so, but I am just doing an experiment)

i.e. I have below factory Utilities class:

    public class FactoryClassUtils {

    public static ArgumentBean getArgumentBean(String firstArg, int secondArg) {
        return new ArgumentBean(firstArg, secondArg);
    }

    public static SimpleBean getSimpleBean(ArgumentBean firstArg, int secondArg) {
        return new SimpleBean(firstArg, secondArg);
    }

    }

and below mentioned Configuration has been specified in the spring config xml:

        <bean name="argumentBean" class="com.view.spring.factory.factoryclasses.FactoryClassUtils"
        factory-method="getArgumentBean">
        <constructor-arg type="java.lang.String" index="0" value="Hey All!!!" />
         <constructor-arg type="int" index="1" value="20" />
    </bean>

    <bean name="simpleBean"
        class="com.view.spring.factory.factoryclasses.FactoryClassUtils"factory-method="getSimpleBean">
        <constructor-arg>
        <bean class="com.tcs.view.spring.dataobjects.ArgumentBean"/>
        </constructor-arg>
        <constructor-arg type="int" value="20" />
        <property name="argumentBean" ref="argumentBean" /> 
    </bean> 

I am getting this error when I am executing above:

    Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'argumentBean' of bean class [com.view.spring.dataobjects.SimpleBean]: Bean property 'argumentBean' 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:805)
    at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:655)

Its worth mentioning that all the getters and setters are present in both of the beans. SimpleBean.java has a property of Type ArgumentBean.java.

Definition of Simple Bean is :

 package com.view.spring.dataobjects;
 public class SimpleBean {
    private ArgumentBean argumentBean;
    int argumentCount;

    public ArgumentBean getArgument() {
        return argumentBean;
    }

    public void setArgument(ArgumentBean argumentBean) {
        this.argumentBean= argumentBean;
    }

    public int getArgumentCount() {
        return argumentCount;
    }

    public void setArgumentCount(int argumentCount) {
        this.argumentCount = argumentCount;
    }

    public SimpleBean(ArgumentBean argument, int argumentCount) {
        this.argumentBean= argument;
        this.argumentCount = argumentCount;
    }

    public void letHimSay() {
        argumentBean.saySomething();
        System.out.println(this.argumentCount);
    }
}

and definition of ArgumentBean is:

package com.view.spring.dataobjects;

public class ArgumentBean {

    private String sayString;
    private int anotherArg;

    public ArgumentBean(String sayString, int anotherArg) {
        this.sayString = sayString;
        this.anotherArg = anotherArg;
    }
    public ArgumentBean(String sayString, Integer anotherArg) {
        this.sayString = sayString;
        this.anotherArg = anotherArg.intValue();
    }

    public ArgumentBean() {

    }

    public void saySomething() {
        System.out.println("We say: "+this.sayString);
        System.out.println(this.anotherArg+" times");
    }
}

I don't get any error if I remove property tag from simpleBean definition. This tag is not working with factory methods, but works well when tried with constructor arguments. Can someone please help me in understanding this situation?

Was it helpful?

Solution 2

Thanks everyone for devoting your time and providing help to me. Problem is solved. Issue was with my code. The bean name in SimpleBean.java is argument rather than argumentBean. I was referring to the variable name, but should go with getter name except 'get' suffix(with first letter smallcase of course). I changed the config to below: < property name="argument" ref="argumentBean" /> and it solved the problem.

OTHER TIPS

You need to add a setter method for argumentBean in your FactoryClassUtils class

   public class FactoryClassUtils {

    private ArgumentBean argumentBean = null;

    public static ArgumentBean getArgumentBean(String firstArg, int secondArg) {
        return new ArgumentBean(firstArg, secondArg);
    }

    public static SimpleBean getSimpleBean(ArgumentBean firstArg, int secondArg) {
        return new SimpleBean(firstArg, secondArg);
    }

    public void setArgumentBean(Argumentbean argumentBean){
    this.argumentBean = argumentBean;    
    }

}

This is needed since you have defined the argumentbean as a property of FactoryClassUtils in your xml

<bean name="simpleBean"
    class="com.view.spring.factory.factoryclasses.FactoryClassUtils"factory-method="getSimpleBean">
    <constructor-arg>
    <bean class="com.tcs.view.spring.dataobjects.ArgumentBean"/>
    </constructor-arg>
    <constructor-arg type="int" value="20" />
    <property name="argumentBean" ref="argumentBean" /> 

It is always good to put setter and getter methods for the property following Java naming convention

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top