Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autogrowing list with generics

I have a domain model that features a number of 'elements', pieces of text that can be rendered to show rich content. There are pieces of HTML text, textile text, Flash objects and so on. The basic features of these elements are encapsulated in AbstractElement, which has implementations HTMLElement, FlashElement and so on. The model therefore has a List<AbstractElement> to contain all the elements it can have.

When editing the model, I want the user to be able to dynamically add elements, and save these when the user submits the form. So what I have is a form that is dynamically expandible with some JavaScript, which results in the following form:

<form action=...>
    <!-- Other attributes -->
    <textarea name="object.elements[0].content"/>
    <textarea name="object.elements[1].content"/>
    <!-- Some elements are based on text, others on files -->
    <input type="hidden" name="object.elements[2].file" value="somevalue"/> 
    <textarea name="object.elements[3].content"/>
    <!-- Submit button -->
</form>

This goes wrong when submitting the form. It's quite obvious why - when submitted, Spring tries to instantiate the required elements in the list. Since the list of elements contains objects of type AbstractElement which is abstract, Spring cannot instantiate new elements.

How would I go about having Spring instantiate the proper type of element? Could add type information in the form, and have some ModelAttribute do it? How would that work? Is there something I can do in the model that'll do this automatically?

like image 913
DCKing Avatar asked Dec 04 '11 21:12

DCKing


People also ask

How to use generic type names in C/Al?

For example, in C#, if you use the generic type parameter T, then you can write a List<T> class that is declared as either List<int>, List<string>, or List<MyClass>. With .NET Framework interoperability, you can define DotNet variables for generics. You cannot specify generic type names in C/AL.

What can you do with a generic list?

You can add, delete, populate, sort Generic Lists. <T> is a placeholder for data types and replaced by datatype at compile time. How it is different from Collection Lists?

Where can I find a list of authorized generics?

FDA publishes a list of reported authorized generics and updates that list quarterly. On September 27, 2007, the President signed into law the Food and Drug Administration Amendments Act (FDAAA) (Public Law 110-85). Among other things, FDAAA added new subsection (t) to section 505 of the Federal Food, Drug, and Cosmetic Act (the Act).

How does the generics autowiring feature work in Java?

The generics autowiring feature works with the help of ResolvableType class behind the scenes. It was introduced in Spring 4.0 to encapsulate Java Type and handle access to supertypes, interfaces, generic parameters and finally resolve to a Class: The output of the above code would show the corresponding simple and generic types:


2 Answers

It sounds like you need to create one (or more ) customer property editors which can take the request parameters and convert them to the correct class instances to add to the collection.

Spring uses PropertyEditor instances registered with the data binder to bind request parameters. In cases where the default set of PropertyEditors can't determine the correct type, you can register your own editors to handle the logic.

The process is described in the Spring docs at this link:

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/validation.html

Specifically, see section 5.4.2.1 on how to register customer property editors.

You can register your property editors using the registerCustomEditor() method of the WebDataBinder class in the initBinder() method of your controller (identified with the @InitBinder annotation).

like image 121
khill Avatar answered Oct 15 '22 05:10

khill


I ended up solving this by implementing a ModelAttribute that constructs the list of elements by parsing the raw form data. Parsing the raw form data can be used by using the HttpServletRequest object, looping through the parameter map and just create the required objects 'by hand'. It's reusable if you put it in a helper function, though I need a ModelAttribute in every controller I use it in.

It's not the ideal solution, but it works.

like image 27
DCKing Avatar answered Oct 15 '22 05:10

DCKing