Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Request parameters

A client sends data not only in the request body but also in the address itself: /articles/5 is a path variable, /search?q=java&page=2 holds query string parameters (everything after the ? sign). Some information also arrives in headers. Micronaut maps all of this onto method parameters and converts the strings to the right types for you.

Where values come from

AnnotationSource of the valueExample address
@PathVariableThe part of the path in curly braces/search/tag/java
@QueryValueThe query string after ?/search?q=java
@HeaderA request headerUser-Agent: curl/8.21.0

For a path variable the annotation is optional: Micronaut fills a parameter whose name matches {id} in the address by itself. The annotation just makes the code clearer.

A search controller

Create a file for searching the blog:

// src/main/java/com/example/SearchController.java
package com.example;
 
import io.micronaut.core.annotation.Nullable;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Header;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.annotation.Produces;
import io.micronaut.http.annotation.QueryValue;
 
@Controller("/search")
@Produces(MediaType.TEXT_PLAIN)
public class SearchController {
 
    @Get
    public String search(@QueryValue String q,
                         @QueryValue(defaultValue = "1") int page) {
        return "Searching for '" + q + "', page " + page;
    }
 
    @Get("/tag/{tag}")
    public String byTag(@PathVariable String tag, @QueryValue @Nullable String sort) {
        return "Tag " + tag + ", sort: " + (sort == null ? "none" : sort);
    }
 
    @Get("/client")
    public String client(@Header("User-Agent") String userAgent) {
        return "Your client: " + userAgent;
    }
}

The q parameter is required, page has a default value, and sort is marked @Nullable: when it is missing, you get null. The string "2" from the address becomes an int automatically.

Trying it out

curl "http://localhost:8080/search?q=micronaut"
curl "http://localhost:8080/search?q=micronaut&page=2"
curl "http://localhost:8080/search/tag/java?sort=new"
curl http://localhost:8080/search/client
Searching for 'micronaut', page 1
Searching for 'micronaut', page 2
Tag java, sort: new
Your client: curl/8.21.0

Put an address containing & in quotes, otherwise the shell splits it into two commands.

Wrong type

If a value cannot be converted to the parameter's type, the method is not called and the client gets 400:

curl "http://localhost:8080/search?q=x&page=two"
{"_links":{"self":[{"href":"/search?q=x&page=two","templated":false}]},"_embedded":{"errors":[{"message":"Failed to convert argument [page] for value [two] due to: For input string: \"two\"","path":"/page"}]},"message":"Bad Request"}

The same happens with /articles/abc when the id parameter is declared as Long.

Common mistake

Micronaut treats a parameter without @Nullable and without a default value as required. A request without it gets 400:

curl http://localhost:8080/search
{"_links":{"self":[{"href":"/search","templated":false}]},"_embedded":{"errors":[{"message":"Required QueryValue [q] not specified","path":"/q"}]},"message":"Bad Request"}

If the parameter is optional by meaning, add @Nullable (from the io.micronaut.core.annotation package) or a defaultValue.

Thanks for reading!

Donate to the site — we work hard for you.