OpenFeign / feign

Feign makes writing java http clients easier
Apache License 2.0
9.43k stars 1.92k forks source link

[Question] POST JSON body using POJO #1852

Closed rmonvfer closed 1 year ago

rmonvfer commented 1 year ago

Hi,

I'm developing a REST API client using Feign. This API consumes and emits JSON objects which are serialized and deserialized as POJOs by the client.

To log into the API I just have to send a POST request to the /oauth/token endpoint with the following body:

{
    "oauthClientId": "string",
    "oauthClientSecret" : "string",
    "grantType": "string",
    "scope": "string",
    "redirectUri": "string" 
}

Its correspondent POJO (note that I'm using lombok):

@Data
@Accessors(fluent = true)
public class Credentials {
    String oauthClientId;
    String oauthClientSecret;
    String grantType;
    String redirectUri;
    String scope;
}

The response looks body:

{
    "access_token": "string",
    "expires_in": "string",
    "scope": "string",
    "token_type": "string"
}

Which is deserialized into:

@Data
public class LoginResponse {
    @NonNull
    String access_token;
    String expires_in;
    String scope;
    String token_type;
}

My Feign interface looks like

@Headers({
    "Accept: application/json",
    "Content-Type: application/x-www-form-urlencoded"
})
public interface Api {
    @RequestLine("POST /oauth/token")
    @Headers("Content-Type: application/json")
    LoginResponse login(Credentials credentials);
}

And it's initialized in the following way (simplified class):

public class Client {
    // ...
    private Api api;

    public Client(String baseUrl, Credentials loginCredentials) {
        //..
        this.api = Feign.builder()
            .decoder(new GsonDecoder())
            .target(Api.class, baseUrl);

        LoginResponse loginResponse = this.api.login(loginCredentials);
        //...
    }
}

When the Client is initialized (thus calling the login method) an exception is thrown:

feign.codec.EncodeException: class *.*.Credentials is not a type supported by this encoder.

According to the examples (create an Issue using a POST request) it should be possible to use a POJO as a JSON body, is this assumption correct? Do I need to configure feign in a specific way to achieve this (maybe add a custom decoder)?

Thanks, Ramón

vitalijr2 commented 1 year ago

The GsonDecoder class is used to process the response. You need to use GsonEncoder instead.

rmonvfer commented 1 year ago

Thank you! I was able to make it work by adding .encoder(new GsonEncoder()) in Feign.builder().