2016-04-09 27 views
6

Sono nuovo di primavera di avvio. Nel mio controller sto usando UUID s come @PathVariable. Entro la primavera impostazione predefinita restituisce MethodArgumentTypeMismatchException quando passa un invalido UUID.convertitori personalizzati non registrati in avvio primavera

Quando il client passa un valore non valido UUID Voglio lanciare un numero personalizzato InvalidUUIDException, in modo che sia possibile restituire un erroreDato personalizzato utilizzando questa eccezione.

Per ottenere che sto tentando di registrare un numero personalizzato UUIDConverter (implementazione org.springframework.core.convert.converter.Converter).

@Component 
public class UUIDConverter implements Converter<String, UUID> 
{ 
    private static final Pattern pattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"); 

    @Override 
    public UUID convert(String input) throws InvalidUuidException 
    { 
     if (!pattern.matcher(input).matches()) { 
      throw new InvalidUuidException(input); 
     } 

     return UUID.fromString(input); 
    } 
} 

per registrare questo componente, sto aggiungendo questo convertitore a molle ConversionService. Utilizzo di ConversionServiceFactoryBean.

@Configuration 
public class ConversionServiceConfiguration 
{ 
    @Bean 
    public ConversionServiceFactoryBean conversionService() 
    { 
     ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean(); 
     bean.setConverters(getConverters()); 

     return bean; 
    } 

    private Set<Converter> getConverters() 
    { 
     Set<Converter> converters = new HashSet<>(); 
     converters.add(new UUIDConverter()); 

     return converters; 
    } 
} 

ho provato anche ad utilizzare @Component invece di @Configuration come è stato detto qui: Spring not using mongo custom converters

Altre soluzioni ho provato: Naming il fagiolo conversionServiceFactoryBean invece di conversionService. O chiamando bean.afterPropertiesSet() e risintonizzare un ConversionService utilizzando bean.getObject() ...

Ho anche cercato di estendersi da WebMvcConfigurerAdapter, ignorando addFormatters e aggiungere il mio convertitore lì usando addConverter ...

come accennato qui: How to register custom converters in spring boot? ho ha anche provato a registrare il convertitore direttamente come @Bean.

Non importa quello che ho provato, non verrà applicata la UUIDConverter.

Qual è la soluzione corretta fare qualcosa di simile in primavera-boot?
Qualcuno può aiutare qui? Cosa sto facendo di sbagliato?

+0

Ho esattamente lo stesso problema – wasabi

+0

hai attivato SprinbWebMvc? – hovanessyan

risposta

0

Il modo idiomatica in primavera per gestire questo caso è quello di utilizzare una consuetudine ExceptionHandler. Fondamentalmente stai dicendo a Spring che gestirai questa specifica classe di errore.

L'idea è che si definisce il ExceptionHandler, che intercetta l'errore gettato (ad es MethodArgumentTypeMismatchException) e restituisce un costume ResponseEntity popolato con qualsiasi struttura (ad es ErrorDto) è necessario, i codici di errore, le intestazioni ecc

Ecco un esempio:

@ExceptionHandler({ MethodArgumentTypeMismatchException.class }) 
public ResponseEntity<Object> handleMethodArgumentTypeMismatch(
    MethodArgumentTypeMismatchException ex, WebRequest request) { 

    //populate your ErrorDto with the desired information 
    ErrorDto errorDto = 
     new ErrorDto(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), ex); 

    //return your ErrorDto wrapped in ResponseEntity 
    return new ResponseEntity<Object>(errorDto, HttpStatus.BAD_REQUEST); 
} 

UPDATE

sono stato effettivamente in grado di eseguire un codice di esempio fe attirando il tuo convertitore personalizzato, ma quello che succede è, l'eccezione che passi viene incassata in ConversionFailedException, quindi in TypeMismatchException e infine in MethodArgumentTypeMismatchException e questo è ciò che viene restituito al client. Quindi, anche se riesci a eseguirlo con il convertitore personalizzato, c'è del lavoro aggiuntivo per propagare la tua eccezione al client e non ottenerlo nel MethodArgumentTypeMismatchException.

+0

Spiacente, questo codice non è correlato al problema. L'eccezione ** la gestione ** funziona bene. Il problema qui è quello di lanciare un'eccezione ** personalizzata ** per comunicare esplicitamente al client che l'UUID è il pezzo non valido nella richiesta utilizzando il convertitore degli stivali di primavera. Per quanto riguarda il tuo aggiornamento: questo è quello che puoi evitare usando le eccezioni personalizzate – Tim

+0

Hai effettivamente eseguito il debug del tuo codice per vedere se viene chiamato il metodo di conversione del convertitore? – hovanessyan

+0

Con ExceptionHandler, è comunque possibile inviare al client tutte le informazioni desiderate. Per quanto ho capito, la tua app restituirà JSON, quindi non importa se costruisci il JSON da questa o quell'eccezione o dall'uso di un'altra classe. Normalmente in REST lo stato di errore viene indicato tramite i codici di stato HTTP, che è possibile impostare utilizzando ExceptionHandler. – hovanessyan

1

so solo su questo problema perché l'ho fatto lo stesso me stesso con un'altra classe e ore trascorse debug ...

Il UUIDConverter è un fagiolo already a registered by Spring itself. Scegli letteralmente qualsiasi altro nome e dovresti vederlo apparire.

+0

Huh, ho bisogno di provarlo. In tal caso mi aspetterei eccezione NoUniqueBean o qualcosa di simile:/Grazie per il tuo suggerimento! – Tim

Problemi correlati