Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Controllers and routes

A controller is a class that accepts HTTP requests and returns responses. Each of its methods serves one route: a combination of an HTTP method (GET, POST, DELETE…) and an address. Micronaut finds controllers by itself: the annotation processor records all routes at compile time, so no registration is needed.

The first controller

Create the file by hand or with mn create-controller com.example.Hello (it also creates a test stub):

// src/main/java/com/example/HelloController.java
package com.example;
 
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
 
@Controller("/hello")
public class HelloController {
 
    @Get
    @Produces(MediaType.TEXT_PLAIN)
    public String index() {
        return "Hello, Micronaut!";
    }
}

@Controller("/hello") sets the class's base address, and @Get without an argument is a route on that address itself. @Produces(MediaType.TEXT_PLAIN) says the response is plain text: by default Micronaut answers in JSON.

curl -i http://localhost:8080/hello
HTTP/1.1 200 OK
content-type: text/plain
 
Hello, Micronaut!

Parts of the address

A fragment in curly braces is a path variable. Its value arrives in the method parameter with the same name:

// src/main/java/com/example/HelloController.java
@Get("/{name}")
@Produces(MediaType.TEXT_PLAIN)
public String greet(String name) {
    return "Hello, " + name + "!";
}

The request curl http://localhost:8080/hello/Anna returns Hello, Anna!.

The article controller

Let's start the blog's main controller. For now it returns text; data arrives in the next lessons:

// src/main/java/com/example/ArticleController.java
package com.example;
 
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Delete;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Produces;
 
@Controller("/articles")
@Produces(MediaType.TEXT_PLAIN)
public class ArticleController {
 
    @Get
    public String list() {
        return "All articles";
    }
 
    @Get("/{id}")
    public String show(Long id) {
        return "Article " + id;
    }
 
    @Delete("/{id}")
    public HttpResponse<Void> delete(Long id) {
        return HttpResponse.noContent();
    }
}

@Produces on the class applies to all methods. HttpResponse.noContent() returns an empty response with status 204. Check it:

curl http://localhost:8080/articles/5
curl -i -X DELETE http://localhost:8080/articles/5

The first command prints Article 5, the second prints HTTP/1.1 204 No Content.

Method annotations

AnnotationHTTP methodTypical action
@GetGETRead data
@PostPOSTCreate a record
@PutPUTReplace a record
@PatchPATCHChange part of a record
@DeleteDELETEDelete a record

They all live in the io.micronaut.http.annotation package.

Common mistake

If you send a request with a method that has no route, Micronaut answers 405 and tells you which methods are allowed:

curl -i -X POST http://localhost:8080/articles
HTTP/1.1 405 Method Not Allowed
allow: HEAD,GET
 
{"_links":{"self":[{"href":"/articles","templated":false}]},"_embedded":{"errors":[{"message":"Method [POST] not allowed for URI [/articles]. Allowed methods: [HEAD, GET]"}]},"message":"Method Not Allowed"}

Check that the method carries the right HTTP method annotation, and that the address in @Controller plus the one in the method annotation add up to the path you are calling.

Thanks for reading!

Donate to the site — we work hard for you.