Announcement Announcement Module
Collapse
No announcement yet.
configuring a map using an object property Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

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

    Rob

    Comment


    • #3
      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

      Comment


      • #4
        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

        Comment


        • #5
          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

          Comment


          • #6
            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 :?:

            Comment


            • #7
              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

              Comment

              Working...
              X