Tuesday, July 04, 2006

How to bind and validate in MultiActionController

In Spring framework, it provides several controller in MVC model. Personaly, I like the MultiActionController best. And I do not like SimpleFormController because it only one "onSubmit" method. For WEB page, I do not think any page just have one button, i.e: "Save" or "Update". However, SimpleFormController have strong validator ability. But I still hate lots of configure in SimpleFormController.

In Spring MultiActionController, it already provides bind method, however, this method just throws Exception when it find the invalidate error message. To catch this error, we need write a new method to override it.

The goal is to use both MultiActionController and SimpleFormController

Solution: bind and validate in MultiActionController.

In XML, you can write your MultiActionController as normal define.



Now we need bind the form and validator it.

I will use a save action as example:

First create a bindObject method in your BaseContoller (extends MultiActionController)

protected BindException bindObject(HttpServletRequest request,
Object command, Validator validator) throws Exception {
preBind(request, command);
ServletRequestDataBinder binder = createBinder(request, command);
binder.bind(request);

BindException errors = new BindException(command,
getCommandName(command));
if (validator.supports(command.getClass())) {
ValidationUtils.invokeValidator(validator, command, errors);
}

return errors;
}

Now in the save action, you can use this method as normal.

public ModelAndView save(HttpServletRequest request,
HttpServletResponse response, PhoneInfo command) throws Exception {
ModelAndView addPhoneView = new ModelAndView(LIST_VIEW, "phones",
phones);
addPhoneView.addObject("phoneInfo", command);

// add validator and call bindobject to get the result
BindException errors = super.bindObject(request, command, new PhoneInfoValidator());
if (errors.hasErrors()) {
addPhoneView.addAllObjects(errors.getModel());
return addPhoneView;
}

// otherwise --- save this object...
return addPhoneView;
}

In this way, I can easy to fix my problem when I use MultiActionController. I can bind and validate any object as I like.

10 comments:

Faisal khan said...

I can't see errors on view page any idea ? one error returned and added inside into view but can't display, though i m using error message and status message into the view.

Unknown said...

It worked better for me when I created the bind exception in BaseController.bindObject a little different, like so:

BindException errors = new BindException(binder.getBindingResult());


This way, I get to keep the conversion errors that the binder reports when a conversion of the form value string to the appropriate type (e.g. long, integer, date) fails.

Also, I have overridden the bind method as inherited from MultiActionController, because it halts on conversion errors (which is due to the fact that internally, MultiActionController.bind calls binder.closeNoCatch()).

Finally, I could not find the preBind method as called in BaseController.bindObject (at least not in Spring 2.5 as I am using currently), but leaving it out seems to pose no problem at all.

zxcv said...

does not xml?

Anonymous said...

hola amigos he seguido los pasos y me valida el formulario, pero no salen los mensajes bajo los campos, a que se debe?

Anonymous said...

la clase validador implementa de interfaz
import org.springframework.validation.Validator; , necesito que se obtenga los mensajes que falta llenar el camposetc, etc

Anonymous said...

he seguido tus consejos pero no consigo que se desplieguen los mensajes de error me puedes ayudar? jcgesoft@hotmail.com

Anonymous said...

If errors are not being displayed and if your command name is not "command", please make below change.

Assume that your command name is "gcn"

// IN BINDOBJECT METHOD
BindException errors = new BindException(command,
"gcn");

Anonymous said...

It was very interesting for me to read the post. Thanx for it. I like such topics and anything that is connected to this matter. I definitely want to read a bit more on that blog soon.

Yatish Sonkeshariya said...

Its great n solve my problem. Its working fine.....Thanks very much

Yatish Sonkeshariya said...

But i m still little bit confuse about bind() method. After overriding bindObject(), still i need to write bind() othewise it doesn't work, Why????