Announcement Announcement Module
Collapse
No announcement yet.
Multiple Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multiple

    Hi All

    I have been working for a day or so trying to get Spring (using version 1.2.2) to create a java.util.List. I have set up a bean using ListFactoryBean but it doesn't have the behaviour that I expected. (I have modified my code examples so that you don't need to know the context of the application I am working on.)

    Code:
    <bean id="colours" class="org.springframework.beans.factory.config.ListFactoryBean">
    	<property name="sourceList"> 
        		<list>
    			<value>red</value>
        		</list>
    	</property>
    </bean>
    When I create this bean and inject it into another bean it works fine: Spring creates a List containing a single String. If I modify the XML slightly to add a couple more values to the list...

    Code:
    <bean id="colours" class="org.springframework.beans.factory.config.ListFactoryBean">
    	<property name="sourceList"> 
        		<list>
    			<value>red</value>
    			<value>green</value>
    			<value>blue</value>
        		</list>
    	</property>
    </bean>
    ...I still have valid XML (having looked at the DTD). When I try to inject this bean, I get a NoSuchMethodException. What is the signature of the method Spring is trying to call on the bean that I am trying to inject this bean into? It is not a method that takes a java.util.List as I have that and it doesn't find it.

    I have tried to find other threads on this and the closest I have come is this one from last year: http://forum.springframework.org/showthread.php?t=10510 This thread makes a couple of suggestions that I have tried out and did not work. (They also cause NoSuchMethodExceptions)

    My example above is mentioned and that didn't work. Also this approach...

    Code:
    <value>CVB,CVP</value>
    ... is said to create a List of size 2. It doesn't. It creates a list with a single String whose value is "CVB,CVP". What does work is if I change the method signature of the setter on my bean from

    Code:
    public void setColourList(List colours)
    ... to...

    Code:
    public void setColourList(String [] colours)
    I get an array of size 2, with the String tokenized on the comma.

    Is this a bug or am I using Spring badly? My current solution is to have a <list> with a single <value> which is comma seperated string - rather ungainly when you have 10 values - passed into a method taking a String [], which I then convert to a List using java.util.Arrays.asList().

    Just for completeness, here is the stack trace I get

    Code:
    java.lang.NoSuchMethodException: setColourList
            at java.lang.Class.findMethod(Ljava.lang.String;[Ljava.lang.Class;I)Ljav
    a.lang.reflect.Method;(Unknown Source)
            at java.lang.Class.getMethod(Ljava.lang.String;[Ljava.lang.Class;I)Ljava
    .lang.reflect.Method;(Unknown Source)
            at org.springframework.util.MethodInvoker.prepare()V(MethodInvoker.java:
    180)
            at org.springframework.beans.factory.config.MethodInvokingFactoryBean.af
    terPropertiesSet()V(MethodInvokingFactoryBean.java:111)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBean
    Factory.invokeInitMethods(Ljava.lang.String;Ljava.lang.Object;Lorg.springframewo
    rk.beans.factory.support.RootBeanDefinition;)V(AbstractAutowireCapableBeanFactor
    y.java:966)
            at org.springframework.beans.factory.support.AbstractAutowireCapableBean
    Factory.createBean(Ljava.lang.String;Lorg.springframework.beans.factory.support.
    RootBeanDefinition;[Ljava.lang.Object;)Ljava.lang.Object;(AbstractAutowireCapabl
    eBeanFactory.java:358)
            at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
    (Ljava.lang.String;Ljava.lang.Class;[Ljava.lang.Object;)Ljava.lang.Object;(Abstr
    actBeanFactory.java:226)
            at org.springframework.beans.factory.support.AbstractBeanFactory.getBean
    (Ljava.lang.String;)Ljava.lang.Object;(AbstractBeanFactory.java:147)
            at org.springframework.beans.factory.support.DefaultListableBeanFactory.
    preInstantiateSingletons()V(DefaultListableBeanFactory.java:270)
            at org.springframework.context.support.AbstractApplicationContext.refres
    h()V(AbstractApplicationContext.java:312)
            at org.springframework.web.context.support.AbstractRefreshableWebApplica
    tionContext.refresh()V(AbstractRefreshableWebApplicationContext.java:134)
            at org.springframework.web.servlet.FrameworkServlet.createWebApplication
    Context(Lorg.springframework.web.context.WebApplicationContext;)Lorg.springframe
    work.web.context.WebApplicationContext;(FrameworkServlet.java:305)
            at org.springframework.web.servlet.FrameworkServlet.initWebApplicationCo
    ntext()Lorg.springframework.web.context.WebApplicationContext;(FrameworkServlet.
    java:250)
            at org.springframework.web.servlet.FrameworkServlet.initServletBean()V(F
    rameworkServlet.java:219)
            at org.springframework.web.servlet.HttpServletBean.init()V(HttpServletBe
    an.java:111)
            at javax.servlet.GenericServlet.init(Ljavax.servlet.ServletConfig;)V(Gen
    ericServlet.java:258)
    Your thoughts and experiences appreciated.
    Marcel
    Last edited by robyn; May 14th, 2006, 05:12 PM.

  • #2
    The 1st case you're describing sounds perfectly fine. I have such cases and they work w/o problem. Can you provide more context? "colours" bean injection, target's class definition (the one that defines setColorList(List)) in a little more details. Also, it looks like (in the stack trace) that exception happens in the bean init method. Does your bean definition provide one? Does your class implement InitializingBean?

    Comment


    • #3
      Thanks for your reply. I hope you don't mind me simplfying my examples to this extent - I don't think, given the nature of the project I am working on (security considerations etc), I should be posting source code verbatim.

      The list is a List of Strings, as per my last post. In the application, they are to be displayed in a drop down list on a webpage.

      The class that the list is being injected into is actually a straight bean - instance fields with getters and setters for each - with a static field of type List. There is really nothing special about it. I use a MethodInvokingBean to inject the list.

      Code:
      <bean id="ColoursSetter" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
      	<property name="targetClass"><value>com.foo.bean</value></property>
      	<property name="targetMethod"><value>setColoursList</value></property>
      	<property name="arguments">
      		<ref bean="colours"/>
      	</property>
      </bean>
      About InitializingBean: com.foo.bean doesn't implements this. I don't see that I have to - I have had my example work when I have only a single <value> element within the <list> element, so it seems to me that Spring is happy with my bean and method definitions, but it breaks when I add more <value> elements.

      Comment


      • #4
        I really don't see why it wouldn't work, especially if it's working with one element. Can you clarify these couple points though?

        In your examples:

        Code:
        public void setColourList&#40;List colours&#41;
        and
        Code:
        <bean id="ColoursSetter" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
           <property name="targetClass"><value>com.foo.bean</value></property> 
           <property name="targetMethod"><value>setColoursList</value></property> 
           <property name="arguments"> 
              <ref bean="colours"/> 
           </property> 
        </bean>
        1. Is "setColourList" actually a static method? If it's not, you should specify "targetObject" property instead of "targetMethod". Instance method cannot be executed w/o instance.

        2. "targetMethod" specifies "setColoursList" and in your example method's name is "setColourList". Is this a typo here or in your application?

        Comment


        • #5
          you should specify "targetObject" property instead of "targetMethod".
          sorry, i meant instead of "targetClass" here.

          Comment


          • #6
            1. Yes, setColourList is a static method.
            2. Sorry this is a typo in my example. Like I said, I've simplified what I am trying to do in the application so you need not know the context. That was a mistake in my creation of the example.

            From what I know of reflection, it seems Spring is looking for a method called setColourList with a particular signature (specified by an array of Class objects). Adding new <value> elements changes the signature of the method it searches for. I'd love to know where in the source code it create the Class array as this seems to me to be the problem.

            Comment


            • #7
              Ok, I see where the problem is.
              Code:
              <property name="arguments">
                <ref bean="colours"/>
              </property>
              "argument" property is an array, i.e. method can have an arbitrary number of arguments. When you pass List value, it's converted to array and then bean factory looks for a method with arguments matching to the corresponding List elements.

              Try to modify your bean definition as following. It should work.
              Code:
              <property name="arguments">
                <list>
                  <ref bean="colours"/>
                </list>
              </property>

              Comment


              • #8
                Thanks. I will give that a crack, hopefully today sometime, and let you know how it goes.

                Comment


                • #9
                  Hey that's done the trick!

                  Thanks very much for your assistance!

                  Comment

                  Working...
                  X