Announcement Announcement Module
Collapse
No announcement yet.
sharing list and map definitions? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • sharing list and map definitions?

    Hi,

    I have several beans each containing a list that shares many (over 50) entries. Is there any way to inherit these common entries to reduce clutter?

    For example:

    (current situation simplified)


    <bean id="logicalConnection" class="xxx.MessageDefinition">
    <property name="fields">
    <list>
    <ref bean="userNumField"/>
    <ref bean="passField"/>
    </list>
    </property>
    </bean>
    <bean id="logicalConnectionReply" class="xxx.MessageDefinition">
    <property name="fields">
    <list>
    <ref bean="userNumField"/>
    <ref bean="passField"/>
    <ref bean="infoField"/>
    </list>
    </property>
    </bean>


    Desired:
    something like

    <list id="base-list">
    <ref bean="userNumField"/>
    <ref bean="passField"/>
    </list>
    <bean id="logicalConnection" class="xxx.MessageDefinition">
    <property name="fields" value-ref="base-list"/>
    </property>
    </bean>
    <bean id="logicalConnectionReply" class="xxx.MessageDefinition">
    <property name="fields">
    <list extends="base-list">
    <ref bean="infoField"/>
    </list>
    </property>
    </bean>

  • #2
    We achieved what you need by simply extending the capabilities of ListFactoryBean and MapFactoryBean.

    Comment


    • #3
      You can provide a reuse-able bean definition for a List implementation, such as:
      Code:
      <beans>
      
      	<bean id="base-list" class="java.util.ArrayList">
      		<constructor-arg>
      			<list>
      				<value>item1</value>
      				<value>item2</value>
      			</list>
      		</constructor-arg>
      	</bean>
      	
      	<bean id="needsList1" class="xyz.NeedsList">
      		<property name="list" ref="base-list"/>
      	</bean>
      
      	<bean id="needsList2" class="xyz.NeedsList">
      		<property name="list" ref="base-list"/>
      	</bean>
      		
      </beans>
      Or another option is bean-inheritance: injecting the list into an abstract parent bean and then having your other bean definitions inherit from that by using the "parent" attribute.

      Out of curiosity, are you using DI for the individual elements of the List?

      Comment


      • #4
        We chose to extend Spring so that we can reuse a base set of items and then add to it for each custom bean.

        Comment


        • #5
          Originally posted by wallychang
          Is there any way to inherit these common entries to reduce clutter?
          If you are instantiating the many instances of the same class then you can inherit configuration:

          Code:
            <bean id="exampleClass" abstract="true" class="yourClass">
              <property name="xyz" value="abc"/>
            </bean>
          
            <bean id="aRealClass" parent="exampleClass"/>
          This won't really help in your situation though

          I don't think there is anything out of the box that will help you, but the following might be a good start:

          Code:
          <bean id="baseList" class="org.springframework.beans.factory.config.ListFactoryBean">
            <property name="sourceList">
              <list>
                <value>someProperty</value
                <value>someOtherProperty</value
              </list>
            </property>
          </bean>
          
          <bean id="yourBean" class="yourClass">
            <property name="yourProperty" ref="baseList"/>
          </bean>
          That will get you someway, but I don't know of any factory bean to add to the existing list, however the following will do:

          Code:
          public class ListAddingBeanBean implements FactoryBean {
            private final List lists;
            public ListAddingBeanBean (final List theLists) {
              this.lists = theLists;
            }
          
            public Object getObject() {
              // as we are singleton, we could cache this :)
              List newList = new ArrayList();
              for (Iterator i = lists.iterator; i.hasNext(); ) {
                List list = (List) i.next();
                newList.addAll(list);
              }
              return newList;
            }
          
            public Class getObjectType() {
              return List.class;  // could be parameterisable of course.
            }
            public boolean isSingleton() {
              return truel
            }
          }
          This would then be wired up:

          Code:
            <bean id="someOtherClass" class="yourClassAgain">
              <property name="somethingTakingAList">
                <bean class="ListAddingFactoryBean">
                  <list>
                    <ref local="baseList"/>
                    <list>
                      <value>abc</value>
                      <value>def</value>
                    </list>
                  </list>
                </bean>
              </property>
            </bean>
          I have *no* idea whether the above will work, and I am sure, after having typed all that that there *must* be a more elegant solution

          Anyways; subject to someone pointing out a better way; I hope it helps
          Last edited by Colin Yates; Feb 10th, 2006, 02:24 PM.

          Comment


          • #6
            Originally posted by Mark Fisher
            You can provide a reuse-able bean definition for a List implementation, such as:
            Code:
            <beans>
            
            	<bean id="base-list" class="java.util.ArrayList">
            		<constructor-arg>
            			<list>
            				<value>item1</value>
            				<value>item2</value>
            			</list>
            		</constructor-arg>
            	</bean>
            	
            	<bean id="needsList1" class="xyz.NeedsList">
            		<property name="list" ref="base-list"/>
            	</bean>
            
            	<bean id="needsList2" class="xyz.NeedsList">
            		<property name="list" ref="base-list"/>
            	</bean>
            		
            </beans>
            Or another option is bean-inheritance: injecting the list into an abstract parent bean and then having your other bean definitions inherit from that by using the "parent" attribute.
            The problem with this approach is that needsList1 and needsList2 have the same items; what if there were only one or two different items between the lists? (I'm sorry if my initial post wasn't clear about this problem).

            On the other hand, would this be possible by using the init-method="addAll" attribute?

            Originally posted by Mark Fisher
            Out of curiosity, are you using DI for the individual elements of the List?
            Yes, each element in the list has its own attributes.

            Comment


            • #7
              Originally posted by wallychang
              The problem with this approach is that needsList1 and needsList2 have the same items; what if there were only one or two different items between the lists? (I'm sorry if my initial post wasn't clear about this problem).
              See my post above with the ListAddingFactoryBean

              On the other hand, would this be possible by using the init-method="addAll" attribute?
              The problem is that (I think) the list is passed by reference; so you would be updating the original list. Also; how would you specify the parameters.

              Did the solution in my post not work for you?

              Comment


              • #8
                Originally posted by yatesco
                See my post above with the ListAddingFactoryBean

                The problem is that (I think) the list is passed by reference; so you would be updating the original list. Also; how would you specify the parameters.
                Sorry , I was confusing it with the behavior of the factory-method attribute, where you can specify constructor arguments.

                Originally posted by yatesco
                Did the solution in my post not work for you?
                I wanted to see if there was any way to acheive the same functionality without creating a custom factory bean, but it seems that I am out of options, so I'll try your approach Thanks!
                Last edited by wallychang; Feb 10th, 2006, 04:21 PM.

                Comment


                • #9
                  I was browsing the 2.0 reference the other day. It appears to have this new collection merging feature. See Section 3.3.3.4, 2.0 M2 reference. (Of course this won't help you if you are stuck with 1.x.)

                  Comment


                  • #10
                    Hi

                    Just letting ya'll know that the collection merging support mentioned by manifoldronin is going to be backported into the 1.2.x branch.

                    Cheers
                    Rick

                    Comment


                    • #11
                      'merge' not defined yet?

                      Originally posted by Rick Evans
                      Just letting ya'll know that the collection merging support mentioned by manifoldronin is going to be backported into the 1.2.x branch.
                      I actually got a validation error,

                      Code:
                      org.xml.sax.SAXParseException: cvc-complex-type.3.2.2: Attribute 'merge' is not allowed to appear in element 'property'.
                      trying to use this feature with 2.0 M2. The spring-beans.xsd in M2 (also the head) doesn't seem to have 'merge' defined.

                      Comment


                      • #12
                        Is collection merging now in 1.2.7

                        With the release of 1.2.7, has collection merging now been back ported into that release?

                        Heres hoping...

                        Comment


                        • #13
                          In looking over the changelogs, it appears this is not in 1.2.7 or 1.2.8; nor is it going to be in 1.2.9 (per current JIRA report). Is this still expected to be back-ported? Thanks.

                          Comment

                          Working...
                          X