implementation("io.micronaut.problem: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
<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:
Property | Type | Description |
---|---|---|
|
boolean |
Sets whether the configuration is enabled. Default value true. |
|
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: