The documentation you are viewing is not the latest documentation of Micronaut Problem Json

Micronaut Problem JSON

Produce application/problem+json responses from a Micronaut application.

Version:

1 Introduction

Micronaut Problem is a library which makes it easy to produce application/problem+json responses from a Micronaut application. It connects the Problem library and Micronaut Error Formatting capabilities.

2 Release History

For this project, you can find a list of releases (with release notes) here:

3 Installation

implementation("io.micronaut.problem:micronaut-problem-json")
<dependency>
    <groupId>io.micronaut.problem</groupId>
    <artifactId>micronaut-problem-json</artifactId>
</dependency>

4 Usage

This library registers ProblemErrorResponseProcessor; an ErrorResponseProcessor for Problem. It sets the response content type to application/problem+json and the response HTTP Status code to match the status field for Problem.

Moreover, it registers ThrowableProblemHandler. A Micronaut ErrorHandler for handling ThrowableProblem exception.

4.1 Problem Builder

You can use Problem builder to create problem:

package io.micronaut.problem;

import io.micronaut.http.HttpStatus;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.Status;
import org.zalando.problem.Problem;

import java.net.URI;

@Controller("/product")
public class ProductController {
    @Get
    @Status(HttpStatus.OK)
    public void index() {
        throw Problem.builder()
                .withType(URI.create("https://example.org/out-of-stock"))
                .withTitle("Out of Stock")
                .withStatus(new HttpStatusType(HttpStatus.BAD_REQUEST))
                .withDetail("Item B00027Y5QG is no longer available")
                .with("product", "B00027Y5QG")
                .build();
    }
}
package io.micronaut.problem

import io.micronaut.http.HttpStatus
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Status
import org.zalando.problem.Problem

@Controller("/product")
class ProductController {
    @Get
    @Status(HttpStatus.OK)
    void index() {
        throw Problem.builder()
                .withType(URI.create("https://example.org/out-of-stock"))
                .withTitle("Out of Stock")
                .withStatus(new HttpStatusType(HttpStatus.BAD_REQUEST))
                .withDetail("Item B00027Y5QG is no longer available")
                .with("product", "B00027Y5QG")
                .build()
    }
}
package io.micronaut.problem

import io.micronaut.http.HttpStatus
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.Status
import org.zalando.problem.Problem
import java.net.URI

@Controller("/product")
class ProductController {
    @Get
    @Status(HttpStatus.OK)
    fun index() {
        throw Problem.builder()
                .withType(URI.create("https://example.org/out-of-stock"))
                .withTitle("Out of Stock")
                .withStatus(HttpStatusType(HttpStatus.BAD_REQUEST))
                .withDetail("Item B00027Y5QG is no longer available")
                .with("product", "B00027Y5QG")
                .build()
    }
}

The above snippet returns:

{
    "status": 400,
    "title": "Out of Stock",
    "detail": "Item B00027Y5QG is no longer available",
    "type": "https://example.org/out-of-stock",
    "parameters": {"product": "B00027Y5QG"}
}

4.2 Custom Problem

You can create a custom problem by extending AbstractThrowableProblem

package io.micronaut.problem;

import io.micronaut.http.HttpStatus;
import org.zalando.problem.AbstractThrowableProblem;

import java.net.URI;

public class TaskNotFoundProblem extends AbstractThrowableProblem {

    private static final URI TYPE = URI.create("https://example.org/not-found");

    public TaskNotFoundProblem(Long taskId) {
        super(TYPE, "Not found", new HttpStatusType(HttpStatus.NOT_FOUND), String.format("Task '%s' not found", taskId));
    }
}
package io.micronaut.problem

import io.micronaut.http.HttpStatus
import org.zalando.problem.AbstractThrowableProblem

class TaskNotFoundProblem extends AbstractThrowableProblem {

    private static final URI TYPE = URI.create("https://example.org/not-found")

    TaskNotFoundProblem(Long taskId) {
        super(TYPE, "Not found", new HttpStatusType(HttpStatus.NOT_FOUND), String.format("Task '%s' not found", taskId))
    }
}
package io.micronaut.problem

import com.fasterxml.jackson.annotation.JsonIgnore
import io.micronaut.http.HttpStatus
import org.zalando.problem.AbstractThrowableProblem
import org.zalando.problem.Exceptional
import java.net.URI

class TaskNotFoundProblem(taskId: Long) :
        AbstractThrowableProblem(URI.create("https://example.org/not-found"),
                "Not found",
                HttpStatusType(HttpStatus.NOT_FOUND),
                String.format("Task '%s' not found", taskId)) {

    @JsonIgnore
    override fun getCause(): Exceptional {
        TODO("Not yet implemented")
    }
}

If your logic throws such a Problem:

package io.micronaut.problem;

import io.micronaut.http.HttpStatus;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.annotation.PathVariable;
import io.micronaut.http.annotation.Status;

@Controller("/task")
public class TaskController {
    @Get("/{taskId}")
    @Status(HttpStatus.OK)
    public void index(@PathVariable Long taskId) {
        throw new TaskNotFoundProblem(taskId);
    }
}
package io.micronaut.problem

import io.micronaut.http.HttpStatus
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.PathVariable
import io.micronaut.http.annotation.Status

@Controller('/task')
class TaskController {
    @Get('/{taskId}')
    @Status(HttpStatus.OK)
    void index(@PathVariable Long taskId) {
        throw new TaskNotFoundProblem(taskId)
    }
}
package io.micronaut.problem

import io.micronaut.http.HttpStatus
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import io.micronaut.http.annotation.PathVariable
import io.micronaut.http.annotation.Status

@Controller("/task")
class TaskController {
    @Get("/{taskId}")
    @Status(HttpStatus.OK)
    fun index(@PathVariable taskId: Long) {
        throw TaskNotFoundProblem(taskId)
    }
}

You will get:

{
    "status": 404,
    "title": "Not found",
    "detail": "Task '3' not found",
    "type": "https://example.org/not-found"
}

5 Configuration

You can configure it via:

🔗
Table 1. Configuration Properties for ProblemConfigurationProperties
Property Type Description

problem.enabled

boolean

Sets whether the configuration is enabled. Default value true.

problem.stack-trace

boolean

Whether the HTTP Response should include the stack trace for instances of {@link org.zalando.problem.ThrowableProblem}. Default value (false).

6 Repository

You can find the source code of this project in this repository: