1. Introduction
In most typical web applications, we often need to restrict a request parameter to a set of predefined values. Enums are a great way to do this.
In this quick tutorial, we'll show how to use enums as web request parameters in Spring MVC.
2. Use Enums as Request Parameters
Let's first define an enum for our examples:
public enum Modes { ALPHA, BETA; }
We can then use this enum as a RequestParameter in a Spring controller:
@GetMapping("/mode2str") public String getStringToMode(@RequestParam("mode") Modes mode) { // ... }
Or we can use it as a PathVariable:
@GetMapping("/findbymode/{mode}") public String findByEnum(@PathVariable("mode") Modes mode) { // ... }
When we make a web request, such as /mode2str?mode=ALPHA, the request parameter is a String object. Spring can try to convert this String object to an Enum object by using its StringToEnumConverterFactory class.
The back-end conversion uses the Enum.valueOf method. Therefore, the input name string must exactly match one of the declared enum values.
When we make a web request with a string value that doesn't match one of our enum values, for example, /mode2str?mode=unknown, Spring will fail to convert it to the specified enum type. In this case, we'll get a ConversionFailedException.
3. Custom Converter
In Java, it's considered good practice to define enum values with uppercase letters, as they are constants. However, we may want to support lowercase letters in the request URL.
In this case, we need to create a custom converter:
public class StringToEnumConverter implements Converter<String, Modes> { @Override public Modes convert(String source) { return Modes.valueOf(source.toUpperCase()); } }
To use our custom converter, we need to register it in the Spring configuration:
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new StringToEnumConverter()); } }
4. Exception Handling
The Enum.valueOf method in the StringToEnumConverter will throw an IllegalArgumentException if our Modes enum has no matched constant. We can handle this exception in our custom converter in different ways, depending on requirements.
For example, we can simply have our converter return null for non-matching Strings:
public class StringToEnumConverter implements Converter<String, Modes> { @Override public Modes convert(String source) { try { return Modes.valueOf(source.toUpperCase()); } catch (IllegalArgumentException e) { return null; } } }
However, if we don't handle the exception locally in the custom converter, Spring will throw a ConversionFailedException exception to the calling controller method. There are several ways to handle this exception.
For example, we can use a global exception handler class:
@ControllerAdvice public class GlobalControllerExceptionHandler { @ExceptionHandler(ConversionFailedException.class) public ResponseEntity<String> handleConflict(RuntimeException ex) { return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST); } }
5. Conclusion
In this article, we showed how to use enums as request parameters in Spring with some code examples.
We also provided a custom converter example that can map the input string to an enum constant.
Finally, we discussed how to handle the exception thrown by Spring when it encounters an unknown input string.
As always, the source code for the tutorial is available over on GitHub.