Skip to content

[BUG][JAVA][restclient] useJackson3: generated RestClient is missing Spring's default message converters (follow-up to #23354) #24587

Description

@anatoly-tamarack

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

With useJackson3=true, buildRestClientBuilder never calls registerDefaults(), so the generated
RestClient carries 2 of Spring's 5 default converters. ByteArray, String and Resource are
missing, and any operation the generator emits with one of those return types fails on read. The
useJackson3=false branch of the same template is unaffected — it hands its converter to an API
that starts from the defaults:

{{#useJackson3}}
builder.addCustomConverter(new JacksonJsonHttpMessageConverter(mapper));   // starts empty
return RestClient.builder().configureMessageConverters(messageConverters);

{{^useJackson3}}
converters.add(0, new MappingJackson2HttpMessageConverter(mapper));        // starts with defaults
return RestClient.builder().messageConverters(messageConverters);

Follow-up to #23354, which reported the stronger symptom (no converters at all, JSON included) and
was closed pending spring-projects/spring-framework#36579, fixed in Spring 7.0.7. #23588 separately
switched withJsonConverteraddCustomConverter, which also made JSON work. JSON is fixed twice
over; the non-JSON defaults were never restored.

Actual vs expected output

Converters on the built client, spring-web 7.0.8 (Spring fix in place):

addCustomConverter only              (master today) -> 2 [JacksonJson, Form]
registerDefaults + addCustomConverter                -> 6 [JacksonJson, ByteArray, String, Resource, Form, JacksonJson]
registerDefaults + withJsonConverter    (expected)   -> 5 [ByteArray, String, Resource, Form, JacksonJson]
plain RestClient.builder().build()                   -> 5 [ByteArray, String, Resource, Form, JacksonJson]

Calling the generated CSV operation against a server responding text/csv:

org.springframework.web.client.UnknownContentTypeException: Could not extract response:
  no suitable HttpMessageConverter found for response type
  [interface org.springframework.core.io.Resource] and content type [text/csv]
    at DefaultRestClient.readWithMessageConverters(DefaultRestClient.java:263)
    at com.example.client.api.ReportControllerApi.getReportCsv(ReportControllerApi.java:496)

The generator emits a method returning Resource, then builds a client that cannot read one.

openapi-generator version

7.23.0, and still present in ApiClient.mustache on master (verified by reading the template, not by
building master). Regression relative to useJackson3=false; root cause unchanged since #23023.

OpenAPI declaration file content or url
openapi: 3.0.3
info: { title: repro, version: "1.0.0" }
paths:
  /reports/{id}/csv:
    get:
      operationId: getReportCsv
      parameters:
        - { name: id, in: path, required: true, schema: { type: string } }
      responses:
        "200":
          description: CSV export
          content:
            text/csv:
              schema: { type: string, format: binary }
Generation Details
generatorName: java
library: restclient
additionalProperties:
  useSpringBoot4: "true"
  useJackson3: "true"

Spring Framework 7.0.8 / Spring Boot 4, Jackson 3.1.5, Java 25.

Steps to reproduce
  1. Generate the spec above with the config above.
  2. ApiClient client = new ApiClient(ApiClient.buildRestClientBuilder().build()).setBasePath(...);
  3. getReportCsv("x") against a server responding text/csvUnknownContentTypeException.
  4. Regenerate with useJackson3=false → the same call succeeds.
Related issues/PRs
Suggest a fix

Register the defaults, and — now that spring-framework#36579 is fixed — use withJsonConverter so
the generated mapper replaces the default JSON converter rather than duplicating it:

Consumer<HttpMessageConverters.ClientBuilder> messageConverters = builder -> {
    builder.registerDefaults()
           .withJsonConverter(new JacksonJsonHttpMessageConverter(mapper));
    {{#withXml}}
    builder.withXmlConverter(new JacksonXmlHttpMessageConverter(xmlMapper));
    {{/withXml}}
};

That gives the same 5 converters as RestClient.builder().build() with the generated mapper
substituted in. It implies a Spring 7.0.7 floor; if that's not acceptable,
registerDefaults().addCustomConverter(...) also works, at the cost of a duplicate JSON converter.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions