@ModelAttribute interdependency in Spring MVC

Rossen Stoyanchev at Spring Framework is finally ready to tackle the thorny issue of @ModelAttribute inter-dependency.

The new annotation-based handlers allow easy definition of simple controllers, but when combined with JDK 7′s unpredictable ordering of reflected methods, problems could occur..

@ModelAttribute annotation on a method essentially defines it to provide “reference data”; being calling to populate the model, before the handler method is invoked.

The Problem

Essentially the problem arose when using two or more @ModelAttribute methods to load entities or provide reference data, with one depending on the other.

The most common scenario would probably be:

  1. load some entity from the database
  2. calculate or provide reference data, dependent on that entity.

For example:

@ModelAttribute("job")

protected Job loadOrCreate (@RequestParam(value="id", required=false) Integer id);

@ModelAttribute("jobDisplay")
protected JobDisplay buildJobUI (@ModelAttribute("job") Job job);

Reflection order used to be fairly predictable. However in JDK 7, deliberate changes were made to reduce people depending on reflection order.

What I found, is that due to reflection ordering, buildJobUI() was being found before loadOrCreate().

Since Spring was not coded to resolve dependencies, but just processed in the order returned, buildJobUI() was having a blank default Job instance created for it & data binding performed into that. Following that, loadOrCreate() was skipped since the attribute was already present in the implicit model.

So, Job was never loaded from the database, loadOrCreate() was skipped, and fields were bound into an incorrect blank instance. As you would expect, this resulted in total UI failure.

Intended Solution

Rossen’s plan is to check @ModelAttribute method dependencies and invoke them in an appropriate order (vs the current order determined by reflection), or raise an exception (e.g. circular dependency).

While adding a significant degree of complexity & sophistication internally, at the API level this should provide an “it just works” intuitive extension of the present mechanism.

Rossen and Patras Vlad Sebastian have also opened consideration of @ModelAttribute method depends on an @RequestMapping method, i.e. a command object bound and validated by the @RequestMapping method? Rossen thinks he could treat those differently and invoke them after, not before. He’s re-opened an old ticket SPR-5695 and will explore that as an option.

To me, this makes sense. I quite often have “render” methods to build & supplement the View Model, based on the entity after request-handling. However to some extent, I miss having a clear distinction between “referenceData” and “renderModel” as these are quite different phases of the request-handling lifecycle.

Do you use @ModelAttribute methods? What do you think about the proposed improvements?

Read the full discussion here:
- SPR-6299 Support for @ModelAttribute interdependency

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>