2013-03-25 1 views
8

Ich benutze Spring 3.1.2.RELEASE. Ich möchte eine Fehlermeldung auf meiner JSP anzeigen, wenn mein Datumsfeld nicht richtig formatiert ist. Ich dachte, ich wäre den richtigen Schritten gefolgt. Ich Bindemittel einen Konverter in meinem Controller ...Wie zeige ich einen benutzerfreundlichen Fehler an, wenn Spring das java.util.Date-Feld eines Modells nicht validieren kann?

@InitBinder 
public void initBinder(final WebDataBinder binder) { 
    final DateFormat dateFormat = new SimpleDateFormat(Contract.DATE_FORMAT); 
    dateFormat.setLenient(false); 

    // true passed to CustomDateEditor constructor means convert empty String to null 
    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); 
... 
} 

ich diese Fehlermeldungen in meiner messages.properties Datei enthalten ist (im Frühjahr Anwendungskontext enthielten)

typeMismatch.activationDate=The activation date format should be of the form MM/dd/yyyy 
typeMismatch.sampleUserForm.activationDate=The activation date format should be of the form MM/dd/yyyy 

Hier ist das Modell, das ich bin mit:

public class SampleUserForm 
{ 

    private String userId; 
    private String firstName; 
    private String middleName; 
    private String lastName; 
    private String username; 
    private String url; 
    private String password; 
    private String confirmPassword; 
    private State state; 
    private java.util.Date activationDate; 
    private java.util.Date expirationDate; 
    private List<Product> products; 
    private Set<Role> roles = new HashSet<Role>(); 

Und hier ist die Fehlermeldung erhalte ich, wenn ich meine Form mit einem schlecht formatierten Datum einreichen ...

org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors 
Field error in object 'sampleUserForm' on field 'activationDate': rejected value [1900]; codes [typeMismatch.sampleUserForm.activationDate,typeMismatch.activationDate,typeMismatch.java.util.Date,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [sampleUserForm.activationDate,activationDate]; arguments []; default message [activationDate]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'activationDate'; nested exception is java.lang.IllegalArgumentException: Could not parse date: Unparseable date: "1900"] 
    org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:111) 
org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:75) 
    org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:156) 
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:117) 
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96) 
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617) 
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578) 
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882) 
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:754) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) 
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) 
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) 
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) 

Was muss ich sonst tun, um nach einem schlecht formatierten Datum zu suchen? Ich würde lieber eine freundliche Fehlermeldung für den Benutzer anzeigen als die Seite, die unwiderstehlich stirbt.

Hier ist die Controller-Methode, die das Formular behandeln soll. Hinweis Ich habe bereits ein BindingResult eingefügt.

@RequestMapping(value = "/save", method = RequestMethod.POST) 
public ModelAndView save(final HttpServletRequest request, 
         final SampleUserForm sampleUserForm, 
         final Model model, 
         final BindingResult result) 
{ 
    String nextPage = "sampleusers/add"; 
    m_sampleUserFormValidator.validate(sampleUserForm, result); 
    if (!result.hasErrors()) 
    { 
     ... process the model and determine the next page ... 
    } // if 

    return new ModelAndView(nextPage); 
} 

Antwort

6

Siehe auch: Spring @Valid validator not invoked properly (Roo, Hibernate).

Kurzgeschichte verändert die Controller-Methode Signatur von

@RequestMapping(value = "/save", method = RequestMethod.POST) 
public ModelAndView save(final HttpServletRequest request, 
        final SampleUserForm sampleUserForm, 
        final Model model, 
        final BindingResult result) 

zu

@RequestMapping(value = "/save", method = RequestMethod.POST) 
public ModelAndView save(final HttpServletRequest request, 
         final Model model, 
         final SampleUserForm sampleUserForm, 
         final BindingResult result) 

fixiert alles.

5

Ich nehme an, Sie sollten das Formular in eine Ihrer POST Methoden @ModelAttribute verbindlich. In der gleichen Methode binden Sie eine BindingResult bindingResult und alle Binding-Fehler sollten in diesem bindingResult Objekt erfasst werden. Innerhalb der Methode sollten Sie in der Lage sein, für

