Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract classes and Spring MVC @ModelAttribute/@RequestParam

I have a hierarchy of model classes in my Spring/Hibernate application.

When submitting a POST form to a Spring MVC controller, is there any standard way of specifying the type of the object being submitted, so Spring can instantiate the correct subclass of the type declared in the receiving method's @ModelAttribute or @RequestParam?

For example:

public abstract class Product {...}
public class Album extends Product {...}
public class Single extends Product {...}


//Meanwhile, in the controller...
@RequestMapping("/submit.html")
public ModelAndView addProduct(@ModelAttribute("product") @Valid Product product, BindingResult bindingResult, Model model)
{
...//Do stuff, and get either an Album or Single
}

Jackson can deserialize JSON as a specific subtype using the @JsonTypeInfo annotation. I'm hoping Spring can do the same.

like image 297
EngineerBetter_DJ Avatar asked Sep 07 '11 15:09

EngineerBetter_DJ


People also ask

What is ModelAttribute in Spring MVC?

@ModelAttribute is an annotation that binds a method parameter or method return value to a named model attribute, and then exposes it to a web view. In this tutorial, we'll demonstrate the usability and functionality of this annotation through a common concept, a form submitted from a company's employee.

What is the difference between @RequestParam and @ModelAttribute?

When you have a method annotated with @ModelAttribute , it is being called every time code hits that servlet. When you have @ModelAttribute as one of the method's parameters, we are talking about incoming Http form data-binding. Calling @RequestParam is a shortcut for saying request.

Can we map a request with @ModelAttribute?

Method level ModelAttribute annotation cannot be mapped directly with any request. Let's take a look at the following example for better understanding. We have 2 different methods in the above example.

Can we use @ModelAttribute?

The @ModelAttribute annotation is used as part of a Spring MVC web app and can be used in two scenarios. Firstly, it can be used to inject data objects in the model before a JSP loads.


1 Answers

Jackson can deserialize JSON as a specific subtype using the @JsonTypeInfo annotation. I'm hoping Spring can do the same.

Assuming you use Jackson for type conversion (Spring uses Jackson automatically if it finds it on the classpath and you have <mvc:annotation-driven/> in your XML), then it has nothing to do with Spring. Annotate the types, and Jackson will instantiate the correct classes. Nevertheless, you will have to do instanceof checks in your Spring MVC controller method.

Update after comments:

Have a look at 15.3.2.12 Customizing WebDataBinder initialization. You could use an @InitBinder method that registers an editor based on a request parameter:

@InitBinder
public void initBinder(WebDataBinder binder, HttpServletRequest request) {
    String productType = request.getParam("type");

    PropertyEditor productEditor;
    if("album".equalsIgnoreCase(productType)) {
        productEditor = new AlbumEditor();
    } else if("album".equalsIgnoreCase(productType))
        productEditor = new SingleEditor();
    } else {
        throw SomeNastyException();
    }
    binder.registerCustomEditor(Product.class, productEditor);
}
like image 58
Sean Patrick Floyd Avatar answered Nov 15 '22 19:11

Sean Patrick Floyd