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 demonstrate 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, like /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 doesn’t have a matched constant. We can handle this exception in our custom converter in different ways, depending on our 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 brief article, we learned 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 this article is available over on GitHub.