Spring Web Flow - Conversion of nested / rich / complex model objects

751 Views Asked by At

How do we bind complex model objects in Spring Web Flow? Take the following example:

public class User {
    int id;
    String name;
    Address address;
}

public class Address {
    int id;
    String street;
    String city;
}

In the view, I have to update the address for this user from address Id. The scenario is where user searches for different addresses and links one address to the user. Since the search result is address ID, how do we convert the address Id to address object?

The current view that I have is -

 <form:form method="POST" modelAttribute="user" action="${flowExecutionUrl}">
      <form:inputpath="address.id" />
 </form:form>

The web flow is the following:

<view-state id="updateAddress" model="flowScope.user">
    <binder>
        <binding property="address" />
    </binder>

    <transition on="addressSubmitted" to="addNextInfo"></transition>
    <transition on="cancel" to="cancelled" bind="false" />
</view-state>

So, two questions:

  • How do we convert the address id to address object inside the user object automatically? I was planning to use Spring converter to do this, but I do not know whether it is for this purpose or is there a better way?
  • Are the other parts in the application that I am showing correct?
1

There are 1 best solutions below

0
On

I think using a custom converter is exactly right. You'd probably want to extend the existing StringToObject converter. I'm guessing some classes here but the converter may look something like this:

public class StringToAddress extends StringToObject {

   private final AddressService addressService;

   public StringToAddress(AddressService addressService) {
       super(Address.class);
       this.addressService = addressService;
   }

   @Override
   protected Object toObject(String string, Class targetClass) throws Exception {
       return addressService.findById(string);
   }

   @Override
   protected String toString(Object object) throws Exception {
       Address address = (Address) object;
       return String.valueOf(address.getId());
   }
}

And then you'll need to configure the conversion service:

@Component("conversionService")
public class ApplicationConversionService extends DefaultConversionService {

    @Autowired
    private AddressService addressService;

    @Override
    protected void addDefaultConverters() {
       super.addDefaultConverters();

       // registers a default converter for the Address type
       addConverter(new StringToAddress(addressService));
    }
}

That will then automatically kick-in whenever Spring attempts to bind the id to the Address field (and will lookup and bind the real Address object).

Keith Donald goes through an example custom converter setup in his post here which is worth referencing.