OpenAPITools / OpenAPITools/openapi-generator

[BUG] Method ApiClient.setObjectMapper() does not properly set a custom ObjectMapper in the Feing client

Open
#14,313 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Description

I would like to use a ObjectMapper with custom configuration , but when I try to set it with method ApiClient.setObjectMapper() the Feign Client does not take it.

The problem happens inside the generated code - class ApiClient.

The Feign Client is created in the constructor:

    public ApiClient() {
        this.basePath = "https://localhost:8080/users";
        this.objectMapper = this.createObjectMapper();
        this.apiAuthorizations = new LinkedHashMap();
        this.feignBuilder = Feign.builder().client(new OkHttpClient()).encoder(new FormEncoder(new JacksonEncoder(this.objectMapper))).decoder(new ApiResponseDecoder(this.objectMapper)).logger(new Slf4jLogger());
    }

and so if you call method setObjectMapper() after that, it is not applied:

public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

the method buildClient() uses the Feign Client with default ObjectMapper:

    public <T extends ApiClient.Api> T buildClient(Class<T> clientClass) {
        return (ApiClient.Api)this.feignBuilder.target(clientClass, this.basePath);
    }
openapi-generator version

These are the related dependencies for both generator and client application:

        <openapi-generator-maven-plugin.version>6.2.1</openapi-generator-maven-plugin.version>
        <feign.version>10.11</feign.version>
        <feign-form.version>3.8.0</feign-form.version>
        <jackson.version>2.13.4</jackson.version>
        <jackson-databind-nullable.version>0.2.4</jackson-databind-nullable.version>
        <jackson-databind.version>2.13.4.2</jackson-databind.version>
Generation Details

The code is generated with OpenAPI Maven Plugin with this configuration:

 <build>
        <plugins>
            <plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>${openapi-generator-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <id>generate-api-code-client-java</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/../openapi.yaml</inputSpec>
                            <generatorName>java</generatorName>
                            <configOptions>
                                <invokerPackage>${project.groupId}.${project.artifactId}</invokerPackage>
                                <apiPackage>${project.groupId}.${project.artifactId}.api</apiPackage>
                                <modelPackage>${project.groupId}.${project.artifactId}.model</modelPackage>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>${project.artifactId}</artifactId>
                                <sourceFolder>src/gen/java/main</sourceFolder>
                                <dateLibrary>java8</dateLibrary>
                                <library>feign</library>
                                <java8>true</java8>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
Steps to reproduce

The next code snippet illustrates the error:

// This is the ObjectMapper with custom config
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyArray, CoercionAction.AsEmpty);
objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyObject, CoercionAction.AsNull);

// This is the ApiClient creation and setup
ApiClient defaultClient = new ApiClient();
defaultClient.setBasePath(baseURL);
defaultClient.setObjectMapper(objectMapper); // here the mapper should be set
UsersApi = defaultClient.buildClient(UsersApi.class);
api.getUsers(); // here the mapper should be used but throws error as custom config is not applied
// i.e. com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce empty String ("")
Suggest a fix

I think the method setObjectMapper() or the method buildClient() should force the rebuild of Feign Client when a custom mapper has been set.

The only workaround I found is creating a new Feign Client and setting it with method setFeignBuilder():

Builder feignBuilder = Feign.builder().client(new OkHttpClient()).encoder(new FormEncoder(new JacksonEncoder(objectMapper))).decoder(new ApiResponseDecoder(objectMapper)).logger(new Slf4jLogger());
defaultClient.setFeignBuilder(feignBuilder);

I think this is not a proper solution as the only part that needs to be set is the ObjectMapper.

Maybe there is an easier way to do it but I have not found it, I appreciate any help with this.

Thanks in advance!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the generated ApiClient constructor, setObjectMapper(), and buildClient() shown in the issue, then locate the Java Feign generator template that produces them. Reproduce the custom ObjectMapper setup and verify that a client built afterward uses it instead of the default mapper.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.