Saturday, 2 April 2011

Using MethodInvokingFactoryBean to call setters with multiple arguments

There is the odd occasion when you want to load a class in your Spring configuration and call an initialisation method that takes two or more parameters. The whole point of Spring is that you use it to create simple POJO beans, so having to call an initialisation or ‘setter’ method with more than one argument is unusual, but not impossible.

One of the things I like about programming is that can be more than one correct answer: both work, with one being better than the other.

The most obvious ways to set this up is to use the InitializingBean interface and call your method in the afterPropertiesSet(), for example:

  public void setHighThreadHold(Number highThreshHold) {
  }

 
public void setLowThreashHold(Number lowThreadHold) {
  }

 
public void afterPropertiesSet() {
   
setThresholds(highThreshold, lowThreshold);
 
}

This idea is my idea that does work, but is it the best way of achieving our aim?

Another idea is to use a MethodInvokingFactoryBean which, using a bit of confg, does it all for you...

In this example, the object that’s being instantiated is SomeObject which has a setter called: setPairOfStrings and our aim is to call this method during the Spring context creation.

package example_2_lifecycle_management.methodinvokingfactory;

/**
* This is our business object. It has a setter with two parameters.
*
*
@author Roger
*/
public class SomeObject implements Interface_A {

 
/** This is the first string in our pair of Strings */
 
private String str1;
 
/** This is the second String in our pair of Strings */
 
private String str2;

 
/**
   * This is our setter method with a compulsory TWO parameters
   *
   *
@param str1
   *            First arg
   *
@param str2
   *            Second arg
   */
 
public void setPairOfStrings(String str1, String str2) {
   
this.str1 = str1;
   
this.str2 = str2;
 
}

 
/**
   * This is the business method as defined by Interface_A
   */
 
public void businessMethod() {
   
System.out.println("Inside - SomeObject - Values are: Str1 = " + str1 + " Str2 = "
       
+ str2);
 
}

}

In order to populate attributes str1 and str2 we can use the following XML:
<!-- This is the object we need to instantiate -->  
<bean id="someobject" class="example_2_lifecycle_management.methodinvokingfactory.SomeObject"/>

<!-- This is the config that calls the double arg setter method: setPairOfStrings  -->  
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject">
           <ref local="someobject"/>
        </property>
        <property name="targetMethod">
            <value>setPairOfStrings</value>
        </property>
        <property name="arguments">
        <list>
            <value>String1</value>
            <value>String2</value>
        </list>
    </property>
</bean>

The code needed to run/test this is:

    // Create an application context
   
ApplicationContext ctx = new FileSystemXmlApplicationContext(
       
"methodinvokingfactorybean.xml");

   
// Using the fully configured factory - get hold of the bean we're after
   
Interface_A a = ctx.getBean("someobject", Interface_A.class);

   
// got the bean - so call our business method.
   
a.businessMethod();

Both of the answers will work, but I believe that the second one: MethodInvokingFactoryBean solves the problem more elegantly.

3 comments:

Anonymous said...

thank you

Anonymous said...

thanks!!!

Anonymous said...

Thanks, nice tip