views:

44

answers:

1

Here goes a command object which needs to be populated from a Spring form

public class Person {

    private String name;
    private Integer age;    

    /**
      * on-demand initialized
      */
    private Address address;

    // getter's and setter's

}

And Address

public class Address {

    private String street;

    // getter's and setter's

}

Now suppose the following MultiActionController

@Component
public class PersonController extends MultiActionController {

    @Autowired
    @Qualifier("personRepository")
    private Repository<Person, Integer> personRepository;

    /**
      * mapped To /person/add
      */
    public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Person person) throws Exception {
        personRepository.add(person);

        return new ModelAndView("redirect:/home.htm");
    }

}

Because Address attribute of Person needs to be initialized on-demand, i need to override newCommandObject to create an instance of Person to initiaze address property. Otherwise, i will get NullPointerException

@Component
public class PersonController extends MultiActionController {

    /**
      * code as shown above
      */

    @Override
    public Object newCommandObject(Class clazz) thorws Exception {
        if(clazz.isAssignableFrom(Person.class)) {
            Person person = new Person();
            person.setAddress(new Address());

            return person;
        }
    }

}

Ok, Expert Spring MVC and Web Flow says

Options for alternate object creation include pulling an instance from a BeanFactory or using method injection to transparently return a new instance.

First option

  • pulling an instance from a BeanFactory

can be written as

@Override
public Object newCommandObject(Class clazz) thorws Exception {
    /**
      * Will retrieve a prototype instance from ApplicationContext whose name matchs its clazz.getSimpleName()
      */
    getApplicationContext().getBean(clazz.getSimpleName());
}

But what does he want to say by using method injection to transparently return a new instance ??? Can you show how i implement what he said ???

ATT: I know this funcionality can be filled by a SimpleFormController instead of MultiActionController. But it is shown just as an example, nothing else

+1  A: 

I'm pretty sure he means using the lookup-method system as documented in chapter 3 of the spring reference manual

Only down side is that <lookup-method> requires a no arg method rather than the newCommandObject(Class) method of MultiActionController.

this can be solved with something like:

public abstract class PersonController extends MultiActionController {

    /**
      * code as shown above
      */

    @Override
    public Object newCommandObject(Class clazz) thorws Exception {
        if(clazz.isAssignableFrom(Person.class)) {
            return newPerson();
        }
    }                          

    public abstract Person newPerson();
}

in the context file:

<bean id="personController" class="org.yourapp.PersonController">
  <lookup-method name="newPerson" bean="personPrototype"/>
</bean>

The down side is that using this sort of thing is you are kinda stuck with configuring the controller bean via xml it's not possible (certainly in < 3) to do this with annotations.

Gareth Davis
@gid Thank you. I think you are right. No way to get the same behavior by using Spring annotations ???
Arthur Ronald F D Garcia