Announcement Announcement Module
Collapse
No announcement yet.
Assigning bean property A value as bean property B value Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Assigning bean property A value as bean property B value

    We are trying to do the following:

    Code:
    <bean id="beanB" class="somepackage.ClassB">
      <property name="beanBproperty1" value="somevalue" />
    </bean>
    
    <bean id="beanA" class="somepackage.ClassA">
      <property name="beanAproperty" ref="beanB.beanBproperty2" />
    </bean>
    or

    Code:
    <bean id="beanA" class="somepackage.ClassA">
      <property name="beanAproperty" value="$&#123;beanB.beanBproperty2&#125;" />
    </bean>
    This does not seem currently possible. Is there an out of the box way of doing this? We already achieved this by extending the ApplicationContext and BeanFactory but we would rather not have to use proprietary implementations.

    The odd thing is that Spring allows the following:

    Code:
    <bean id="beanA" class="somepackage.ClassA">
      <property name="beanAproperty.subproperty" value="somevalue" />
    </bean>
    so it's a bit weird that the reverse isn't possible.

    Thank you in advance for your time and consideration.

  • #2
    Take a look at org.springframework.beans.factory.config.PropertyP athFactoryBean. It's kind of verbal, but it works.

    Comment


    • #3
      Originally posted by dvoytenko
      Take a look at org.springframework.beans.factory.config.PropertyP athFactoryBean. It's kind of verbal, but it works.
      Verbose indeed but it seems to work! Thanks!

      Anyone knows if there are any plans to allow for notation similar to

      Code:
      <bean id="beanA" class="somepackage.ClassA">
        <property name="beanAproperty" ref="beanB.beanBproperty2" />
      </bean>
      
      or
      
      <bean id="beanA" class="somepackage.ClassA">
        <property name="beanAproperty" value="$&#123;beanB.beanBproperty2&#125;" />
      </bean>
      in a future release (ala JSF)?

      Comment


      • #4
        [quote="gstathis"]
        Originally posted by dvoytenko
        Anyone knows if there are any plans to allow for notation similar to

        Code:
        <bean id="beanA" class="somepackage.ClassA">
          <property name="beanAproperty" ref="beanB.beanBproperty2" />
        </bean>
        
        or
        
        <bean id="beanA" class="somepackage.ClassA">
          <property name="beanAproperty" value="$&#123;beanB.beanBproperty2&#125;" />
        </bean>
        in a future release (ala JSF)?
        I am looking for the same solution.

        Yes, that would have been really really nice and FLEXIBLE to have some simple evaluation logic in the XML config rather than writing this in a Java code which basically eliminates the advantage of the Spring configuraion.

        I would like to add another more complex case:

        Code:
        <bean id="beanA" class="somepackage.ClassA">
          <property name="beanAproperty" value="My value consisting of $&#123;beanA.beanBproperty1&#125; and $&#123;beanB.beanBproperty1&#125;" />
        </bean>

        Comment


        • #5
          Originally posted by stain
          Code:
          <bean id="beanA" class="somepackage.ClassA">
            <property name="beanAproperty" value="My value consisting of $&#123;beanA.beanBproperty1&#125; and $&#123;beanB.beanBproperty1&#125;" />
          </bean>
          As well as "property" argument resolution similar to that of the constructor argument resolution that Spring already supports:
          http://www.springframework.org/docs/...ns.html#d0e746

          Comment


          • #6
            Anyone knows if there are any plans to allow for notation similar to

            Code:
            <bean id="beanA" class="somepackage.ClassA">
            <property name="beanAproperty" ref="beanB.beanBproperty2" />
            </bean>

            or

            <bean id="beanA" class="somepackage.ClassA">
            <property name="beanAproperty" value="${beanB.beanBproperty2}" />
            </bean>
            "beanB.beanBproperty2" is a legal bean name. Spring doesn't have restrictions on dots in the beans names. I guess something like following could work:
            Code:
              <property name="beanAproperty" /> 
                <ref bean="beanB" path="beanBproperty2"/>
              </property>

            Comment


            • #7
              Originally posted by dvoytenko
              I guess something like following could work:
              Code:
                <property name="beanAproperty" /> 
                  <ref bean="beanB" path="beanBproperty2"/>
                </property>
              Oooh! Me like! Somebody put this in JIRA.

              Comment


              • #8
                Originally posted by dvoytenko
                "beanB.beanBproperty2" is a legal bean name.
                Unfortunately yes. But in Java the "." (dot) also means other things like package delimiter or Class.method(). It would make Spring configuration files more intuitive if the dot could also be resolved as a Class.method() delimiter.

                In any case, here is another suggestion from one of my colleagues:

                Code:
                <bean id="beanA" class="somepackage.ClassA">
                  <property name="beanAproperty" ref="beanB.beanBproperty2&#91;'namedArrayValue'&#93;" />
                </bean>
                or

                Code:
                <bean id="beanA" class="somepackage.ClassA">
                  <property name="beanAproperty" ref="beanBproperty2&#91;'namedArrayValue'&#93;" />
                </bean>
                Now that would be great!

                Comment


                • #9
                  As I had a bit too much time on my hands (don't tell my PM!), here's one possible solution:

                  Create an instance of BeanFactoryPostProcessor to parse though all the bean configurations looking for any PropertyValues that match a particular pattern (in this case anything starting with @).

                  For the matching PropertyValue, replace it with a custom PropertyValue (in this case ReferencedPropertyValue).

                  Instance of BeanFactoryPostProcessor:
                  Code:
                  public void postProcessBeanFactory ( ConfigurableListableBeanFactory beanFactory )
                      throws BeansException
                  {
                      String[] beanNames = beanFactory.getBeanDefinitionNames ();
                  
                      for ( int b = 0; b < beanNames.length; b ++ )
                      {
                          String beanName = beanNames[b];
                  
                          BeanDefinition beanDef = beanFactory.getBeanDefinition ( beanName );
                          MutablePropertyValues mpv = beanDef.getPropertyValues ();
                          PropertyValue[] propertyValues = mpv.getPropertyValues ();
                  
                          for ( int pv = 0; pv < propertyValues.length; pv ++ )
                          {
                              PropertyValue pValue = propertyValues[pv];             
                              this.processPropertyValue ( beanFactory, beanName, mpv, pv, pValue );
                          }
                      }
                  }
                      
                  protected void processPropertyValue ( BeanFactory beanFactory, MutablePropertyValues mpv, int index, PropertyValue pValue )
                  {
                      if ( pValue.getValue () instanceof String )
                      {
                          String value = ( String ) pValue.getValue ();
                          if ( value.startsWith ( PREFIX ) )
                          {
                              MethodInvokingPropertyValue mipv =
                                  ( new MethodInvokingPropertyValue ( pValue.getName (), value.substring ( PREFIX.length () ) ) )
                                  .setBeanFactory ( beanFactory );
                  
                              mpv.setPropertyValueAt ( mipv, index );
                          }
                      }
                  }
                  In ReferencedPropertyValue, the overridden method getValue should convert the expression (e.g. '@beanA[someKey].someProperty') into it's component parts and use something like BeanWrapperImpl to return the property value of the referenced bean. (This is quite tricky when trying to support keyed properties such as Maps and Arrays but not impossible. Give me a shout if you need any pointers).

                  Code:
                  public class ReferencedPropertyValue extends PropertyValue
                  {
                      private BeanFactory beanFactory;
                  
                      public ReferencedPropertyValue ( String propertyName, Object propertyValue )
                      {
                          super ( propertyName, propertyValue );
                      }
                  
                      public ReferencedPropertyValue setBeanFactory ( BeanFactory bf )
                      {
                          this.beanFactory = bf;
                          return this;
                      }
                      
                      public Object getValue ()
                      {
                          String expression = super.getValue ();
                          Object result = ... convert expression to use beanFactory and return property value ...
                  
                          return result;
                      }
                  }
                  The above only applies to mutable properties, i.e. setter methods. It would be relatively straightforward to add code to support constructor properties and so on.

                  Of course there's the question of dependencies but that another discussion

                  Cuong.

                  Comment


                  • #10
                    Originally posted by gstathis
                    We are trying to do the following:

                    Code:
                    <bean id="beanB" class="somepackage.ClassB">
                      <property name="beanBproperty1" value="somevalue" />
                    </bean>
                    
                    <bean id="beanA" class="somepackage.ClassA">
                      <property name="beanAproperty" ref="beanB.beanBproperty2" />
                    </bean>
                    I'm a little concerned that allowing this would introduce implicit bean dependencies not always consistent with those defined in "depends-on".

                    Of course, you could always define "somevalue" as a 3rd bean, and reference it in both properties (which admittedly doesn't help the verbosity situation).

                    Comment

                    Working...
                    X