2013-03-25 5 views
8

Sto usando Spring 3.1.2.RELEASE. Voglio visualizzare un messaggio di errore sul mio JSP se il mio campo data non è formattato correttamente. Pensavo di aver seguito tutti i passi giusti. Ho Binder un convertitore in mio controller ...Come posso visualizzare un errore user friendly quando Spring non è in grado di validare il campo java.util.Date di un modello?

@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)); 
... 
} 

Ho incluso questi messaggi di errore nel mio file messages.properties (inclusi nel contesto di applicazione della molla)

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 

Qui è il modello che sto utilizzando:

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>(); 

E qui è il messaggio di errore che ricevo quando presento il mio modulo con una data di mal formattato ...

0.123.516,410617 millions
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) 

Cos'altro devo fare/controllare il trap per una data formattata male? Preferirei visualizzare un messaggio di errore amichevole all'utente piuttosto che la pagina che sta morendo senza grazia.

Ecco il metodo del controller che deve gestire il modulo. Avviso Ho già incluso un BindingResult.

@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); 
} 

risposta

6

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

Breve storia sta cambiando la firma del metodo di controllo da

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

a

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

tutto fisso.

5

Presumo che dovrebbe essere vincolante la forma in uno dei vostri POST metodi utilizzando @ModelAttribute. Nello stesso metodo, associare un BindingResult bindingResult e tutti gli errori di associazione devono essere acquisiti in questo oggetto bindingResult. All'interno del metodo, si dovrebbe essere in grado di verificare la presenza di

if (bindingResult.hasErrors()) {

e prendere i provvedimenti opportuni.

+0

Viene visualizzato questo errore prima che venga richiamato il metodo POST del mio controller, in altre parole, non raggiunge mai lo stato in cui controllo BindingResult per gli errori. – Dave

+0

L'aggiunta dei BindingResults come parametro successivo dopo quello annotato con @ModelAttribute nel metodo del controller risolve il problema, esattamente come Teja lo ha descritto. Senza i risultati vincolanti, la primavera lancia l'eccezione. Con i risultati vincolanti ti darà la possibilità di reagire ai problemi. –

+0

Salve, BindingResult era già nel metodo del controller. Ho incluso la firma del metodo del controller nella domanda. Altri tipi di messaggi di errore vengono visualizzati correttamente, solo le conversioni di date stanno generando le eccezioni. – Dave

0

annotare un metodo su quella classe controller con questo livello di classe/metodo della nota:

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

più 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; 
} 

Si può vedere questo link per maggiori 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

+0

Ciao, sono un po 'confuso su quello che stai spiegando. Capisco che la classe PropertyEditorSupport possa convertire una stringa in un oggetto java.util.Date, ma quale è la variabile "error = yourerror;" e come faccio a tradurre un'eccezione di analisi nell'utente vedendo il codice di errore "typeMismatch.sampleUserForm.activationDate" visualizzato su JSP? – Dave

+0

CustomDateEditor di spring genera un'eccezione di analisi. Dopo l'eccezione, termina. Il controllo non passa al controller. Ciò che devi fare è estendere il supporto di PropertyEditor. Nel tuo codice esteso non generare eccezioni. –

1

Credo che l'errore è quando si formatta il dati. Per confermare che è necessario eseguire il debug dell'applicazione e controllare il valore della data. E un'altra buona pratica sarebbe quella di credere di configurare un formato standard per la tua applicazione.

seguire l'esempio qui sotto:

@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

Sì, esiste chiaramente un problema di formattazione perché cerco e analizzo "1900" utilizzando la stringa di data "MM/gg/aaaa". Come faccio ad incorporare il "FormattingConversionService" nel mio @initBinder e come posso visualizzare il messaggio di errore rappresentato dal codice "typeMismatch.sampleUserForm.activationDate" sul mio JSP? – Dave

+0

Con FormattingConversionService non è necessario convertire i dati nel raccoglitore. Per far funzionare questo metodo è sufficiente creare una classe con metodi e annotazioni all'interno di un pacchetto che viene scansionato. E prova a usare questo esempio nel tuo JSP:

0

L'argomento BindingResult deve essere accanto al modello in fase di convalida. Es.

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