Home » Java » Enterprise Java » Spring 4.1 and Java 8: java.util.Optional

About Rafal Borowiec

Rafal Borowiec
Software developer, Team Leader, Agile practitioner, occasional blogger, lecturer. Open Source enthusiast, quality oriented and open-minded.

Spring 4.1 and Java 8: java.util.Optional

As of Spring 4.1 Java 8’s java.util.Optional, a container object which may or may not contain a non-null value, is supported with @RequestParam, @RequestHeader and @MatrixVariable. While using Java 8’s java.util.Optional you make sure your parameters are never null.


Request Params

In this example we will bind java.time.LocalDate as java.util.Optional using @RequestParam:

public class SampleController {

    @RequestMapping(value = "r", produces = "text/plain")
    public String requestParamAsOptional(
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
            @RequestParam(value = "ld") Optional<LocalDate> localDate) {

        StringBuilder result = new StringBuilder("ld: ");
        localDate.ifPresent(value -> result.append(value.toString()));
        return result.toString();

Prior to Spring 4.1, we would get an exception that no matching editors or conversion strategy was found. As of Spring 4.1, this is no more an issue. To verify the binding works properly, we may create a simple integration test:

@SpringApplicationConfiguration(classes = Application.class)
public class SampleSomeControllerTest {

    private WebApplicationContext wac;
    private MockMvc mockMvc;

    public void setUp() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();

    // ...


In the first test, we will check if the binding works properly and if the proper result is returned:

public void bindsNonNullLocalDateAsRequestParam() throws Exception {
    mockMvc.perform(get("/o/r").param("ld", "2020-01-01"))
            .andExpect(content().string("ld: 2020-01-01"));

In the next test, we will not pass ld parameter:

public void bindsNoLocalDateAsRequestParam() throws Exception {
            .andExpect(content().string("ld: "));

Both tests should be green!

Request Headers

Similarly, we can bind @RequestHeader to java.util.Optional:

@RequestMapping(value = "h", produces = "text/plain")
public String requestHeaderAsOptional(
        @RequestHeader(value = "Custom-Header") Optional<String> header) {

    StringBuilder result = new StringBuilder("Custom-Header: ");
    header.ifPresent(value -> result.append(value));

    return result.toString();

And the tests:

public void bindsNonNullCustomHeader() throws Exception {
    mockMvc.perform(get("/o/h").header("Custom-Header", "Value"))
            .andExpect(content().string("Custom-Header: Value"));

public void noCustomHeaderGiven() throws Exception {
    mockMvc.perform(get("/o/h").header("Custom-Header", ""))
            .andExpect(content().string("Custom-Header: "));

Matrix Variables

Introduced in Spring 3.2 @MatrixVariable annotation indicates that a method parameter should be bound to a name-value pair within a path segment:

@RequestMapping(value = "m/{id}", produces = "text/plain")
public String execute(@PathVariable Integer id,
                      @MatrixVariable Optional<Integer> p,
                      @MatrixVariable Optional<Integer> q) {

    StringBuilder result = new StringBuilder();
    result.append("p: ");
    p.ifPresent(value -> result.append(value));
    result.append(", q: ");
    q.ifPresent(value -> result.append(value));

    return result.toString();

The above method can be called via /o/m/42;p=4;q=2 url. Let’s create a test for that:

public void bindsNonNullMatrixVariables() throws Exception {
            .andExpect(content().string("p: 4, q: 2"));

Unfortunatelly, the test will fail, because support for @MatrixVariable annotation is disabled by default in Spring MVC. In order to enable it we need to tweak the configuration and set the removeSemicolonContent property of RequestMappingHandlerMapping to false. By default it is set to true. I have done with WebMvcConfigurerAdapter like below:

public class WebMvcConfig extends WebMvcConfigurerAdapter {
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();

And now all tests passes! Please find the source code for this article here: https://github.com/kolorobot/spring41-samples

Reference: Spring 4.1 and Java 8: java.util.Optional from our JCG partner Rafal Borowiec at the Codeleak.pl blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!


1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design


and many more ....


Receive Java & Developer job alerts in your Area


Leave a Reply

1 Comment on "Spring 4.1 and Java 8: java.util.Optional"

Notify of
Sort by:   newest | oldest | most voted
Sriram Tanikella

Excellent article. Thanks a lot for sharing your knowledge.