[Spring] MultiActionController wirft ServletRequestBindingException

Crod

Mitglied
Moin Moin,

ich hoffe, dass mir hier jemand helfen kann.

Ich nutze in einer Webanwendung den durch Spring bereit gestellten MultiActionController.

Dieser besitzt eine Methode, die mir mit Hilfe des übergebenen Validators und des übergebenen Command Objektes die Fehler zurück geben soll. Diese sind wie folgend aus:

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

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

	return errors;
}

Weiter hin habe ich ein Formular, an das ich das Command Objekt gebunden habe, mit Hilfe der <form:..> Tags. Beim Absenden des Formulares wird folgende Methode aufgerufen:

Code:
public final ModelAndView saveChanges(final HttpServletRequest request, final HttpServletResponse response, final Messe command)
	throws Exception {	
	ModelAndView mav = new ModelAndView("edit");
	mav.addObject("command", command);
	
	BindException errors = this.bindObject(request, command, new EditValidator());
	if (errors.hasErrors()) {
		mav.addAllObjects(errors.getModel());
		return mav;
	}
		
	return mav;
}

In einem kleineren Beispiel, das ich zuvor konstruiert hatte, klappt dies auch soweit. Bei dem oben genannten Fall tritt allerdings folgender Fehler auf:

Code:
org.springframework.web.bind.ServletRequestBindingException: Errors binding onto object 'command'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'command' on field 'name': rejected value [Ulm]; codes [jsp.all.test.message.command.name,jsp.all.test.message.name,jsp.all.test.message.java.lang.String,jsp.all.test.message]; arguments []; default message [null]
	org.springframework.web.bind.ServletRequestDataBinder.closeNoCatch(ServletRequestDataBinder.java:119)
	org.springframework.web.servlet.mvc.multiaction.MultiActionController.bind(MultiActionController.java:499)
	org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:431)
	org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:372)
	org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:774)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:460)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:425)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
	org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:265)
	org.acegisecurity.intercept.web.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:107)
	org.acegisecurity.intercept.web.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:72)
	org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:124)
	org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
	org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
	org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
	org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
	org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)

Und ich kann mir nach langen hin und her einfach nicht erklären wieso.

Ich hoffe, dass mir hier jemand einen Tipp geben kann.

Vielen Dank schon mal.
Torben
 
Puh, was für ein dämlicher Fehler. Ich war natürlich selber Schuld.

Es lag daran, dass ich in dem Controller in der XML Datei den selben Validator nochmals zugewiesen hatte. Wodurch er natürlich jedes mal automatisch ausgeführt wurde.
 
Guten Morgen,

schade, ich hatte gehofft, dass sich das ganze Problem damit aufgelöst hat. Ich habe aber im Zusammenhang mit dieser Thematik noch ein Problem, welches ich diesmal nicht so einfach lösen konnte. Deshalb schreibe ich es gleich in den diesen Thread.

Aktuell sieht mein MultiActionController so aus:

Code:
public class TestController extends MultiActionController {

        /** Registrieren des CustomEditor für das Date Attribut */
	protected final void initBinder(final HttpServletRequest pRequest, final ServletRequestDataBinder pBinder) throws Exception {
		pBinder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("dd.MM.yyyy"), false));
	}
	
	/** Validierung und Rückgabe der Fehler */
	protected final BindException bindObject(final HttpServletRequest request, final Object command, final Validator validator) throws Exception {
		this.bind(request, command);
		ServletRequestDataBinder binder = this.createBinder(request, command);
		binder.bind(request);

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

		return errors;
	}

	/** Rückgabe der Auswahl */
	public final ModelAndView view(final HttpServletRequest request, final HttpServletResponse response, final TestCommand command) throws Exception {
		return new ModelAndView("testView").addObject("command", new TestCommand());
	}

	/** Speichern der Auswahl */
	public final ModelAndView save(final HttpServletRequest request, final HttpServletResponse response, final TestCommand command)
			throws Exception {
		ModelAndView mav = new ModelAndView("testView");
		mav.addObject("command", command);

		// Validieren der gebundenen Daten und Ausgabe der Fehler
		BindException errors = this.bindObject(request, command, new TestValidator());
		if (errors.hasErrors()) {
			mav.addAllObjects(errors.getModel());
			return mav;
		}

		// Andernfalls Rückgabe der Success-View.
		return mav.addObject("status", "Speichern erfolgreich.");
	}

	/** ExcpetionHandler Methode für die ServletRequestBindingException */
	public final ModelAndView showErrors(final HttpServletRequest request, final HttpServletResponse response, final ServletRequestBindingException errors) {
		return new ModelAndView("testView", ((BindException) errors.getRootCause()).getModel());
	}
}

Standardmäßig wird dem Controller kein Validator zugewiesen. Die Validierung wird in der Methode bindObject() duchgeführt. Diese wird wiederum in den Actionmethoden aufgerufen.

Nun kommen wir zum eigentlichen Problem. Das gebundene Befehlsobjekt hat zwei Attribute: ein String und ein Date. Um das Date richtig zu setzen und zu validieren, habe ich durch überschreiben der Methode initBinder() einen CustomDateEditor registriert.

Wird nun beim Parsen der im Formular gemachten Eingabe zu einem Datum ein Fehler gefunden, wird eine ServletRequestBindingException geworfen.Für diese wird nun eine ExceptionHanlder Methode erwartet. In meinem Fall die showErrors(). Ich hoffe, dass es bis hierhin soweit alles richtig und verständlich war.

Nun möchte ich aber, dass diese "Validierung" und das Werfen der ServletRequestBindingException durch den CustomDateEditor nicht autmatisch geschieht, sondern das ich diese ebenfalls manuell, so wie die normale Validierung, durchführen kann. Sprich diese soll auch irgendwie in meiner bindObject() abgearbeitet werden und der Aufruf der ExcpetionHandler Methode soll wegfallen.

Ich hoffe mir konnte einer folgen und sagen, ob irgendwas in dieser Richtung möglich ist.

Vielen dank und Grüße aus dem Norden
Torben
 

Neue Beiträge

Zurück