if (bindingResult.hasErrors()) {

und entsprechende Maßnahmen ergreifen zu überprüfen.

+0

Ich bekomme diesen Fehler, bevor die POST-Methode meines Controllers aufgerufen wird - mit anderen Worten, es erreicht nie den Zustand, in dem ich das BindingResult auf Fehler überprüfe. – Dave

+0

Das Hinzufügen von BindingResults als nächsten Parameter nach dem mit @ModelAttribute in der Controller-Methode markierten Objekt löst das Problem, genau wie Teja es beschrieben hat. Ohne die verbindlichen Ergebnisse wirft Feder die Ausnahme. Mit den verbindlichen Ergebnissen erhalten Sie die Chance, auf die Probleme zu reagieren. –

+0

Hallo, Das BindingResult war bereits in der Controller-Methode. Ich habe die Signatur der Controller-Methode in die Frage eingefügt. Andere Arten von Fehlermeldungen werden wieder angezeigt, aber nur diese Datumskonvertierungen werfen die Ausnahmen auf. – Dave

0

annotate ein Verfahren auf diesem Controller-Klasse mit dieser Klasse/Methode Ebene Anmerkung:

@ExceptionHandler(BindException.class) 
public String handleBindExcption(/*flexible parameters*/){ 
    //codes goes here 
    return "view"; //view name or modelAndView 
} 

mehr info

0
`class DateBinderImpl` extends PropertyEditorSupport { 



public void setAsText(String text) 
     throws IllegalArgumentException 
    { 
if(text.isEmpty()){ 

     Datelistener dateString = new Datelistener(); 
     dateString.setValue(""); 
     setValue(dateString); setValue is method of PropertyEditorSupport 
return; 
    } 
// for other date check condition use SimpleDateFormat class 

public String getAsText() 
    { 
     Datelistener dateString = (Datelistener) getValue(); 
     if(dateString.getDate.isEmpty()){ 
      return ""; 

} 


public class Datelistener { 
private String date; 
public Datelistener() 
    { 

    } 
//setter and getter for date; 

} 

public class TestModel{ 
    private Datelistener date; 
// gettter and setter for date 




} 
@InitBinder 
public void initBinder(WebDataBinder binder) 
    { 
     binder.registerCustomEditor(Datelistener, new DateBinderImpl()); 

    } 

private boolean checkClientSideValidation(TestModel model, BindingResult bindingResult) { 
Datelistener dateobject=model.getDate(); // now you can obtained binded date value. 
dateobject.getDate().isEmpty(){ 
bindingResult.rejectValue("date;", "", new Object[] {""}, ""); 
      return true; 
} 

Sie diesen Link für mehr http://forum.springsource.org/showthread.php?58933-Handle-excpetions-from-custom-property-editor-spring-2-5 http://www.codercorp.com/blog/spring/registering-propertyeditorss-with-spring-for-custom-objects-example.html

sehen
+0

Hallo, ich bin ein wenig verschwommen auf was du erklärst. Ich verstehe, dass die PropertyEditorSupport-Klasse eine Zeichenfolge in ein java.util.Date-Objekt konvertieren kann, aber was ist die Variable "error = younror;" und wie mache ich eine Parse-Ausnahme übersetzen in den Benutzer sehen den Fehlercode "typeMismatch.sampleUserForm.activationDate" auf der JSP angezeigt? – Dave

+0

CustomDateEditor von Frühling wirft Parsing exception.So nach der Ausnahme wird es beendet.So Kontrolle wird nicht zu Ihrem Controller übergeben.Was Sie tun müssen, ist yo müssen PropertyEditorSupport erweitern. In Ihrem erweiterten Code werfen keine Ausnahme fangen es. –

1

Ich glaube, dass der Fehler bei der Formatierung der Daten. Um zu bestätigen, dass Sie Ihre Anwendung debuggen müssen und Datumswert überprüfen müssen. Und eine andere gute Praxis wäre zu glauben, dass Sie ein Standardformat für Ihre Anwendung konfigurieren.

nachstehendes Beispiel folgen:

@Configuration 
public class ApplicationContext { 

    @Bean 
    public FormattingConversionService conversionService() { 

      // Use the DefaultFormattingConversionService but do not register 
      // defaults 
      DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); 

      // Ensure @NumberFormat is still supported 
      conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); 

      // Register date conversion with a specific global format 
      DateFormatterRegistrar registrar = new DateFormatterRegistrar(); 
      registrar.setFormatter(new DateFormatter("dd/MM/yyyy")); // define your format 
      registrar.registerFormatters(conversionService); 

      return conversionService; 
    } 
    } 
+0

Ja, es gibt eindeutig ein Formatierungsproblem, weil ich versuche, "1900" mit der Datumszeichenfolge "MM/TT/JJJJ" zu analysieren. Wie integriere ich Ihren "FormatConversionService" in meinen @initBinder und wie zeige ich dann die Fehlermeldung mit dem Code "typeMismatch.sampleUserForm.activationDate" auf meiner JSP an? – Dave

+0

Mit FormattingConversionService müssen Sie keine Daten im Binder konvertieren. Damit diese Methode funktioniert, müssen Sie nur eine Klasse mit Methoden und Anmerkungen innerhalb eines gescannten Pakets erstellen. Und versuchen Sie, dieses Beispiel in Ihrer JSP zu verwenden:

0

BindingResult Das Argument sollte neben dem zu validierenden Modell sein. Bsp

public void checkout(
         @Valid @ModelAttribute("legalContactDetails") LegalContactDetails legalContactDetails, 
         BindingResult legalContactDetailsResult, 
         @Valid @ModelAttribute("researchIntent") ResearchIntent researchIntent, 
         BindingResult researchIntentResult)