Results 1 to 7 of 7

Thread: configuring a map using an object property

  1. #1
    Join Date
    Apr 2005
    Posts
    19

    Default configuring a map using an object property

    I just want to know if i could configure via spring a map property using as key an object property.

    The objects stored in the map has a name which is going to be injected, so it is written down in the config file and i don't want to hardtype the same string in the map configuration section.

    As far as i can see there might be some chioces:

    - Declare the string representing the name as a bean. I don't like this one pretty much since it would pollute the config.

    - Add some code to the setter method that handle each element instead the map, so the container will call setElement to add each reference:

    Code:
    private Map myMap = new XX();
    
    public void setElement(Element e) {
      myMap.put(e.getName(), e);
    }
    Code:
    <property name="element"><ref bean="myElement1" /></property>
    <property name="element"><ref bean="myElement2" /></property>
    <property name="element"><ref bean="myElement3" /></property>
    I don't like this one 'cause i have not tried it so i don't know if it would work and looks ugly. Also it is coupled to the implementation of my choice XX class.

    So, is there something i am missing?

    thanks

  2. #2
    Join Date
    Aug 2004
    Location
    Southampton, UK
    Posts
    826

    Default

    You can set the key of the Map using the 'key-ref' attribute of the <entry> tag. Does that do what you need?

    Rob
    Rob Harrop
    Lead Engineer, dm Server
    SpringSource
    http://www.springsource.com

    Co-Author - Pro Spring

  3. #3
    Join Date
    Apr 2005
    Posts
    19

    Default

    Nope.

    I want something like:

    Code:
    <map>
      <entry>
        <key field="name"><ref bean="myBean" /></key>
        <bean ref="myBean" />
      </entry>
     ...
    Or something that allows the container to build the map using name property as the key.

    Thanks

  4. #4
    Join Date
    Aug 2004
    Location
    Southampton, UK
    Posts
    826

    Default

    I see. That is not something that is supported in the current release. I'm not sure that we have plans to support any construction patterns similiar to this for 1.3, but maybe we can add something in the future.

    Rob
    Rob Harrop
    Lead Engineer, dm Server
    SpringSource
    http://www.springsource.com

    Co-Author - Pro Spring

  5. #5
    Join Date
    Jul 2005
    Location
    Leeds, UK
    Posts
    10

    Default

    Hiya

    You could always write a little (Spring) code, to wit...

    Code:
    package foo;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.BeanFactory;
    import org.springframework.beans.factory.BeanFactoryAware;
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
    
    import java.util.Hashtable;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public final class CustomCollectionFactoryBean implements FactoryBean, InitializingBean, BeanFactoryAware &#123;
    
        private List list;
        private BeanFactory beanFactory;
        private Map map;
    
        public void setSourceList&#40;final List list&#41; &#123;
            this.list = list;
        &#125;
    
        public Object getObject&#40;&#41; throws Exception &#123;
            if &#40;map == null&#41; &#123;
                map = new Hashtable&#40;this.list.size&#40;&#41;&#41;;
                for &#40;Iterator it = this.list.iterator&#40;&#41;; it.hasNext&#40;&#41;;&#41; &#123;
                    String beanName = &#40;String&#41; it.next&#40;&#41;;
                    map.put&#40;beanName, beanFactory.getBean&#40;beanName&#41;&#41;;
                &#125;
            &#125;
            return map;
        &#125;
    
        public Class getObjectType&#40;&#41; &#123;
            return Map.class;
        &#125;
    
        public boolean isSingleton&#40;&#41; &#123;
            return true;
        &#125;
    
        public void afterPropertiesSet&#40;&#41; throws Exception &#123;
            if &#40;this.list == null&#41; &#123;
                throw new IllegalArgumentException&#40;"The 'SourceList' property is required."&#41;;
            &#125;
        &#125;
    
        public void setBeanFactory&#40;final BeanFactory beanFactory&#41; throws BeansException &#123;
            this.beanFactory = beanFactory;
        &#125;
    &#125;
    With an attendant XML configuration like so...

    Code:
    <?xml version="1.0" ?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    <beans>
    
    	<bean id="corbaTransport" class="foo.CorbaBasedTransport"/>
    	<bean id="otherTransport" class="foo.OtherTransport"/>
    
        <bean id="bagOfBeans" class="foo.CustomCollectionFactoryBean">
            <property name="sourceList">
                <list>
                    <idref local="corbaTransport"/>
                    <idref local="otherTransport"/>
                </list>
            </property>
        </bean>
    
    </beans>
    Where the 'sourceList' property is a list of the names of the beans in your container that you want to have punted into your map (using each beans name as the key for each resolved object).

    Ciao
    Rick
    Developer, Interface21
    http://www.springframework.com - Spring From the Source

  6. #6
    Join Date
    Apr 2005
    Posts
    19

    Default

    ehm...

    Name was a property of the bean, not the beanName itself.
    It could have been stockName, teamName or whatever.

    In fact i could change the code of your 'CustomCollectionFactoryBean' to support that stuff but i am not still quite happy with the solution, sorry.

    What i see is fair enough is declaring a bean containing the name as a String, injecting it to the bean and using it as the map key. It might add some pollution to the config file, as i said before, but to me is much cleaner than the other choices i can think by now.

    Thanks a lot

    PD: I'm not quite sure there is a real demand on supporting this :?:

  7. #7
    Join Date
    Jul 2005
    Location
    Leeds, UK
    Posts
    10

    Default

    Hiya

    Name was a property of the bean, not the beanName itself.
    Indeed; as you say, the code to change this to what you want is trivial, to wit...

    Code:
    package foo;
    
    import org.springframework.beans.factory.FactoryBean;
    import org.springframework.beans.factory.InitializingBean;
    
    import java.util.Hashtable;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public final class CustomCollectionFactoryBean implements FactoryBean, InitializingBean &#123;
    
        private List list;
        private Map map;
    
        public void setSourceList&#40;final List list&#41; &#123;
            this.list = list;
        &#125;
    
        public Object getObject&#40;&#41; throws Exception &#123;
            if &#40;map == null&#41; &#123;
                map = new Hashtable&#40;this.list.size&#40;&#41;&#41;;
                for &#40;Iterator it = this.list.iterator&#40;&#41;; it.hasNext&#40;&#41;;&#41; &#123;
                    Nameable named = &#40;Nameable&#41; it.next&#40;&#41;;
                    map.put&#40;named.getName&#40;&#41;, named&#41;;
                &#125;
            &#125;
            return map;
        &#125;
    
        public Class getObjectType&#40;&#41; &#123;
            return Map.class;
        &#125;
    
        public boolean isSingleton&#40;&#41; &#123;
            return true;
        &#125;
    
        public void afterPropertiesSet&#40;&#41; throws Exception &#123;
            if &#40;this.list == null&#41; &#123;
                throw new IllegalArgumentException&#40;"The 'SourceList' property is required."&#41;;
            &#125;
        &#125;
    &#125;
    Code:
    <?xml version="1.0" ?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http&#58;//www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean id="corbaTransport" class="foo.SimpleNameable">
            <property name="name" value="Rilo"/>
        </bean>
        <bean id="otherTransport" class="foo.SimpleNameable">
            <property name="name" value="Kiley"/>
        </bean>
    
        <bean id="bagOfBeans" class="foo.CustomCollectionFactoryBean">
            <property name="sourceList">
                <list>
                    <ref local="corbaTransport"/>
                    <ref local="otherTransport"/>
                </list>
            </property>
        </bean>
    </beans>
    Code:
    package foo;
    
    public interface Nameable &#123;
    
        public String getName&#40;&#41;;
        public void setName&#40;String name&#41;;
    &#125;
    Code:
    package foo;
    
    public final class SimpleNameable implements Nameable &#123;
    
        private String name;
    
        public String getName&#40;&#41; &#123;
            return name;
        &#125;
    
        public void setName&#40;final String name&#41; &#123;
            this.name = name;
        &#125;
    &#125;
    Code:
    package foo;
    
    import com.isis.icapfe.modelling.Transport;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    
    import java.util.Map;
    import java.util.Iterator;
    
    public final class Main &#123;
    
        @SuppressWarnings&#40;"unchecked"&#41;
        public static void main&#40;final String&#91;&#93; args&#41; &#123;
    
            ApplicationContext ctx = new FileSystemXmlApplicationContext&#40;"beans.xml"&#41;;
            Map beans = &#40;Map&#41; ctx.getBean&#40;"bagOfBeans"&#41;;
            for &#40;Iterator iterator = beans.keySet&#40;&#41;.iterator&#40;&#41;; iterator.hasNext&#40;&#41;;&#41; &#123;
                String name = &#40;String&#41; iterator.next&#40;&#41;;
                System.out.println&#40;name + " &#58; " + beans.get&#40;name&#41;&#41;;
            &#125;
        &#125;
    &#125;
    This is the type of corner case for which the FactoryBean abstraction is a fit (I'll agree that it's not nice, but there ain't nothing to the code as you can see).... this is surely better than extending the DTD? A forthcoming release of classic Spring will have extension points in the parser so that you can define your own XML syntax callbacks however you see fit. Maybe that will be a better solution for you.

    Ciao
    Rick
    Developer, Interface21
    http://www.springframework.com - Spring From the Source

Similar Threads

  1. Order of Bean definitions matters?
    By cfuser in forum Container
    Replies: 2
    Last Post: Oct 21st, 2005, 10:29 AM
  2. Unit testing with JOTM and JtaTransactionManager
    By lalle in forum Architecture
    Replies: 1
    Last Post: Oct 15th, 2005, 09:05 AM
  3. EHCaching Hibernate
    By dencamel in forum Data
    Replies: 3
    Last Post: Sep 6th, 2005, 09:03 PM
  4. Replies: 4
    Last Post: Aug 17th, 2005, 04:42 AM
  5. Replies: 2
    Last Post: May 13th, 2005, 05:42 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •