Forwarding Upstream Problems
When a Micronaut service calls another service that itself returns application/problem+json, the default behaviour is for the Micronaut HTTP client to throw an HttpClientResponseException.
That exception loses the structured information (code, info, level, detail) that the upstream service carefully attached.
The conta-problem-json-mn-client module provides the @ForwardClientProblem annotation, which intercepts the failed call, deserializes the response body as a Problem, and rethrows it as a ThrowableProblem so the same problem propagates out of the calling service to its own client.
Wiring it up
Annotate either the @Client interface or an individual method:
package no.conta.problem.micronaut.example;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.client.annotation.Client;
import no.conta.problem.micronaut.client.ForwardClientProblem;
@Client("/")
@ForwardClientProblem
public interface PetClient {
@Get("/pets/{name}")
Pet findByName(String name);
}
Now any findByName(…) call that fails with an HTTP error response (4xx/5xx) and a body deserializable as a Problem is rethrown as a ThrowableProblem carrying the same status, code, detail, and info as the upstream error.
If the body cannot be deserialized as a Problem, the original HttpClientResponseException is rethrown unchanged.
The interceptor only handles HTTP-level failures (HttpClientResponseException).
Network errors, connect/read timeouts, and other client exceptions are not intercepted — handle those separately if needed.
When to use it
Use it on internal service-to-service clients where it’s correct for the calling service to return the same problem to its caller — typically gateway-style services that delegate to a backend.
Avoid it where the calling service should map upstream failures into its own domain-specific problem codes — in that case, catch HttpClientResponseException (or use Micronaut’s @Fallback / error handling) and translate explicitly.