Handling Responses

About

OpenFeign abstracts HTTP client code by converting remote service APIs into Java interfaces. While it simplifies calling remote services, how we handle responses both success and error is critical for building resilient applications.

OpenFeign simplifies the handling of successful HTTP responses by automatically decoding them into Java objects. Depending on the method return type, OpenFeign delegates response parsing to the appropriate decoder, typically Jackson in Spring Cloud OpenFeign.

Supported Return Types

Return Type
Use Case / When to Use

Pojo (Java DTO)

Standard REST responses (JSON → Java object)

String

When we want the raw response body as a JSON/text string

byte[]

For binary responses like PDFs, images, etc.

feign.Response

For complete access to raw body, headers, status

List<Pojo>

For APIs returning an array or collection

Optional<Pojo>

For nullable responses (customized via fallback or decoder)

Map<String, Object>

For dynamic structures when DTO is not defined

1. Mapping JSON Response to a POJO

In Feign, mapping a JSON response to a POJO (Plain Old Java Object) is a common use case for handling successful HTTP responses. When Feign receives the HTTP response body (usually in JSON), it delegates the conversion of the response into a Java object to a message converter (typically Jackson).

Feign automatically deserializes the JSON response into the return type specified in the interface method this allows us to treat remote calls like local method invocations.

For this to work, ensure:

  • We have Jackson on the classpath (spring-boot-starter-web or spring-boot-starter-json)

  • The POJO has proper getters/setters and no-args constructor

  • The return type of our Feign method matches the expected structure of the JSON

Suppose the remote API returns the following JSON when querying a user:

We want to map this to a UserResponse Java object.

Step 1: Create the POJO

Step 2: Create the Feign Client Interface

Step 3: Use the Client in our Service

2. Getting Raw JSON as a String

Sometimes, we may not want to map the response body to a Java POJO — for example, when:

  • The structure of the JSON is dynamic or unknown

  • We want to log or cache the response as-is

  • We want to delay parsing or forward it to another service

Feign allows returning the raw JSON response as a String. When the return type is String, Feign does not attempt to deserialize the body; it just returns it as-is.

This approach is useful for:

  • Prototyping or debugging API responses

  • Custom parsing using a JSON library (e.g., Jackson, Gson)

  • Interacting with loosely defined APIs

Suppose the endpoint returns:

And we want to capture the entire JSON as a raw string.

Step 1: Define Feign Client Method

Step 2: Use in our Service

3. Accessing Full HTTP Response with feign.Response

By default, OpenFeign maps the HTTP response body to a method's return type (like String, custom POJO, etc.). However, sometimes we need to access the entire HTTP response, including:

  • Status code

  • Headers

  • Response body as bytes or string

  • Reason phrase

This is useful when:

  • We want to inspect or log headers or status codes

  • We are working with non-200 status responses (e.g., 204 No Content, 202 Accepted)

  • We need to read and parse raw response manually

  • We want to wrap the raw response for downstream processing

To achieve this, declare our method to return feign.Response, which is the low-level response representation provided by Feign.

Suppose the remote endpoint returns:

We can access all of it.

Step 1: Define Feign Client

Step 2: Use the Response

4. Receiving Binary Data (e.g., Images or PDFs)

When calling APIs that return binary content (like images, PDFs, or any file download), OpenFeign can return the raw response body as a byte stream, so we can write it to disk, pass it to another service, or convert it to a specific format (e.g., BufferedImage, File, etc.).

To support this:

  • Use feign.Response to get full control of the stream.

  • Use Response.body().asInputStream() to read the binary data.

  • Avoid mapping directly to String or POJO, since binary content may not be encoded as text or JSON.

Example: Downloading a PDF File

Step 1: Define Feign Client

Step 2: Download and Save the File

5. Handling List of Objects

Many REST APIs return a list of items instead of a single object — for example, a list of users, orders, or transactions. OpenFeign supports this out of the box as long as the response structure and return type in the interface match.

This is especially useful for:

  • Fetching all users/products/orders

  • Batch querying resources

  • Simple array-style responses from REST endpoints

Sample JSON Response

Model Class

Feign Client Interface

Service Usage

6. Returning Map or Generic Structures

When the JSON response structure is dynamic or unknown at compile time, we may prefer to deserialize the response into a generic structure like:

  • Map<String, Object> – for loosely structured key-value pairs

  • List<Map<String, Object>> – for lists of untyped records

  • Custom Map<String, T> – when values follow a known structure

Feign integrates well with Jackson, so it can automatically deserialize JSON into maps or collections using standard type inference.

This is especially useful when:

  • The API returns different keys per request (e.g., analytics, filters)

  • We need to pass through raw data to another system

  • We are writing a generic client or adapter for multiple services

Example: Returning a Map from JSON

Sample JSON Response

Step 1: Define Feign Client

Example: Returning a List of Maps

Example: Using in a Service Layer

7. Optional Return Types

Spring Cloud OpenFeign supports returning Optional<T> from client methods. This is useful when:

  • The remote service might return 404 or empty, and we don’t want to throw exceptions for that

  • We want to explicitly express absence of data rather than returning null

  • It encourages null-safe handling at the consumer side

This pattern is especially valuable when integrating with internal services, where a missing record is not necessarily an error.

However, Optional<T> only works reliably when:

  • We are using Spring Cloud >= 2020.x or newer

  • The response body is actually empty or null for 404 (i.e., not a structured error response)

Example 1: Return Optional from GET Request

Feign Client Interface

Example 2: Consuming the Optional in Service

Model Example

Custom Wrapper Example

In many real-world APIs, especially internal microservices, responses are wrapped inside a common envelope or container for consistency. These wrappers typically contain:

  • The actual payload

  • Metadata like status, message, timestamps, etc.

This pattern simplifies error handling, logging, and standardizes API contracts.

Example Custom Wrapper

A typical wrapper class might look like:

To handle such structures with OpenFeign, our client must define the return type using a POJO that reflects this wrapper.

Wrapper Class Example

Model Class

Feign Client Interface

Service Usage

Last updated