Question

Assume I have classes:

abstract class Animal {}

class Elephant extends Animal {
    Trunk trunk;
    RightEar rightEar;
}

class Peacock extends Animal {
    Tail tail;
    Beak beak;
}

And I want to write single controller method, which will have parameter of type Animal:

@RequestMapping("/animal")
public ModelAndView animalsHandler(@ModelAttribute("animal") Animal animal) {...}

I found that for non-complex parameter it could be done by choosing appropriate propertyEditor in @InitBinder method, i.e. it will just convert input string by different ways.

But what if Elephant and Peacock have some other objects inside? Seems I can't write propertyEditors for them in that case, but only for their Trunk, Tail and Beak?.. I am completely confused.

Was it helpful?

Solution

It is important that the requestmapper is able to create the correct instance to be filled with the requestparameters. Once this is done the beanwrapper will be able to handle the attributes with the default behavior. So you need to be able to create a peacock instance for the animal modelattribute and you should be fine.

This is how i have done that: (i did that to resolve entities)

  • on startup scan for entities and create a component holding a map of simpleclassname and class

  • create a StringToEntityConverter resolving the string using the above component and register it to the ConversionService (SimpleClassName_Identifier)

  • send the request parameter like this: SimpleClassName_Identifier

If this is done properly the converter will kick in if the requestparameter is an entity and convert it.

Since o have done that for entities which have all a common baseclass and an integer as id the scanning was pretty simple. The converter takes the string, splits it and uses the entitymanager to fetch the entity if the id is not null or creates a new instance if the id was null. From this point on all the requestmappings can directly have entity instances as requestparameters.

The simpleclassname is working here because all jpa entities need a unique simple name anyway!

If you dont want the component with the name to class mapping you could also send down the full class name. And if you only need new instances the converter simply needs the class name without anything else.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top