HTML Select lists in Spring MVC 2.5 with annotations
By: Paul Parsons
Tags: Java Ee, Java, Spring

In this article, I’d like to talk about the use of HTML select lists with Spring MVC since I’ve had to do some development in this area recently and found little documentation available. Select lists are also known as drop-down lists or combo boxes.

In this post I will use an example web application developed using Spring and Spring MVC 2.5. It uses hard-coded data instead of a database to keep things simple. You can download the source code for it here.

Running the example

To run the example, you will need to install Maven. I used version 2.0.9 to write this post. Once you have installed Maven and downloaded and unzipped the source code you can run the application by executing the following in the directory to which you unzipped the source code:

mvn jetty:run

Once Jetty starts up, you have to go to http://localhost:9080/test-webapp/ to view the web application.

The domain model

The application is a simple web app that allows a user to add, remove and edit Users. Each User is a member of a Department. When you add or edit a user, you must specify the Department that they are in — using a Select list. The User and Department classes are in the com.tsl.springmvc.bom package contained within the /src/main/java folder. They make use of two superclasses — IdentifiableType and NamedType (which extends IdentifiableType), two classes which provide id and name fields respectively to subclasses.

The web pages

When you first run the application, you see the list of users page, which is blank. Click on the link in the “create user” link to create a new user and fill in the information, including the Department. Click save. You should now see a new user in the list of users. Edit this user and save it. The original user should have been changed too. Simple, right? Well, it is, once you know how to do it with Spring MVC! Here comes the explanation….

The basic controller code

The UserController class is the Spring MVC controller that manages all operations to do with users. Note that I am using the annotations available in Spring 2.5 instead of the XML configuration. The controller has create, info (to view), save and delete methods which allow the user to perform the relevant operations on Users. It uses UserDao and DepartmentDao to manipulate User and Department objects. All of this is pretty standard Spring MVC 2.5 so I’m not going to enter into much detail here. The basic code is shown below.

@Controller

public class UserController {

...

@Autowired

private UserDao userService;



@Autowired

private DepartmentDao departmentDao;



@RequestMapping(value="/user/create.html")

public ModelAndView create() {

return new ModelAndView(FORM_VIEW_KEY, FORM_MODEL_KEY, new User());

}





@RequestMapping(value="/user/info.html")

public ModelAndView info(@RequestParam("id") Integer id) {

User result = userService.findById(id);

return new ModelAndView(FORM_VIEW_KEY, FORM_MODEL_KEY, result);

} @RequestMapping(value="/user/save.html", method = RequestMethod.POST)

public ModelAndView save(@ModelAttribute(FORM_MODEL_KEY) User user, BindingResult result, SessionStatus status) {



new UserValidator().validate(user, result);

if (result.hasErrors())

{

return new ModelAndView(FORM_VIEW_KEY, FORM_MODEL_KEY, user);

}

else

{

userService.merge(user);

return new ModelAndView(REDIRECT_SEARCH_VIEW_KEY, search());

}

} @RequestMapping(value="/user/delete.html")

public ModelAndView delete(@RequestParam("id") Integer id) {

User user = userService.findById(id);

userService.remove(user);

return new ModelAndView(REDIRECT_SEARCH_VIEW_KEY, search());

}



@RequestMapping(value="/user/search.html")

public ModelMap search() {

return new ModelMap(SEARCH_MODEL_KEY,

userService.findAll());

}

} Showing the select list To show a list of Departments on the create/edit user page, we have to get them using a DAO. This is best done in the controller using the following code: @ModelAttribute("departments")

public Collection populateDepartments() {

return departmentDao.findAll();

} Note the user of the @ModelAttribute annotation to declare that this is something we will put in the model under the name "departments" so that it can be used on the JSP page. The relevant JSP code (from /src/main/webapp/WEB-INF/jsp/user/user.jsp) to display the list is shown below.

:

Note the use of ${departments} to indicate that we want to use the model attribute "departments" which we registered with the model using the @ModelAttribute controller annotation. What you put in the <form:select> element is very important. The code above specifies:

Which attribute of the model the select list refers to (the department attribute of a User)

Where the list of items for the select comes from (the “departments” model attribute)

Which attribute of each select item (in this case department) to show in the list. Here I specify the “name” attribute of the department

Spring MVC allows you to specify an itemValue attribute for the <form:select> element. DO NOT SPECIFY this attribute if you want to use Property Editors (recommended - see below for more information). Property Editors When someone chooses the Department that a user belongs to, we want to update the "department" attribute of the User object. We don't want to have to do some kind of lookup on a department ID or, worse, store the department ID on the user. What we need to do therefore, is register some kind of converter that is capable of converting a Department to an ID which can be associated with a value in a <form:select> list and, once submitted, doing the reverse conversion on a supplied ID to obtain the original Department object. In JSF, an object that performs this conversion is called a Converter. Spring uses the Java convention and calls it a Property Editor. The DepartmentEditor is shown below. public class DepartmentEditor extends PropertyEditorSupport { private final DepartmentDao departmentDao; public DepartmentEditor(DepartmentDao departmentDao) {

this.departmentDao = departmentDao;

} @Override

public void setAsText(String text) throws IllegalArgumentException {

setValue(departmentDao.findById(Integer.parseInt(text)));

}



@Override

public String getAsText() {

Department s = (Department) getValue();

if (s == null) {

return null;

} else {

return s.getId().toString();

}

}

} The basic convention for implementing a PropertyEditor is:

extend the standard Java class PropertyEditorSupport to make life easier

override the setAsText(String text) method and in the body, call setValue() with the object that corresponds to the text as arguments

override the getAsText() method and in the body, returning a string that represents the object that you obtain when you call getValue()