J'ai cette énumération:
public enum SortEnum {
asc, desc;
}
Que je veux utiliser comme paramètre d'une demande de repos:
@RequestMapping(value = "/events", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public List<Event> getEvents(@RequestParam(name = "sort", required = false) SortEnum sort) {
Cela fonctionne bien lorsque j'envoie ces demandes
/events
/events?sort=asc
/events?sort=desc
Mais quand j'envoie:
/events?sort=somethingElse
Je reçois une réponse 500 et ce message dans la console:
2016-09-29 17:20:51.600 DEBUG 5104 --- [ XNIO-2 task-6] com.myApp.aop.logging.LoggingAspect : Enter: com.myApp.web.rest.errors.ExceptionTranslator.processRuntimeException() with argument[s] = [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type [Java.lang.String] to required type [com.myApp.common.SortEnum]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [Java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam com.myApp.common.SortEnum] for value 'somethingElse'; nested exception is Java.lang.IllegalArgumentException: No enum constant com.myApp.common.SortEnum.somethingElse]
2016-09-29 17:20:51.600 DEBUG 5104 --- [ XNIO-2 task-6] com.myApp.aop.logging.LoggingAspect : Exit: com.myApp.web.rest.errors.ExceptionTranslator.processRuntimeException() with result = <500 Internal Server Error,com.myApp.web.rest.errors.ErrorVM@1e3343c9,{}>
2016-09-29 17:20:51.601 WARN 5104 --- [ XNIO-2 task-6] .m.m.a.ExceptionHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type [Java.lang.String] to required type [com.myApp.common.SortEnum]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [Java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam com.myApp.common.SortEnum] for value 'somethingElse'; nested exception is Java.lang.IllegalArgumentException: No enum constant com.myApp.common.SortEnum.somethingElse
Existe-t-il un moyen d'empêcher Spring de lancer ces exceptions et de définir l'énumération sur null?
MODIFIER
La réponse acceptée de Strelok fonctionne. Cependant, j'ai décidé de m'occuper de la gestion de l'exception MethodArgumentTypeMismatchException.
@ControllerAdvice
public class ExceptionTranslator {
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseBody
public ResponseEntity<Object> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
Class<?> type = e.getRequiredType();
String message;
if(type.isEnum()){
message = "The parameter " + e.getName() + " must have a value among : " + StringUtils.join(type.getEnumConstants(), ", ");
}
else{
message = "The parameter " + e.getName() + " must be of type " + type.getTypeName();
}
return buildResponse(HttpStatus.UNPROCESSABLE_ENTITY, message);
}
Vous pouvez créer un convertisseur personnalisé qui renverra null
au lieu d'une exception lorsqu'une valeur non valide est fournie.
Quelque chose comme ça:
@Configuration
public class MyConfig extends WebMvcConfigurationSupport {
@Override
public FormattingConversionService mvcConversionService() {
FormattingConversionService f = super.mvcConversionService();
f.addConverter(new MyCustomEnumConverter());
return f;
}
}
Et un convertisseur simple pourrait ressembler à ceci:
public class MyCustomEnumConverter implements Converter<String, SortEnum> {
@Override
public SortEnum convert(String source) {
try {
return SortEnum.valueOf(source);
} catch(Exception e) {
return null; // or SortEnum.asc
}
}
}
vous devez faire ce qui suit
@InitBinder
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(YourEnum.class, new YourEnumConverter());
}
reportez-vous aux informations suivantes: https://machiel.me/post/Java-enums-as-request-parameters-in-spring-4/
Les réponses fournies jusqu'à présent ne sont pas complètes. Voici un exemple de réponse étape par étape qui a fonctionné pour moi: -
1st Définissez l'énumération dans votre signature de point final (type d'abonnement).
Exemple :
public ResponseEntity v1_getSubscriptions(@PathVariable String agencyCode,
@RequestParam(value = "uwcompany", required = false) String uwCompany,
@RequestParam(value = "subscriptiontype", required = false) SubscriptionType subscriptionType,
@RequestParam(value = "alert", required = false) String alert,
2nd Définissez un éditeur de propriétés personnalisé qui sera utilisé pour traduire de String en enum:
import Java.beans.PropertyEditorSupport;
public class SubscriptionTypeEditor extends PropertyEditorSupport {
public void setAsText(String text) {
try {
setValue(SubscriptionType.valueOf(text.toUpperCase()));
} catch (Exception ex) {
setValue(null);
}
}
}
3e Inscrivez l'éditeur de propriété avec le contrôleur:
@InitBinder ("subscriptiontype")
public void initBinder(WebDataBinder dataBinder) {
dataBinder.registerCustomEditor(SubscriptionType.class, new SubscriptionTypeEditor());
}
Les traductions de string en enum devraient se dérouler parfaitement maintenant.
Si vous utilisez Spring Boot, c’est la raison pour laquelle vous ne devez pas utiliser WebMvcConfigurationSupport
.
La meilleure pratique consiste à implémenter l'interface org.springframework.core.convert.converter.Converter
et avec l'annotation @Component
. Ensuite, Spring Boot chargera automatiquement tous les beans Converter
. Code de démarrage de printemps
@Component
public class GenderEnumConverter implements Converter<String, GenderEnum> {
@Override
public GenderEnum convert(String value) {
return GenderEnum.of(Integer.valueOf(value));
}
}