Skip to content

[JAVA] Add generic okhttp client - #24734

Open
rar91279 wants to merge 36 commits into
OpenAPITools:masterfrom
rar91279:java-generic-okhttp
Open

[JAVA] Add generic okhttp client #24734
rar91279 wants to merge 36 commits into
OpenAPITools:masterfrom
rar91279:java-generic-okhttp

Conversation

@rar91279

@rar91279 rar91279 commented Aug 19, 2026

Copy link
Copy Markdown

Adds a new okhttp library to the Java client generator, marked [BETA]. It is derived from
okhttp-gson, but decoupled from Gson: a single template set emits working clients for Gson
(default), Jackson 2, Jackson 3 and JSON-B
, on OkHttp 5.4.0, and it honours the existing
useJspecify option.

okhttp-gson is untouched and remains the default library — its generated output is byte-identical
to master. This is purely additive for existing users; the new library is opt-in via
--library okhttp.

openapi-generator generate -g java --library okhttp \
  -p serializationLibrary=jackson -p useJackson3=true -p useJspecify=true

JavaClientCodegen

  • Registers the library, adds it to JSPECIFY_SUPPORTED_LIBRARIES and to the useJackson3
    allowlist, and reuses the okhttp-gson supporting-file branch without forcing a serialization
    library.
  • Resolves isGson/isJackson/isJsonb after the serialization switch, where
    getSerializationLibrary() is authoritative. No new early property reads, so no behavioural risk
    to other libraries.
  • Forces openApiNullable off for JSON-B: jackson-databind-nullable is Jackson-only and the pom
    omits it there, so leaving the flag on emitted JsonNullable references that could not resolve.
  • Applies the x-enum-as-string discriminator rewrite for every serialization library, not just
    Jackson. This is not a Jackson nicety — a child schema that narrows an inherited discriminator to
    a single-value enum otherwise generates a getter that cannot override the parent's String
    getter. JsonNullable/JsonIgnore imports stay Jackson-only.
  • Extends useSingleRequestParameter and the oneOf/anyOf ModelNull handling to the new
    library; both were gated on allowlists that excluded it, even though its templates support them.

Samples — 27 configs covering the four serialization variants, JSpecify for each of Jackson 2/3
and JSON-B, oneOf/anyOf, nullable-required, AWS4 signing, dynamic operations, grouped
parameters, parcelable models, streaming, Swagger 1/2 annotations, OpenAPI 3.1, the echo API and
user-defined templates.

One renamebin/configs/java-okhttp-user-defined-templates.yaml
java-okhttp-gson-user-defined-templates.yaml. It generated the okhttp-gson sample despite the
neutral name, and every other okhttp-gson config is already named java-okhttp-gson-*. Content
unchanged, generated sample untouched.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

@bbdouglas @sreeshas @jfiala @lukoyanov @cbornet @jeff9finger @karismann @Zomzog @lwlee2608 @martin-mfg @KannaKim


Summary by cubic

Adds a new okhttp Java client library that generates OkHttp 5.4.0 clients for Gson (default), Jackson 2/3, and JSON-B. okhttp-gson remains the default and byte-identical; the new library is opt-in via --library okhttp. Standardizes discriminator handling and fixes correctness issues in the new templates.

Codegen and templates

  • Registers okhttp in JavaClientCodegen, resolves serializer flags after serializationLibrary, extends useSingleRequestParameter and oneOf/anyOf null handling, delegates model symbol imports to avoid duplicate import lines, and rejects the boolean defaultToEmptyContainer=true spelling (it silently inverted the option).
  • Forces openApiNullable=false across the library and applies the x-enum-as-string discriminator rewrite across all serializers.
  • New Java/libraries/okhttp/* templates provide per-client JSON config, payload bytes passed to auth, AWS4 signed last, and RetryingOAuth on OkHttp (no Apache Oltu).
  • JSON-B gains custom serializers for discriminator hierarchies, flattened additional properties, and required-property validation that binds property-by-property (rejects undeclared fields, survives nesting, and applies at discriminator roots); oneOf wrappers get composed fromJson/toJson helpers.

Correctness, samples, and CI

  • Fixes gzip content length restoration plus AWS4-safe compression (skips gzip for SigV4 and replays compressed uploads in segments so progress stays truthful), progress body/source memoization and one-shot/duplex delegation, x-amz-* header signing, RFC3339 date module for Jackson 2/3 (built locally so Jackson 2 lenient parsing takes effect), @JsonbTransient additionalProperties, response-header lowercasing with Locale.ROOT, bearer-token NPE, null params in dynamic operations, and resource leaks in the download path (bodies and sinks close on mid-copy failures and responses close on failures). Jackson readOnly properties now deserialize (READ_ONLY access dropped, constructor annotated), generateBuilders/generateConstructorWithAllArgs now generate, performBeanValidation keeps required-parameter null checks, date-only legacy values no longer shift a day, and JSON-B compiles with dateLibrary=joda (joda adapters registered unconditionally).
  • Composed models validate branches against mismatched deserialization, JSON-B validation no longer NPEs when configured before the first JSON instance is built, JSON-B additional properties survive nested hierarchy roots and cannot shadow a subtype's declared field name, and build files now declare the Jackson Joda datatype module so dateLibrary=joda Jackson clients compile.
  • Adds 27 okhttp sample configs across Gson/Jackson 2/3/JSON-B, JSpecify, oneOf/anyOf, streaming, AWS4, OpenAPI 3.1, grouped params, dynamic operations, and parcelable. The Jackson 2/3 and JSON-B samples now generate from the same spec as the Gson sample (previously the http-signature spec), which exposed and fixed JSON-B gaps: a File adapter, @JsonbTransient in composed models, and composed deserializers handling arrays and scalar roots.
  • Wires samples into GitHub Actions and new Maven profiles, synchronizes Java 17 for Jackson 3 across Maven/Gradle/sbt and moves those samples to the JDK 17 CI build, adds Parcelable deps to sbt and aligns Bean Validation dependencies (Jakarta EL vs Glassfish EL by useJakartaEe), updates generator docs (api doc examples now import modelPackage), renames the okhttp-gson user-defined-templates config, ports the invoker unit tests, and removes stale info.md/*ApiDocumentation.md output from the user-defined-templates samples.

Generate with openapi-generator generate -g java --library okhttp -p serializationLibrary=gson|jackson|jsonb [-p useJackson3=true] [-p useJspecify=true]. No migration for existing okhttp-gson users. openApiNullable is disabled for the whole library, so jackson-databind-nullable types are not generated.

Written for commit e373777. Summary will update on new commits.

Review in cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

6 issues found across 3000 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/others/java/okhttp-jackson-oneOf/settings.gradle">

<violation number="1" location="samples/client/others/java/okhttp-jackson-oneOf/settings.gradle:1">
P3: The new settings.gradle is missing a trailing newline at end of file, unlike every other sample settings.gradle in this directory. Add a final newline to match conventions and avoid a spurious diff marker.</violation>
</file>

<file name="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/RFC3339InstantDeserializer.java">

<violation number="1" location="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/RFC3339InstantDeserializer.java:32">
P2: This deserializer is never installed in the generated mapper, so the `_fromString` override that normalizes space-separated RFC3339 values never runs. Register `RFC3339JavaTimeModule` in `JSON` alongside `JavaTimeModule`, or omit this supporting class.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-user-defined-templates/src/main/java/org/openapitools/client/Configuration.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-user-defined-templates/src/main/java/org/openapitools/client/Configuration.java:39">
P2: During concurrent first access, `AtomicReference.updateAndGet` may retry this updater after a CAS failure, so `apiClientFactory.get()` can construct and discard extra clients. Initialize the singleton under a non-retryable critical section, or keep factory invocation outside a retryable updater.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache:39">
P1: When `serializationLibrary=jsonb` is used with `additionalProperties: true`, JSON-B cannot round-trip undeclared fields. Unknown response keys are ignored, while values added through `putAdditionalProperty` are not emitted under their original names; add a JSON-B serializer/deserializer that captures and flattens undeclared fields and excludes the backing bean property.</violation>
</file>

<file name="samples/client/others/java/okhttp-jackson-oneOf/git_push.sh">

<violation number="1" location="samples/client/others/java/okhttp-jackson-oneOf/git_push.sh:47">
P2: When the directory already has a non-`origin` remote, this check skips adding `origin`, but the script later pulls and pushes from `origin`. Check specifically for `origin` before deciding whether to add it.</violation>

<violation number="2" location="samples/client/others/java/okhttp-jackson-oneOf/git_push.sh:54">
P1: When `GIT_TOKEN` is set, this command stores the credential in plaintext in `.git/config` and exposes it through Git remote inspection. Use Git's credential helper or `GIT_ASKPASS` instead of embedding the token in the remote URL.</violation>
</file>

Note: This PR contains a large number of files. cubic only reviews up to 400 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.

Re-trigger cubic

{{#isJackson}}
@JsonAnyGetter
{{/isJackson}}
public Map<String, Object> getAdditionalProperties() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When serializationLibrary=jsonb is used with additionalProperties: true, JSON-B cannot round-trip undeclared fields. Unknown response keys are ignored, while values added through putAdditionalProperty are not emitted under their original names; add a JSON-B serializer/deserializer that captures and flattens undeclared fields and excludes the backing bean property.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache, line 39:

<comment>When `serializationLibrary=jsonb` is used with `additionalProperties: true`, JSON-B cannot round-trip undeclared fields. Unknown response keys are ignored, while values added through `putAdditionalProperty` are not emitted under their original names; add a JSON-B serializer/deserializer that captures and flattens undeclared fields and excludes the backing bean property.</comment>

<file context>
@@ -0,0 +1,55 @@
+  {{#isJackson}}
+  @JsonAnyGetter
+  {{/isJackson}}
+  public Map<String, Object> getAdditionalProperties() {
+    return additionalProperties;
+  }
</file context>

echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
else
git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When GIT_TOKEN is set, this command stores the credential in plaintext in .git/config and exposes it through Git remote inspection. Use Git's credential helper or GIT_ASKPASS instead of embedding the token in the remote URL.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/java/okhttp-jackson-oneOf/git_push.sh, line 54:

<comment>When `GIT_TOKEN` is set, this command stores the credential in plaintext in `.git/config` and exposes it through Git remote inspection. Use Git's credential helper or `GIT_ASKPASS` instead of embedding the token in the remote URL.</comment>

<file context>
@@ -0,0 +1,63 @@
+        echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
+        git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
+    else
+        git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
+    fi
+
</file context>

Comment thread samples/client/echo_api/java/okhttp-jackson-user-defined-templates/git_push.sh Outdated
@rar91279
rar91279 marked this pull request as draft August 19, 2026 12:04
@rar91279
rar91279 marked this pull request as ready for review August 19, 2026 21:32

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread samples/client/others/java/okhttp-jackson-oneOf/git_push.sh Outdated
…ON-B

Adds a new "okhttp" library to the Java client generator, forked from
"okhttp-gson" but decoupled from Gson: one template set emits clients for
Gson (default), Jackson 2, Jackson 3 and JSON-B, on OkHttp 5.4.0, and honours
the existing useJspecify option.

Templates (Java/libraries/okhttp/):
- JSON.mustache carries three parallel implementations - Gson (gson-fire +
  TypeAdapterFactory), Jackson (ObjectMapper, jacksonPackage-parameterised for
  2.x/3.x) and JSON-B (Yasson + JsonbAdapters, with a GenericType<T> helper
  standing in for TypeToken).
- ApiClient holds JSON as an instance so serializer config is per-client,
  passes request payloads to auth as byte[] rather than String, and signs
  AWS4 last so it sees the final query string.
- auth/RetryingOAuth embeds its own TokenRequestBuilder and talks to OkHttp
  directly, dropping the Apache Oltu dependency that okhttp-gson needs.
- api/pojo/oneof/anyof switch between TypeToken, TypeReference and
  JSON.GenericType, and use the shared nullableArgument partials plus the
  jSpecifyDatatype lambda already provided by AbstractJavaCodegen.

Templates that only differed cosmetically from their root-level counterparts
(Pair, StringUtil, ServerVariable, ServerConfiguration, maven.yml, travis,
git_push.sh) are deliberately not forked - mustache resolution falls back to
Java/ and the generated output is verified to include them.

JavaClientCodegen:
- registers the library, adds it to JSPECIFY_SUPPORTED_LIBRARIES and to the
  useJackson3 allowlist, and reuses the okhttp-gson supporting-file branch
  without forcing the serialization library.
- resolves isGson/isJackson/isJsonb after the serialization switch, where
  getSerializationLibrary() is authoritative, instead of guessing earlier.
- forces openApiNullable off for JSON-B, since jackson-databind-nullable is
  Jackson-only and the pom omits it there.
- applies the x-enum-as-string discriminator rewrite for every serialization
  library (a narrowed discriminator otherwise generates a getter that cannot
  override the parent's String getter), while keeping the JsonNullable and
  JsonIgnore imports Jackson-only.
- extends the useSingleRequestParameter and oneOf/anyOf ModelNull handling to
  the new library, both of which its templates support.
…library

bin/configs/java-okhttp-user-defined-templates.yaml generated the okhttp-gson
sample despite the neutral name; every other okhttp-gson config on master is
already named java-okhttp-gson-*. Renaming it keeps the naming consistent and
frees the java-okhttp-* prefix for the new okhttp library, without touching the
generated sample.
27 configs covering the new library: the four serialization variants (Gson,
Jackson 2, Jackson 3, JSON-B), JSpecify for each of Jackson 2/3 and JSON-B,
oneOf/anyOf, nullable-required, AWS4 signing, dynamic operations, grouped
parameters, parcelable models, streaming, swagger 1/2 annotations, OpenAPI 3.1,
the echo API and user-defined templates.

Fixes carried over from the prototype branch:
- java-okhttp-echo-api.yaml had "library" commented out, so it silently
  generated with the default okhttp-gson library instead of okhttp.
- java-okhttp-jackson-nullable-required.yaml never set
  serializationLibrary: jackson, making it a duplicate of the gson config.
- java-okhttp.yaml had "useReflectionEqualsHashCode::" with a double colon, so
  the property never applied.
- java-okhttp-jackson3-oneOf.yaml wrote to others/java/oneOf-okhttp-jackson3,
  breaking the okhttp-<serializer>-<feature> convention of its siblings, and
  java-okhttp-jackson3-jspecify.yaml reused the artifactId of the non-jspecify
  jackson3 config.
- java-okhttp-jsonb-jspecify.yaml set useJackson3 alongside JSON-B.

Every config names its serialization library explicitly, including the Gson
ones: JavaClientCodegen infers its internal "jackson" flag from the absence of
the property, so relying on the default would opt Gson output into
Jackson-specific nullable handling.

All 27 configs generate, and every generated sample compiles and passes its
tests under Maven.
- pom.xml: java-client-okhttp profile builds the four serialization variants,
  java-client-okhttp-parcelable mirrors the okhttp-gson parcelable profile.
- Workflows: each okhttp-gson entry gains its okhttp counterpart, in both the
  path triggers and the sample matrices. The petstore-server workflow gets the
  three samples that mirror okhttp-gson there; the plain client workflow gets
  the serialization, jspecify, oneOf, nullable-required, swagger, streaming,
  AWS4, grouped-parameter and parcelable samples; echo-api, gradle and sbt get
  their okhttp equivalents.
- docs/generators/java.md: regenerated - the library table gains okhttp and
  useJspecify now lists it as supported.
Generated output for the 27 new bin/configs. Every sample compiles and passes
its tests under Maven, across all four serialization variants.
The previously committed samples were generated with a jar that still contained
seven okhttp templates from an earlier prototype build: Pair, StringUtil,
ServerVariable, ServerConfiguration, maven.yml, travis and git_push.sh. Those
templates are intentionally not part of this library - mustache resolution is
supposed to fall back to the shared Java/ and _common/ templates - but stale
target/classes output survived an incremental build and was shaded into the CLI
jar, where library-local templates take precedence.

Rebuilt with `mvn clean install` and regenerated. Only git_push.sh actually
differed in the output; it now matches _common/git_push.sh.mustache and is
byte-identical to the okhttp-gson sample, as are Pair, StringUtil,
ServerVariable, ServerConfiguration, maven.yml and travis.
Correctness fixes to the forked templates:

- GzipRequestInterceptor: restore the forceContentLength() wrapper dropped from
  okhttp-gson. Without it the gzip body reports contentLength() == -1, OkHttp
  falls back to Transfer-Encoding: chunked, and every compressed request fails
  against servers that reject chunked request bodies. The unused okio.Buffer
  import was the tell that the removal was accidental.
- ProgressResponseBody: restore the memoized bufferedSource field. OkHttp calls
  source() again on close(), so without caching each call built a fresh
  ForwardingSource over a partially consumed stream, resetting the progress
  counter and risking double reads.
- ProgressRequestBody: CountingSink no longer reports done, so a known-length
  body gets exactly one terminal callback instead of two (writeTo still emits
  the terminal event, which is what unknown-length bodies rely on). Dropped the
  unreachable private countingSink(Sink) helper.
- AWS4Auth: sign x-amz-* headers. They were never added to the signable
  request, so SigV4 omitted them from SignedHeaders and AWS rejected the
  signature. Content-Type is deliberately left unsigned because OkHttp's
  BridgeInterceptor appends the multipart boundary after signing. This also
  wires up the two-pass auth ordering in ApiClient, which until now had no
  effect.
- JSON: register RFC3339JavaTimeModule for Jackson 2. The codegen already
  emitted RFC3339InstantDeserializer and RFC3339JavaTimeModule, but nothing
  installed them, so the space-separated RFC3339 normalization never ran. Every
  other Jackson library registers it. Jackson 3 does not emit the classes and
  is left untouched.
- additional_properties: replace Java `transient` with @JsonbTransient. The
  transient keyword was added by this fork and made Java serialization drop all
  undeclared properties when serializableModel=true; @JsonbTransient keeps
  JSON-B from emitting the backing map without that side effect.
- ApiResponse: lowercase header keys in the caseInsensitiveResponseHeaders
  branch, matching okhttp-gson, native, jersey2 and jersey3.
- pojo: stop emitting five Jackson imports that JavaClientCodegen already
  contributes via model.imports, which produced duplicate import lines.
  JsonTypeName is only contributed for Jackson 2, so it is still emitted from
  the template under useJackson3.

Build files:

- build.gradle: add the com.google.android:android compileOnly dependency under
  parcelableModel, mirroring the pom. Generated Parcelable models now compile
  with a plain Gradle build.
- build.sbt: add the swagger-parser-v3 dependency under dynamicOperations and
  the jakarta.validation-api dependency under useBeanValidation, both of which
  the pom and Gradle builds already declared; gate jackson-annotations on
  Jackson 2 so Jackson 3 clients take the version aligned by jackson-databind.

All 27 samples regenerated; each compiles and passes mvn test, and
JavaClientCodegenTest still passes 288 tests. okhttp-gson output is unchanged.
…imports

The previous fix emitted the JsonTypeName import from pojo.mustache whenever
useJackson3 was set. AbstractJavaCodegen already adds that import for any model
whose classname was sanitized, regardless of Jackson version, so models such as
Apple, Banana and EnumTest ended up importing it twice.

Contribute it from JavaClientCodegen.postProcessModelProperty instead. Because
model.imports is a Set, the import is emitted exactly once whichever path asks
for it, and the template no longer hardcodes it.

Jackson-annotation duplicate imports across the okhttp samples drop from 19 to
1. The remaining one is JsonIgnore on a model that hits both the
additionalProperties template path and the shared nullable addImports path,
which appends to a List without de-duplicating - the same pre-existing
mechanism that leaves five duplicate imports in okhttp-gson-nullable-required
on master.
@KannaKim

Copy link
Copy Markdown
Contributor

This PR is too broad in scope, it's difficult to review 400k lines of changes.

@rar91279

rar91279 commented Sep 2, 2026

Copy link
Copy Markdown
Author

Hi, @KannaKim.
Thank you and sorry about that.

Yes, i know, that a bunch of changes, but its a completelly new okhttp generator supporting all three currently available JSON serialization libs as well as JSpecify.

I don't want and i try hard, to don't change anything on the current okhttp-gson generator.
I suppose many people use this as default and changing anything on it could have much more impact on running codebases as adding generic okthttp generator, as beta, aside of it.

Do you have some Idea for me how to organize this PR better for review?
Beside the fixing all concerns of cubic review, i have to do.

@wing328

wing328 commented Sep 3, 2026

Copy link
Copy Markdown
Member

thanks for the contribution.

please resolve the merge conflicts when you've time

is it correct to say that you've been using this generator's output in production for a while and it's working as expected?

i'll try to take a look this weekend.

# Conflicts:
#	modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
…t separator helper

Port two changes from master into the okhttp library:

- generateInsecureTlsHook (OpenAPITools#24786): when set to false, the okhttp
  ApiClient omits the verifyingSsl field, setVerifyingSsl/isVerifyingSsl
  and the trust-all X509TrustManager/HostnameVerifier, for consumers
  whose static analysis flags that code. The verifying TLS setup moves
  into trustedTrustManagers()/trustedHostnameVerifier() so both template
  variants share it.

- CollectionFormat helper (OpenAPITools#24781): deduplicate the collection-format
  delimiter lookup in parameterToPairs and collectionPathParameterToString
  into a collectionFormatSeparator method.
… changes

Includes the churn from master (7.26.0-SNAPSHOT version bump, path
backslash removal, inline-enum resolver fix), the new ApiClient helpers,
and the RequiredAndNullable/FileContent files the jspecify samples were
missing since the spec gained them in OpenAPITools#24711.
…earer-token NPE, modelCopy JsonTypeName

- JSON-B has no @JsonAnyGetter/@JsonAnySetter, so models with
  'additionalProperties: true' silently dropped undeclared fields in both
  directions. Generate a CustomJsonbSerializer/CustomJsonbDeserializer
  into each such pojo and register them in the Jsonb config built by
  JSON, mirroring what the Gson CustomTypeAdapterFactory does. Verified
  with a runtime round trip against the generated okhttp-jsonb client.

- HttpBearerAuth.getBearerToken() threw NullPointerException before a
  token was configured, although applyToParams treats an unset supplier
  as valid unauthenticated state. Return null instead.

- @JsonTypeName was emitted as "java" when pojo.mustache is rendered as
  a user-defined Model template (files config), because the bundle
  root's "name" key holds the generator name. Resolve the model name
  through the models/model scope, which works in both contexts.

- ApiResponse: use conventional 'private final' modifier order and fix
  the "response bod" javadoc typo.
Correctness fixes across the okhttp templates and JavaClientCodegen,
each verified by unit tests and runtime round trips against the
regenerated clients:

Gson:
- oneOf/anyOf branches typed List<X>/Map<String,X> had no validation
  (bare matches++), and plain non-primitive branches (UUID, BigDecimal)
  none at all, while String/Boolean accepted any primitive - valid
  payloads failed with "N classes match result, expected 1". Branch
  validation now checks the concrete JSON type, ported from the
  okhttp-gson baseline.
- Serializing a null additional property crashed on
  JsonNull.getAsJsonObject(); the baseline's isJsonNull branch is
  restored.
- JSON.isInstanceOf(type, null) returned true, letting non-nullable
  oneOf/anyOf wrappers accept null; nullable wrappers handle null in
  setActualInstance, so null now matches nothing.
- new JSON() unconditionally rebuilt the shared static Gson, discarding
  a setGson() customization on every ApiClient/RetryingOAuth
  construction; the constructor now keeps an existing instance.
- CustomTypeAdapterFactory is no longer generated for parents with
  children (it was never registered, matching the baseline guard).

Jackson:
- oneOf deserializers double-counted duplicated data types (the one
  loop missing the x-duplicated-data-type guard), so such models could
  never deserialize; jsonb loops had the same gap.
- errorObjectType's catch block gained the missing Jackson branch.
- Jackson 3 now gets RFC3339JavaTimeModule/RFC3339InstantDeserializer
  like Jackson 2 (JavaClientCodegen whitelist + JSON.mustache).
- openApiNullable is forced off for the whole library: the templates
  never emit JsonNullable, so the flag only produced dead
  equalsNullable/hashCodeNullable helpers and duplicate imports.

JSON-B:
- Discriminator hierarchies were silently unsupported (a Cat response
  typed Animal lost its fields). Yasson's native @JsonbTypeInfo cannot
  be used because the discriminator is also a bean property (key
  collision on both paths, "CHANGE naming conflict"), so hierarchy
  roots now generate TypeSelector-style custom (de)serializers that
  dispatch on the discriminator and bind subtypes through a second,
  polymorphism-free Jsonb instance (JSON.getPlainJsonb()).
- The additionalProperties deserializer coerced explicit JSON null
  into the field default, skipped readOnly properties, and read the
  volatile Jsonb once per field; it now binds null, sets readOnly
  fields reflectively, validates openapiRequiredFields (previously
  dead for JSON-B), and captures the instance once per object.
- anyOf toUrlQueryString iterated composedSchemas.oneOf and always
  returned null under supportUrlQuery.

ApiClient:
- executeStream() leaked the connection and discarded the error body
  on non-2xx responses; it now mirrors handleResponse().
- dynamicOperations sent null optional header/cookie params as empty
  strings; fillParametersFromOperation now skips null values.
- The dead public updateParamsForAuth() (stale-URI semantics diverging
  from buildRequest's inline loop) is removed.
- build.gradle no longer declares the mockito dependency pom dropped.
…oJson, free-form validation

- oneOf wrapper models were missing the static fromJson(String)/toJson()
  helpers that okhttp-gson (and this library's anyOf wrappers and plain
  pojos) expose, an API-surface regression for migrating consumers. The
  Gson block from anyof_model.mustache is mirrored into
  oneof_model.mustache.

- The per-type branch validation rejected free-form values: Object is a
  Java language-specific primitive, so an anyType branch or anyType
  container item fell into the primitive check and its "must be Number"
  fallback - a Map<String, Object> oneOf branch no longer accepted
  string/boolean/object values. anyType branches and items now skip
  validation entirely (any JSON value matches), like the okhttp-gson
  baseline.
Regenerated for the composed fromJson/toJson helpers and the anyType
validation fix.

Ports the 8 hand-maintained invoker tests from the okhttp-gson petstore
sample (ApiClient, Client, Configuration, JSON, StringUtil, ApiKeyAuth,
HttpBasicAuth, RetryingOAuth), adapted to this library: byte[] auth
payloads, the Oltu-free RetryingOAuth is exercised against a local
HttpServer instead of Mockito, JSONTest uses the composed-model
fromJson/toJson helpers and the library's fail-fast discriminator
messages, and equals() assertions avoid reflectionEquals (needs
--add-opens on JDK 9+). Suite: 501 tests, 0 failures.
@rar91279
rar91279 force-pushed the java-generic-okhttp branch from d7145f5 to d289677 Compare September 4, 2026 11:32
@rar91279

rar91279 commented Sep 4, 2026

Copy link
Copy Markdown
Author

Hello @wing328,

thank you for your time.

Unfortunally it isn't in production now. I have only 4 local test projects against local httpbin running before push.
i'll migrate an api client to the new one with jackson2 in a production system going in testing next week.

JSON-B will be difficult, i don't have any projects runnig this in production :(

I have merged master yesterday and resolved cubic concerns.

…re spec, fix jsonb gaps

The three okhttp samples generated with a non-gson serializer took their spec from
3_0/java/native/petstore-...-with-http-signature.yaml, which declares an
`http_signature_test` scheme (type: http, scheme: signature). ApiClient.mustache only
registers basic/bearer/apiKey/oauth schemes, while api.mustache emits every scheme name
into localVarAuthNames, so PetApi.addPet, updatePet, findPetsByStatus and findPetsByTags
threw `RuntimeException: Authentication undefined: http_signature_test` on every generated
call surface (plain, WithHttpInfo and Async alike), with no way out: getAuthentications()
is an unmodifiable map, and the throw happens in buildRequest before any interceptor runs.

Point them at the spec java-okhttp.yaml already uses. That drops the unsatisfiable scheme
and, because all four serializers now generate from one spec, makes okhttp / okhttp-jackson
/ okhttp-jackson3 / okhttp-jsonb a like-for-like serializer matrix.

The richer spec exposed three jsonb defects, all fixed here:

* JSON.mustache registered no adapter for java.io.File, the mapping of `format: binary`.
  JSON-B then treated File as a bean: serializing recursed through getAbsoluteFile()
  ("Recursive reference has been found in class java.io.File") and deserializing demanded
  START_OBJECT where the schema carries a string. Adds a FileAdapter matching Jackson's
  representation - getAbsolutePath() out, new File(String) in.
* oneof_model/anyof_model did not import JsonbTransient, which
  additional_properties.mustache needs for its holder field. A pojo gets the import from
  pojo.mustache; a composed model got none, so any composed schema with
  additionalProperties failed to compile (40 errors).
* the composed deserializers called parser.getObject() unconditionally, which throws on
  START_ARRAY, and routed every branch through ctx.deserialize, which Yasson cannot bind to
  a root-level scalar. They now read a generic JsonValue and send structured values through
  the context and scalars through the binding API.

Verified against a Prism mock per sample, driving every generated operation of all 42
okhttp-family samples (864 operations): all four serializers are now identical
operation-for-operation on the shared spec, all 14 okhttp/okhttp-gson pairs remain
identical, and no okhttp-gson template, sample or config is touched.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10 issues found across 3000 files

Not reviewed (too large): samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/api/FakeApi.java (~3,457 lines), samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/api/FakeApi.java (~3,457 lines), samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/api/FakeApi.java (~3,456 lines), samples/client/petstore/java/okhttp-dynamicOperations/src/main/java/org/openapitools/client/api/FakeApi.java (~2,248 lines), samples/client/petstore/java/okhttp-parcelableModel/src/main/java/org/openapitools/client/api/FakeApi.java (~2,191 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/additional_properties.mustache:11">
P2: For JSON-B models with children, `putAdditionalProperty` values are dropped during serialization. `@JsonbTransient` removes the holder from normal mapping, but the `hasChildren` serializer uses plain JSON-B without the additional-properties serializer; add equivalent flattening to that path or avoid applying this annotation for models handled there.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/AWS4Auth.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/AWS4Auth.mustache:79">
P1: When `useGzipFeature=true`, `AWS4Auth` signs the original payload, but `GzipRequestInterceptor` compresses the body before it reaches AWS. The resulting SigV4 payload hash does not match the transmitted bytes, so signed requests are rejected; disable gzip for AWS4 requests or sign the final compressed body.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressResponseBody.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressResponseBody.mustache:42">
P1: When a callback-tagged request receives a response without a body, `responseBody` is null and this wrapper dereferences it while the generated client consumes the response. Skip creating `ProgressResponseBody` for null response bodies in `getProgressInterceptor()` so no-content responses complete normally.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-user-defined-templates/src/main/java/org/openapitools/client/GzipRequestInterceptor.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-user-defined-templates/src/main/java/org/openapitools/client/GzipRequestInterceptor.java:40">
P1: When AWS4 signing and `useGzipFeature` are enabled together, this interceptor changes the signed request body after `AWS4Auth` computes its signature, so AWS rejects the request. Skip compression for signed requests or apply signing after compression using the compressed payload hash.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java:19">
P3: The generated Category.java imports eight symbols that are never referenced in the file: com.fasterxml.jackson.annotation.JsonCreator, JsonValue, java.io.IOException, java.util.HashMap, List, Map, Set, and org.openapitools.client.JSON. These unused imports are emitted by the new okhttp pojo.mustache common import block (model.imports) for every model regardless of whether the model uses them, adding compiler warnings to every generated model. Restrict the template's import emission to symbols the model actually uses (e.g., only emit JSON when the model references the JSON helper, JsonValue/JsonCreator only when relevant), so the generated models compile warning-free.</violation>
</file>

<file name="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/ServerConfiguration.java">

<violation number="1" location="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/ServerConfiguration.java:55">
P2: When a server variable has no `enum` and a caller overrides it, `URL(Map<String, String>)` throws `NullPointerException` because `ServerVariable.enumValues` is nullable. Check for `null` before inspecting the allowed values so non-enumerated server variables can be substituted.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/ServerConfiguration.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/ServerConfiguration.java:55">
P2: When a custom server variable has no enum values, `URL(Map)` throws `NullPointerException` while validating the supplied value. Guard the optional `enumValues` collection before calling `size()` or `contains()`.</violation>
</file>

<file name="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/GzipRequestInterceptor.java">

<violation number="1" location="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/GzipRequestInterceptor.java:52">
P2: When gzip is enabled for an asynchronous upload, this eager write makes `ProgressRequestBody` report completion before the network sends the request. It also retains every compressed file or streaming body in memory, which can cause large uploads to run out of memory; avoid precompressing in the interceptor or use a streaming/file-backed strategy that preserves progress reporting.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/Configuration.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/Configuration.java:39">
P2: When multiple threads first call `getDefaultApiClient()`, `updateAndGet` can invoke `apiClientFactory` more than once and discard the extra clients. Protect lazy initialization with synchronization or another mechanism that guarantees the factory runs only once.</violation>
</file>

<file name="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/RFC3339JavaTimeModule.java">

<violation number="1" location="samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/RFC3339JavaTimeModule.java:32">
P2: When Jackson registers this module, `super.setupModule(context)` publishes the deserializer map before these `addDeserializer` calls execute. Move the registrations before `super.setupModule(context)` or into the constructor, otherwise the RFC3339 deserializer is never used.</violation>
</file>

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

Re-trigger cubic

ContentStreamProvider provider = new ContentStreamProvider() {
@Override
public InputStream newStream() {
return new ByteArrayInputStream(payload);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When useGzipFeature=true, AWS4Auth signs the original payload, but GzipRequestInterceptor compresses the body before it reaches AWS. The resulting SigV4 payload hash does not match the transmitted bytes, so signed requests are rejected; disable gzip for AWS4 requests or sign the final compressed body.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/auth/AWS4Auth.mustache, line 79:

<comment>When `useGzipFeature=true`, `AWS4Auth` signs the original payload, but `GzipRequestInterceptor` compresses the body before it reaches AWS. The resulting SigV4 payload hash does not match the transmitted bytes, so signed requests are rejected; disable gzip for AWS4 requests or sign the final compressed body.</comment>

<file context>
@@ -0,0 +1,114 @@
+    ContentStreamProvider provider = new ContentStreamProvider() {
+      @Override
+      public InputStream newStream() {
+        return new ByteArrayInputStream(payload);
+      }
+    };
</file context>

// Memoized: OkHttp calls source() again on close(), and a second ForwardingSource would
// reset the progress counter and re-wrap an already partially consumed stream.
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When a callback-tagged request receives a response without a body, responseBody is null and this wrapper dereferences it while the generated client consumes the response. Skip creating ProgressResponseBody for null response bodies in getProgressInterceptor() so no-content responses complete normally.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/ProgressResponseBody.mustache, line 42:

<comment>When a callback-tagged request receives a response without a body, `responseBody` is null and this wrapper dereferences it while the generated client consumes the response. Skip creating `ProgressResponseBody` for null response bodies in `getProgressInterceptor()` so no-content responses complete normally.</comment>

<file context>
@@ -0,0 +1,61 @@
+        // Memoized: OkHttp calls source() again on close(), and a second ForwardingSource would
+        // reset the progress counter and re-wrap an already partially consumed stream.
+        if (bufferedSource == null) {
+            bufferedSource = Okio.buffer(source(responseBody.source()));
+        }
+        return bufferedSource;
</file context>


Request compressedRequest = originalRequest.newBuilder()
.header("Content-Encoding", "gzip")
.method(originalRequest.method(), forceContentLength(gzip(body)))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When AWS4 signing and useGzipFeature are enabled together, this interceptor changes the signed request body after AWS4Auth computes its signature, so AWS rejects the request. Skip compression for signed requests or apply signing after compression using the compressed payload hash.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-user-defined-templates/src/main/java/org/openapitools/client/GzipRequestInterceptor.java, line 40:

<comment>When AWS4 signing and `useGzipFeature` are enabled together, this interceptor changes the signed request body after `AWS4Auth` computes its signature, so AWS rejects the request. Skip compression for signed requests or apply signing after compression using the compressed payload hash.</comment>

<file context>
@@ -0,0 +1,91 @@
+
+        Request compressedRequest = originalRequest.newBuilder()
+                                                   .header("Content-Encoding", "gzip")
+                                                   .method(originalRequest.method(), forceContentLength(gzip(body)))
+                                                   .build();
+        return chain.proceed(compressedRequest);
</file context>

Comment on lines +32 to +36
super.setupModule(context);

addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT);
addDeserializer(OffsetDateTime.class, RFC3339InstantDeserializer.OFFSET_DATE_TIME);
addDeserializer(ZonedDateTime.class, RFC3339InstantDeserializer.ZONED_DATE_TIME);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When Jackson registers this module, super.setupModule(context) publishes the deserializer map before these addDeserializer calls execute. Move the registrations before super.setupModule(context) or into the constructor, otherwise the RFC3339 deserializer is never used.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/others/java/okhttp-jackson-oneOf/src/main/java/org/openapitools/client/RFC3339JavaTimeModule.java, line 32:

<comment>When Jackson registers this module, `super.setupModule(context)` publishes the deserializer map before these `addDeserializer` calls execute. Move the registrations before `super.setupModule(context)` or into the constructor, otherwise the RFC3339 deserializer is never used.</comment>

<file context>
@@ -0,0 +1,39 @@
+
+   @Override
+   public void setupModule(SetupContext context) {
+       super.setupModule(context);
+
+       addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT);
</file context>
Suggested change
super.setupModule(context);
addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT);
addDeserializer(OffsetDateTime.class, RFC3339InstantDeserializer.OFFSET_DATE_TIME);
addDeserializer(ZonedDateTime.class, RFC3339InstantDeserializer.ZONED_DATE_TIME);
addDeserializer(Instant.class, RFC3339InstantDeserializer.INSTANT);
addDeserializer(OffsetDateTime.class, RFC3339InstantDeserializer.OFFSET_DATE_TIME);
addDeserializer(ZonedDateTime.class, RFC3339InstantDeserializer.ZONED_DATE_TIME);
super.setupModule(context);

Comment thread samples/client/others/java/okhttp-jackson-oneOf/docs/DefaultApi.md Outdated
@@ -0,0 +1,156 @@
/*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The generated Category.java imports eight symbols that are never referenced in the file: com.fasterxml.jackson.annotation.JsonCreator, JsonValue, java.io.IOException, java.util.HashMap, List, Map, Set, and org.openapitools.client.JSON. These unused imports are emitted by the new okhttp pojo.mustache common import block (model.imports) for every model regardless of whether the model uses them, adding compiler warnings to every generated model. Restrict the template's import emission to symbols the model actually uses (e.g., only emit JSON when the model references the JSON helper, JsonValue/JsonCreator only when relevant), so the generated models compile warning-free.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/model/Category.java, line 19:

<comment>The generated Category.java imports eight symbols that are never referenced in the file: com.fasterxml.jackson.annotation.JsonCreator, JsonValue, java.io.IOException, java.util.HashMap, List, Map, Set, and org.openapitools.client.JSON. These unused imports are emitted by the new okhttp pojo.mustache common import block (model.imports) for every model regardless of whether the model uses them, adding compiler warnings to every generated model. Restrict the template's import emission to symbols the model actually uses (e.g., only emit JSON when the model references the JSON helper, JsonValue/JsonCreator only when relevant), so the generated models compile warning-free.</comment>

<file context>
@@ -0,0 +1,156 @@
+import java.util.Objects;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.JsonValue;
</file context>

…ibrary

Address the actionable findings from the 2026-09-07 review run, all confined
to the okhttp library templates:

- GzipRequestInterceptor: skip compression for AWS SigV4-signed requests.
  AWS4Auth hashes the uncompressed payload and stamps the Authorization
  header before the Request exists, so gzipping afterwards made the
  transmitted bytes disagree with the signature and AWS rejected the call.
  Guarded by withAWSV4Signature, so non-AWS clients are unchanged.
- GzipRequestInterceptor: keep upload progress truthful. Buffering to publish
  a Content-Length drained the enclosing ProgressRequestBody, firing every
  callback (terminal one included, with uncompressed totals) before a byte
  reached the socket. Compress the wrapped delegate instead and re-wrap the
  compressed buffer with the same callback, and replay it in segments so the
  upload is reported as it happens. The in-memory buffering itself is
  inherent to publishing a compressed length and is now documented.
- pojo.mustache: flatten additionalProperties for JSON-B models with
  children. @JsonbTransient hides the holder and the flattening serializer
  was registered only for non-hasChildren models, so an instance whose
  runtime type is the discriminated root silently lost its extra properties.
- build.gradle.mustache: select Java 17 when useJackson3 is set, as the POM
  already does; nothing derives the internal java17 property from it, so
  Gradle clients targeted Java 8 with a Jackson 3 dependency.
- build.sbt.mustache: add the Parcelable and Bean Validation provider
  dependencies that the POM and Gradle builds already declare.
- ProgressRequestBody: delegate isOneShot()/isDuplex() so a wrapped one-shot
  or duplex body keeps its contract.
- ApiResponse.mustache: lower-case response header names with Locale.ROOT so
  a Turkish/Azeri default locale cannot corrupt them.
- api_doc.mustache: import modelPackage rather than a non-existent
  "<invokerPackage>.models" package, so the doc examples compile.

Samples regenerated for all 27 okhttp configs. okhttp-gson stays byte
identical to master.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 existing issue remains and no new issues found across 171 files (changes from recent commits).

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Jackson 3 requires Java 17, so the generated POM for a useJackson3 client
compiles with source/target 17. The three okhttp jackson3 samples were wired
into the JDK 11 sample workflow when okhttp CI coverage was added, and their
"Build with Maven" step has failed there ever since: a JDK 11 javac cannot
honour target 17.

Move them to the JDK 17 workflow, where every other library already keeps its
jackson3 sample (native-jackson3, apache-httpclient-jackson3, jersey3-jackson3):

- samples/client/petstore/java/okhttp-jackson3
- samples/client/petstore/java/okhttp-jackson3-jspecify
- samples/client/others/java/okhttp-jackson3-oneOf

The generated POMs are unchanged; only the CI wiring was wrong.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 173 files (changes from recent commits).

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Roman Mertyn added 2 commits September 8, 2026 16:41
(ApiClient.java:1022-1032) — the real one. sink.writeAll(response.body().source()) never closes the body's source; on success the connection is only released because the stream happens to be read to exhaustion, but if an IOException hits mid-copy, both the BufferedSink (file descriptor) and the response body (pooled connection) leak. Needs try-with-resources on both
Close responses explicitly on failures

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Roman Mertyn and others added 2 commits September 8, 2026 18:25
…ependencies

- Updated template dependencies to select Jakarta EL or Glassfish EL dynamically based on useJakartaEe (5.x for Jakarta EE and 3.x for javax).
- Adjusted hibernate-validator versions for Jakarta vs. javax compatibility.
- Flattened additionalProperties handling for JSON-B models with inheritance.
- Added branch validation in composed models to prevent mismatched deserialization.
- Ensured correct library dependencies in all build scripts (Maven, Gradle, SBT) while maintaining compatibility configurations.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 3000 files

Not reviewed (too large): samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/api/FakeApi.java (~3,457 lines), samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/api/FakeApi.java (~3,457 lines), samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/api/FakeApi.java (~3,456 lines), samples/client/petstore/java/okhttp-dynamicOperations/src/main/java/org/openapitools/client/api/FakeApi.java (~2,248 lines), samples/client/petstore/java/okhttp-parcelableModel/src/main/java/org/openapitools/client/api/FakeApi.java (~2,191 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

Re-trigger cubic

Comment thread samples/client/echo_api/java/okhttp/docs/HeaderApi.md Outdated
…ve required-field validation

- Delegate model symbol imports to JavaClientCodegen to eliminate duplicate import lines in templates.
- Introduce `uncheckedJsonb` instance to bypass additional properties enforcement during deserialization.
- Register custom JSON-B deserializers for models with required properties for stricter validation.
- Synchronize Java version source/target settings across build tools for `useJackson3`.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 21 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache:733">
P1: When a discriminator root declares required properties, JSON-B does not enforce them because this block excludes every `hasChildren` model. Validate required fields in the discriminator deserializer before subtype dispatch, rather than omitting these roots from required validation.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

{{^vendorExtensions.x-is-one-of-interface}}
{{^oneOf}}
{{^anyOf}}
{{^hasChildren}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When a discriminator root declares required properties, JSON-B does not enforce them because this block excludes every hasChildren model. Validate required fields in the discriminator deserializer before subtype dispatch, rather than omitting these roots from required validation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache, line 733:

<comment>When a discriminator root declares required properties, JSON-B does not enforce them because this block excludes every `hasChildren` model. Validate required fields in the discriminator deserializer before subtype dispatch, rather than omitting these roots from required validation.</comment>

<file context>
@@ -703,6 +716,33 @@ public class JSON {
+        {{^vendorExtensions.x-is-one-of-interface}}
+        {{^oneOf}}
+        {{^anyOf}}
+        {{^hasChildren}}
+        {{^isAdditionalPropertiesTrue}}
+        {{#hasRequired}}
</file context>

Comment thread modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache Outdated
Comment thread modules/openapi-generator/src/main/resources/Java/libraries/okhttp/JSON.mustache Outdated
82f8bfe edited build.sbt.mustache, api_doc.mustache, JavaClientCodegen.java
and the two java-okhttp-*-user-defined-templates.yaml configs, but regenerated
only the four JSON-B samples. Run the remaining 27 java-okhttp* configs so the
samples match the templates again. Generated output only, no template change:

- model imports deduplicated (JavaClientCodegen now contributes them)
- build.sbt pins -source/-target to the Maven and Gradle bytecode level
- the two user-defined-templates samples gain their README and api docs
1. A model that forbids additional properties never rejected an UNDECLARED
   field. Yasson binds such a model by plain bean mapping, which drops an
   unknown key silently, so a oneOf branch accepted a payload belonging to a
   sibling branch: {"lengthCm":10,"mealy":true} bound BananaReq and discarded
   `mealy`. Mirror the Gson type adapter's validateJsonElement and reject any
   key outside openapiFields. The guard moves from hasRequired to "declares a
   property", because a branch with no required field needs the check just as
   much; a model with no declared property stays excluded so that an empty
   openapiFields cannot reject every key.

2. Required-field checks did not survive nesting. `uncheckedJsonb` was built
   before EVERY required-field deserializer, so a checked model binding through
   it disabled the checks of all of its nested models too. A recursion guard
   cannot fix that: a re-entrant whole-object bind has to land on some instance
   that carries no checker, which is the defect itself. Drop uncheckedJsonb and
   bind property by property through the fully configured instance instead -
   the shape the additional-properties deserializer already used. That cannot
   re-enter itself, since the target type is the property's and not the class'.

3. The root of a discriminated hierarchy enforced no required property, because
   the registration block excludes every hasChildren model. Validate in the
   discriminator deserializer, both for the unmapped-root fallback and for a
   mapped subtype that has children of its own. A leaf subtype is covered by
   registering the required-field deserializers BEFORE plainJsonb is built:
   that instance now carries everything except the polymorphism roots, so a
   subtype bound through it validates itself.

4. setJsonb()/setSerializer() called before the first JSON was constructed left
   plainJsonb null, and every generated deserializer then failed with an NPE.
   Build the companion instance first, and check it in the constructor too.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 issues found across 3000 files

Not reviewed (too large): samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/api/FakeApi.java (~3,457 lines), samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/api/FakeApi.java (~3,457 lines), samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/api/FakeApi.java (~3,456 lines), samples/client/petstore/java/okhttp-dynamicOperations/src/main/java/org/openapitools/client/api/FakeApi.java (~2,248 lines), samples/client/petstore/java/okhttp-parcelableModel/src/main/java/org/openapitools/client/api/FakeApi.java (~2,191 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache:58">
P2: When `withXml=true` on the supported Java 11 or 17 targets, generated models cannot compile because JAXB was removed from the JDK and this build declares no JAXB API. Add a `jakarta.xml.bind-api` dependency for Jakarta mode and `javax.xml.bind:jaxb-api` for the non-Jakarta mode.</violation>

<violation number="2" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache:58">
P2: On Java 11+, SBT-generated clients fail to compile because the generated sources reference `javax.annotation.Generated`, but this build declares only `jakarta.annotation-api`. Add the matching `javax.annotation` API dependency or generate the corresponding Jakarta annotation imports.</violation>

<violation number="3" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache:69">
P1: When `useBeanValidation=true` and `useJakartaEe=false`, generated models import `javax.validation`, but this build declares the Jakarta validation artifact. Use `javax.validation:validation-api:2.0.1` for the non-Jakarta branch and retain the current Jakarta coordinate only for `useJakartaEe=true`.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java:115">
P3: In the Jackson-generated models, `openapiFields`/`openapiRequiredFields` are declared and populated but never read: the okhttp-gson template consumes them in `validateJsonElement`, which the Jackson port omits. The same template should not emit these fields (nor the unused `Map`, `JsonCreator`, `JsonValue` imports) for the Jackson/JSON-B serializers, otherwise every generated model carries dead code.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/Query.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/Query.java:1">
P2: The generated model won't compile: it calls Objects.hash() and uses @JsonTypeName("Query") but never imports java.util.Objects or com.fasterxml.jackson.annotation.JsonTypeName. Because this user-defined-template config maps only pojo.mustache as the Model template, the imports normally added by model.mustache (the unconditional java.util.Objects and the {{#jackson}} JsonPropertyOrder/JsonTypeName pair) are not emitted. Add both missing imports so the generated sample compiles, or include the model.mustache import header in the user-defined template generation.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/StringEnumRef.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/StringEnumRef.java:11">
P2: The modelCopy output for this model is an empty class: it loses the enum constants (SUCCESS/FAILURE/UNCLASSIFIED), the value field, and all serialization helpers that the src/main model version and the gson modelCopy version retain. Every modelCopy file renders as an empty property-less stub, so the user-defined-template modelCopy output is broken, not just this one. Regenerate/fix the pojo template so modelCopy output matches the compiled model content.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/Tag.java">

<violation number="1" location="samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/Tag.java:44">
P3: toIndentedString(Object) is private and never called: toString() only appends "}" without invoking it. Remove the dead method, or have toString() use it, to match the standard pojo template where the field lines are emitted.</violation>
</file>

<file name="samples/client/echo_api/java/okhttp-user-defined-templates/.openapi-generator/FILES">

<violation number="1" location="samples/client/echo_api/java/okhttp-user-defined-templates/.openapi-generator/FILES:8">
P2: The sample commits `info.md` and the six `docs/*ApiDocumentation.md` files, but none are listed in this FILES manifest and the new config no longer generates them (it produces README.md and `docs/*Api.md` instead; `info.md`/`*ApiDocumentation.md` come from the old config's `files:` entries). Files absent from FILES are never removed or rewritten by the generator, so the sample will keep these stale leftovers and stay out of sync with `bin/generate-samples.sh` output. Delete these seven orphaned files.</violation>
</file>

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.

Re-trigger cubic

"com.google.android" % "android" % "4.1.1.4" % "provided",
{{/parcelableModel}}
{{#useBeanValidation}}
"jakarta.validation" % "jakarta.validation-api" % "{{#useJakartaEe}}3.0.2{{/useJakartaEe}}{{^useJakartaEe}}2.0.2{{/useJakartaEe}}",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When useBeanValidation=true and useJakartaEe=false, generated models import javax.validation, but this build declares the Jakarta validation artifact. Use javax.validation:validation-api:2.0.1 for the non-Jakarta branch and retain the current Jakarta coordinate only for useJakartaEe=true.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache, line 69:

<comment>When `useBeanValidation=true` and `useJakartaEe=false`, generated models import `javax.validation`, but this build declares the Jakarta validation artifact. Use `javax.validation:validation-api:2.0.1` for the non-Jakarta branch and retain the current Jakarta coordinate only for `useJakartaEe=true`.</comment>

<file context>
@@ -0,0 +1,85 @@
+      "com.google.android" % "android" % "4.1.1.4" % "provided",
+      {{/parcelableModel}}
+      {{#useBeanValidation}}
+      "jakarta.validation" % "jakarta.validation-api" % "{{#useJakartaEe}}3.0.2{{/useJakartaEe}}{{^useJakartaEe}}2.0.2{{/useJakartaEe}}",
+      {{/useBeanValidation}}
+      {{#performBeanValidation}}
</file context>
Suggested change
"jakarta.validation" % "jakarta.validation-api" % "{{#useJakartaEe}}3.0.2{{/useJakartaEe}}{{^useJakartaEe}}2.0.2{{/useJakartaEe}}",
{{#useJakartaEe}}
"jakarta.validation" % "jakarta.validation-api" % "3.0.2",
{{/useJakartaEe}}
{{^useJakartaEe}}
"javax.validation" % "validation-api" % "2.0.1",
{{/useJakartaEe}}

{{#joda}}
"joda-time" % "joda-time" % "2.12.0",
{{/joda}}
"jakarta.annotation" % "jakarta.annotation-api" % "{{#useJakartaEe}}2.1.1{{/useJakartaEe}}{{^useJakartaEe}}1.3.5{{/useJakartaEe}}",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When withXml=true on the supported Java 11 or 17 targets, generated models cannot compile because JAXB was removed from the JDK and this build declares no JAXB API. Add a jakarta.xml.bind-api dependency for Jakarta mode and javax.xml.bind:jaxb-api for the non-Jakarta mode.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache, line 58:

<comment>When `withXml=true` on the supported Java 11 or 17 targets, generated models cannot compile because JAXB was removed from the JDK and this build declares no JAXB API. Add a `jakarta.xml.bind-api` dependency for Jakarta mode and `javax.xml.bind:jaxb-api` for the non-Jakarta mode.</comment>

<file context>
@@ -0,0 +1,85 @@
+      {{#joda}}
+      "joda-time" % "joda-time" % "2.12.0",
+      {{/joda}}
+      "jakarta.annotation" % "jakarta.annotation-api" % "{{#useJakartaEe}}2.1.1{{/useJakartaEe}}{{^useJakartaEe}}1.3.5{{/useJakartaEe}}",
+      {{#withAWSV4Signature}}
+      "software.amazon.awssdk" % "auth" % "2.20.157",
</file context>
Suggested change
"jakarta.annotation" % "jakarta.annotation-api" % "{{#useJakartaEe}}2.1.1{{/useJakartaEe}}{{^useJakartaEe}}1.3.5{{/useJakartaEe}}",
"jakarta.annotation" % "jakarta.annotation-api" % "{{#useJakartaEe}}2.1.1{{/useJakartaEe}}{{^useJakartaEe}}1.3.5{{/useJakartaEe}}",
{{#withXml}}
{{#useJakartaEe}}
"jakarta.xml.bind" % "jakarta.xml.bind-api" % "4.0.2",
{{/useJakartaEe}}
{{^useJakartaEe}}
"javax.xml.bind" % "jaxb-api" % "2.3.1",
{{/useJakartaEe}}
{{/withXml}}

@@ -0,0 +1,61 @@
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The generated model won't compile: it calls Objects.hash() and uses @JsonTypeName("Query") but never imports java.util.Objects or com.fasterxml.jackson.annotation.JsonTypeName. Because this user-defined-template config maps only pojo.mustache as the Model template, the imports normally added by model.mustache (the unconditional java.util.Objects and the {{#jackson}} JsonPropertyOrder/JsonTypeName pair) are not emitted. Add both missing imports so the generated sample compiles, or include the model.mustache import header in the user-defined template generation.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/Query.java, line 1:

<comment>The generated model won't compile: it calls Objects.hash() and uses @JsonTypeName("Query") but never imports java.util.Objects or com.fasterxml.jackson.annotation.JsonTypeName. Because this user-defined-template config maps only pojo.mustache as the Model template, the imports normally added by model.mustache (the unconditional java.util.Objects and the {{#jackson}} JsonPropertyOrder/JsonTypeName pair) are not emitted. Add both missing imports so the generated sample compiles, or include the model.mustache import header in the user-defined template generation.</comment>

<file context>
@@ -0,0 +1,61 @@
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import java.util.HashSet;
+
</file context>

@@ -0,0 +1,61 @@
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The modelCopy output for this model is an empty class: it loses the enum constants (SUCCESS/FAILURE/UNCLASSIFIED), the value field, and all serialization helpers that the src/main model version and the gson modelCopy version retain. Every modelCopy file renders as an empty property-less stub, so the user-defined-template modelCopy output is broken, not just this one. Regenerate/fix the pojo template so modelCopy output matches the compiled model content.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/StringEnumRef.java, line 11:

<comment>The modelCopy output for this model is an empty class: it loses the enum constants (SUCCESS/FAILURE/UNCLASSIFIED), the value field, and all serialization helpers that the src/main model version and the gson modelCopy version retain. Every modelCopy file renders as an empty property-less stub, so the user-defined-template modelCopy output is broken, not just this one. Regenerate/fix the pojo template so modelCopy output matches the compiled model content.</comment>

<file context>
@@ -0,0 +1,61 @@
+@JsonPropertyOrder({
+})
+@JsonTypeName("StringEnumRef")
+public class StringEnumRef {
+  public StringEnumRef() {
+  }
</file context>

@@ -0,0 +1,82 @@
.github/workflows/maven.yml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The sample commits info.md and the six docs/*ApiDocumentation.md files, but none are listed in this FILES manifest and the new config no longer generates them (it produces README.md and docs/*Api.md instead; info.md/*ApiDocumentation.md come from the old config's files: entries). Files absent from FILES are never removed or rewritten by the generator, so the sample will keep these stale leftovers and stay out of sync with bin/generate-samples.sh output. Delete these seven orphaned files.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-user-defined-templates/.openapi-generator/FILES, line 8:

<comment>The sample commits `info.md` and the six `docs/*ApiDocumentation.md` files, but none are listed in this FILES manifest and the new config no longer generates them (it produces README.md and `docs/*Api.md` instead; `info.md`/`*ApiDocumentation.md` come from the old config's `files:` entries). Files absent from FILES are never removed or rewritten by the generator, so the sample will keep these stale leftovers and stay out of sync with `bin/generate-samples.sh` output. Delete these seven orphaned files.</comment>

<file context>
@@ -0,0 +1,82 @@
+api/openapi.yaml
+build.gradle
+build.sbt
+docs/AuthApi.md
+docs/Bird.md
+docs/BodyApi.md
</file context>

{{#joda}}
"joda-time" % "joda-time" % "2.12.0",
{{/joda}}
"jakarta.annotation" % "jakarta.annotation-api" % "{{#useJakartaEe}}2.1.1{{/useJakartaEe}}{{^useJakartaEe}}1.3.5{{/useJakartaEe}}",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: On Java 11+, SBT-generated clients fail to compile because the generated sources reference javax.annotation.Generated, but this build declares only jakarta.annotation-api. Add the matching javax.annotation API dependency or generate the corresponding Jakarta annotation imports.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.sbt.mustache, line 58:

<comment>On Java 11+, SBT-generated clients fail to compile because the generated sources reference `javax.annotation.Generated`, but this build declares only `jakarta.annotation-api`. Add the matching `javax.annotation` API dependency or generate the corresponding Jakarta annotation imports.</comment>

<file context>
@@ -0,0 +1,85 @@
+      {{#joda}}
+      "joda-time" % "joda-time" % "2.12.0",
+      {{/joda}}
+      "jakarta.annotation" % "jakarta.annotation-api" % "{{#useJakartaEe}}2.1.1{{/useJakartaEe}}{{^useJakartaEe}}1.3.5{{/useJakartaEe}}",
+      {{#withAWSV4Signature}}
+      "software.amazon.awssdk" % "auth" % "2.20.157",
</file context>

}


public static HashSet<String> openapiFields;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: In the Jackson-generated models, openapiFields/openapiRequiredFields are declared and populated but never read: the okhttp-gson template consumes them in validateJsonElement, which the Jackson port omits. The same template should not emit these fields (nor the unused Map, JsonCreator, JsonValue imports) for the Jackson/JSON-B serializers, otherwise every generated model carries dead code.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-jackson-user-defined-templates/src/main/java/org/openapitools/client/model/TestQueryStyleFormExplodeTrueArrayStringQueryObjectParameter.java, line 115:

<comment>In the Jackson-generated models, `openapiFields`/`openapiRequiredFields` are declared and populated but never read: the okhttp-gson template consumes them in `validateJsonElement`, which the Jackson port omits. The same template should not emit these fields (nor the unused `Map`, `JsonCreator`, `JsonValue` imports) for the Jackson/JSON-B serializers, otherwise every generated model carries dead code.</comment>

<file context>
@@ -0,0 +1,128 @@
+  }
+
+
+  public static HashSet<String> openapiFields;
+  public static HashSet<String> openapiRequiredFields;
+
</file context>

* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: toIndentedString(Object) is private and never called: toString() only appends "}" without invoking it. Remove the dead method, or have toString() use it, to match the standard pojo template where the field lines are emitted.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/echo_api/java/okhttp-jackson-user-defined-templates/modelCopy/Tag.java, line 44:

<comment>toIndentedString(Object) is private and never called: toString() only appends "}" without invoking it. Remove the dead method, or have toString() use it, to match the standard pojo template where the field lines are emitted.</comment>

<file context>
@@ -0,0 +1,61 @@
+   * Convert the given object to string with each line indented by 4 spaces
+   * (except the first line).
+   */
+  private String toIndentedString(Object o) {
+    return o == null ? "null" : o.toString().replace("\n", "\n    ");
+  }
</file context>

…builds

JSON.mustache imports com.fasterxml.jackson.datatype.joda.JodaModule (or
tools.jackson.datatype.joda.JodaModule under Jackson 3) and registers it on
the mapper whenever dateLibrary=joda is combined with a Jackson
serializationLibrary, but none of the three generated build files declared
that artifact -- they carried only joda-time. A client generated that way
failed to compile with "package com.fasterxml.jackson.datatype.joda does not
exist".

The omission was inherited from okhttp-gson, whose JSON.mustache is Gson-only
and handles Joda with hand-written DateTimeTypeAdapters, so joda-time alone
was correct there. It stops being correct once the same build files serve the
Jackson serializers.

jackson-datatype-joda is published for both generations at the versions this
library already pins -- com.fasterxml.jackson.datatype:2.22.1 and
tools.jackson.datatype:3.2.1 -- so the dependency follows the jackson-core and
jackson-databind pattern and needs no useJackson3 gate, unlike
jackson-datatype-jsr310.

No sample sets dateLibrary: joda, so this path has no CI coverage; verified by
generating a client for each Jackson generation and compiling both.
82f8bfe dropped the README.mustache -> info.md and api_doc.mustache ->
Documentation.md filename mappings from the two user-defined-templates
configs, and 49d04be regenerated the samples. That run added the new
README.md and docs/*Api.md outputs but left the old ones in place, so both
spellings have been sitting side by side since.

The generator only rewrites or removes files listed in
.openapi-generator/FILES, and these seven per sample are not listed, so they
would have survived every future regeneration. The manifests themselves are
already correct and need no change.

Removes info.md and docs/{Auth,Body,Form,Header,Path,Query}ApiDocumentation.md
from both okhttp-user-defined-templates and
okhttp-jackson-user-defined-templates. Nothing references them: they are not
in either FILES manifest, not linked from README.md, and not part of the pom
or gradle build.
Both live in the discriminator-root serializer that pojo.mustache generates
for a hasChildren model with additionalProperties: true.

A nested value lost its additional properties when its runtime type was a
hierarchy root. JSON registers a CustomJsonbSerializer for every
non-hasChildren model before building plainJsonb and adds the roots only
afterwards, so a nested Cat or Dog kept its flattening but a nested Animal or
GrandparentAnimal fell through to plain bean mapping, where the @JsonbTransient
holder is dropped. Additional-property values now render through a separate
toNestedJsonValue() on the configured Jsonb; the outer value stays on
plainJsonb, which is what keeps the serializer from re-entering itself. This
follows the delegation deserializeBranch already uses.

An additional property could also take a subtype's declared name. The guard
tested the root's openapiFields and then whether the key was already in the
serialized output, but a subtype serializer omits a declared property whose
value is null -- so declawed=null together with
putAdditionalProperty("declawed", x) wrote x under the declared name and, on
the way back, migrated it into the declared field. A generated
declaredFields() helper now resolves the runtime type's own openapiFields by
exact class match over the discriminator mappings, so the declared name wins
whether or not the subtype emitted it. Exact matching rather than instanceof
keeps a mid-level subtype from shadowing its own children.

The second defect only surfaces when the subtype has no serializer of its own,
which is why the petstore hierarchy does not show it: Cat and Dog are
additionalProperties: true and Yasson dispatches to their own serializers.

Regenerating the okhttp samples touches only Animal and GrandparentAnimal, the
two models that are both a discriminator root and additionalProperties: true.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 20 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.gradle.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.gradle.mustache:114">
P1: When `useJackson3` and `joda` are enabled, this dependency combines the Jackson 3 group with the Jackson 2 `$jackson_version`, so the generated Gradle build requests an unavailable or incompatible `tools.jackson.datatype:jackson-datatype-joda:2.x` artifact. Select `$jackson3_version` for Jackson 3 and `$jackson_version` otherwise, and apply the same conditional to the new POM dependency.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

{{#joda}}
implementation 'joda-time:joda-time:2.12.0'
{{#isJackson}}
implementation "{{jacksonPackage}}.datatype:jackson-datatype-joda:$jackson_version"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When useJackson3 and joda are enabled, this dependency combines the Jackson 3 group with the Jackson 2 $jackson_version, so the generated Gradle build requests an unavailable or incompatible tools.jackson.datatype:jackson-datatype-joda:2.x artifact. Select $jackson3_version for Jackson 3 and $jackson_version otherwise, and apply the same conditional to the new POM dependency.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/okhttp/build.gradle.mustache, line 114:

<comment>When `useJackson3` and `joda` are enabled, this dependency combines the Jackson 3 group with the Jackson 2 `$jackson_version`, so the generated Gradle build requests an unavailable or incompatible `tools.jackson.datatype:jackson-datatype-joda:2.x` artifact. Select `$jackson3_version` for Jackson 3 and `$jackson_version` otherwise, and apply the same conditional to the new POM dependency.</comment>

<file context>
@@ -110,6 +110,9 @@ dependencies {
     {{#joda}}
     implementation 'joda-time:joda-time:2.12.0'
+    {{#isJackson}}
+    implementation "{{jacksonPackage}}.datatype:jackson-datatype-joda:$jackson_version"
+    {{/isJackson}}
     {{/joda}}
</file context>

…matrix

Found by generating the okhttp client for a live spring-petclinic-rest server
across all four serialization libraries x 17 parameter combinations (68 runs),
then compiling and exercising each against the running server. All changes are
confined to Java/libraries/okhttp/ plus one okhttp-gated block in
JavaClientCodegen; okhttp-gson and the shared root Java/*.mustache are untouched.

pojo.mustache / JSON.mustache

* readOnly properties never deserialized on Jackson 2 and Jackson 3. The field
  carried @JsonProperty(access = Access.READ_ONLY), which is the SERVER reading
  of OpenAPI readOnly - it means "serialize out, ignore on input", so Jackson
  discarded exactly the values a client needs. Setters are suppressed for
  readOnly vars and the readonly-args constructor had no @JsonCreator, so all
  three paths into the field were closed. Drop the access attribute (matching
  the shared root pojo.mustache, the only other emitter) and annotate the
  constructor. Every id, plus Owner.pets/Pet.visits/ProblemDetail, was null.

* serializationLibrary=jsonb + dateLibrary=joda did not compile: the joda format
  imports were {{#isGson}}-gated while the JSON-B adapters, their fields and
  their setters all reference DateTimeFormatter - eight unresolved symbols. The
  joda adapters were also registered only when a format had been set explicitly,
  so Yasson (which has no joda support) fell back to bean mapping; register them
  unconditionally with ISO defaults, as the FileAdapter already does.

* dateLibrary=legacy corrupted every format: date value. legacy maps both date
  and date-time onto java.util.Date, so the mapper-wide RFC3339 format applied
  to date-only properties: at Europe/Berlin, 2020-01-15 went out as
  "2020-01-14T23:00:00.000+00:00" - simultaneously a full timestamp the server
  rejects and a one-day backward shift. Select the representation per property
  instead, through one shared dateOnlyFormat() so all four serializers agree on
  the wire. Note a bare @jsonformat pattern is insufficient: with no explicit
  timezone it resolves against the mapper default, which Jackson sets to UTC
  rather than the JVM zone, and the day still shifts.

* The generated JSON-B CustomJsonbDeserializer binds each property by declared
  type, so a field-level @JsonbTypeAdapter is never consulted; date-only
  properties now bind through an explicit helper.

* RFC3339JavaTimeModule registers its deserializers after calling
  super.setupModule(), and SimpleModule forwards _deserializers only if that
  lazily-created map is already non-null - so on Jackson 2 the lenient RFC3339
  parsing never took effect at all. Build the equivalent module locally rather
  than patching a template shared by six libraries. The upstream fix belongs in
  RFC3339JavaTimeModule itself.

* generateBuilders and generateConstructorWithAllArgs were silently inert:
  neither flag appeared anywhere in the okhttp pojo template, unlike restclient,
  resttemplate, webclient and native. Wire up the shared javaBuilder partial and
  the all-args constructor.

api.mustache

* performBeanValidation removed the required-parameter null checks instead of
  adding to them - they lived inside the inverted section - and the substituted
  validator never fires for a plain null argument, so a clear ApiException
  became a NullPointerException or the null reached the server. The checks are
  now unconditional and validation is additive.

JavaClientCodegen

* defaultToEmptyContainer is a rule string, but DefaultCodegen only logs
  unrecognised tokens and then sets the flag unconditionally, so the boolean
  spelling every other option uses - defaultToEmptyContainer=true - matched no
  rule and silently produced the OPPOSITE of the documented behaviour. Reject
  it with a message naming the real syntax. Validating this for every generator
  belongs upstream; this is gated to okhttp.

Verified: 42 okhttp configs regenerated, all samples compile, 501 okhttp invoker
tests and 434 okhttp-jsonb tests green, JavaClientCodegenTest green, and each
fix reproduced before/after against the live server. Zero okhttp-gson diff and
zero shared-template diff.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 existing issues remain and 40 new issues found across 280 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/PetComposition.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/PetComposition.java:446">
P2: When a `PetComposition` contains an undeclared JSON property, `toBuilder().build()` silently drops it because the builder has no `additionalProperties` copy path. Preserve the additional-properties map in `toBuilder()` (and expose a builder setter if needed) so the documented shallow copy retains the complete model state.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Order.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Order.java:428">
P2: When an `Order` has undeclared JSON properties, `toBuilder()` drops them from the rebuilt object. Copy `additionalProperties` as part of the builder conversion, including the corresponding builder support.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/GrandparentAnimal.java">

<violation number="1">
P2: When a `GrandparentAnimal` has undeclared properties, `toBuilder()` silently drops them because the builder copies only `petType`. Add builder support for `additionalProperties` and copy the map so the documented shallow-copy operation preserves serialized state.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/PetRef.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/PetRef.java:447">
P2: When a `PetRef` contains an undeclared JSON property, `toBuilder().build()` drops it because `toBuilder()` copies only the six schema fields. Copy `additionalProperties` as part of the documented shallow clone.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/OuterComposite.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/OuterComposite.java:288">
P2: `toBuilder()` drops all undeclared JSON fields. Since `OuterComposite` stores those fields in `additionalProperties`, `toBuilder().build()` silently loses them; copy the map through the builder as part of this shallow copy.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/AllOfModelArrayAnyOf.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/AllOfModelArrayAnyOf.java:325">
P2: `toBuilder()` drops every entry in `additionalProperties`, so rebuilding a model with undeclared JSON fields silently loses those fields. Copy the additional-properties map as part of the builder state (and expose the corresponding builder assignment) before returning the rebuilt instance.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ArrayDefault.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ArrayDefault.java:267">
P2: When an `ArrayDefault` contains undeclared JSON fields, `toBuilder()` drops them despite documenting a shallow copy of the instance. Copy `additionalProperties` into the builder as well.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/NullableClass.java">

<violation number="1">
P2: When a model contains undeclared JSON fields, `toBuilder()` drops `additionalProperties`, so `build()` silently loses data. Copy `additionalProperties` into the builder instance as part of the shallow copy.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/PropertyNameCollision.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/PropertyNameCollision.java:284">
P2: When a `PropertyNameCollision` contains an undeclared JSON property, `toBuilder()` drops that property because it copies only the declared fields. Preserve `additionalProperties` when constructing the builder copy so `toBuilder()` matches its documented shallow-copy contract.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/AllOfModelArrayAnyOfAllOfLinkListColumn1.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/AllOfModelArrayAnyOfAllOfLinkListColumn1.java:226">
P2: When this model contains undeclared JSON fields, `toBuilder()` drops them because it copies only `value`, so the rebuilt model serializes without those fields. Preserve `additionalProperties` through the builder and `toBuilder()` copy.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/Category.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/Category.java:249">
P2: When a `Category` contains undeclared properties, `toBuilder().build()` silently drops them because this copy only transfers `id` and `name`. Copy `additionalProperties` as part of the shallow copy so builder round-trips preserve deserialized or explicitly added data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/SpecialModelName.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/SpecialModelName.java:249">
P2: When this model contains undeclared JSON properties, `toBuilder().build()` silently drops them because `toBuilder()` copies only the declared fields. Copy `additionalProperties` shallowly as part of the builder conversion, and update the builder template so generated models retain these fields.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/FreeFormObjectTestClass.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/FreeFormObjectTestClass.java:252">
P2: When this model contains undeclared JSON properties, `toBuilder()` drops them because it copies only the declared fields. Preserve `additionalProperties` in the builder copy, including a builder path for that map, so the documented shallow copy retains the full model state.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/model/Animal.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/model/Animal.java:358">
P2: When an `Animal` contains an undeclared property, `toBuilder().build()` drops it because `toBuilder()` copies only `className` and `color`. Copy `additionalProperties` as well, shallowly, so rebuilding the model preserves its serialized data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/Apple.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/Apple.java:248">
P2: `toBuilder()` drops undeclared properties. When `putAdditionalProperty` has captured a response field, this chain copies only declared fields, so the rebuilt model loses data during later serialization. Copy `additionalProperties` through the builder as well.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/ComplexQuadrilateral.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/ComplexQuadrilateral.java:248">
P2: When a model contains undeclared JSON fields, `toBuilder()` drops them even though it promises a shallow copy of the instance. Copy `additionalProperties` through the builder so builder-based copy/edit/send workflows preserve unknown fields.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/EnumArrays.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/EnumArrays.java:331">
P2: When `EnumArrays` contains an undeclared JSON property, `toBuilder().build()` silently drops it because this chain copies only declared fields. Copy `additionalProperties` in the builder template and regenerate these models.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/MixedPropertiesAndAdditionalPropertiesClass.java">

<violation number="1">
P2: When this model contains undeclared properties, `toBuilder()` silently loses them because the builder has no additional-properties copy path. Preserve `additionalProperties` in the builder and include it in `toBuilder()` so its documented shallow-copy behavior does not discard JSON data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/model/AllOfRefToLong.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/model/AllOfRefToLong.java:303">
P2: When a JSON-B object contains undeclared fields, `toBuilder()` drops them because it copies only `id`; the returned model then loses those fields on access or serialization. Copy `additionalProperties` as part of the builder state.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/OuterComposite.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/OuterComposite.java:285">
P2: When an `OuterComposite` contains undeclared JSON properties, `toBuilder()` silently loses them because the builder has no `additionalProperties` copy. Add builder support for that map and copy it in `toBuilder()` so the documented shallow-copy operation preserves the full model state.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/NullableFieldsValue.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/NullableFieldsValue.java:249">
P2: When a model contains undeclared JSON properties, `toBuilder()` drops them because it copies only `before` and `after`. Copy `additionalProperties` as well so the documented shallow-copy contract preserves the model state.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/ModelWithOneOfAnyOfProperties.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/ModelWithOneOfAnyOfProperties.java:250">
P2: When this model contains undeclared properties, `toBuilder()` drops them because it copies only the two declared fields. Preserve `additionalProperties` when creating the builder so the documented shallow copy does not lose data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Dog.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Dog.java:237">
P2: When a `Dog` contains undeclared properties, `toBuilder()` drops them from the rebuilt instance. Copy `getAdditionalProperties()` into the builder so editing a known field does not silently lose data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Pet.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Pet.java:447">
P2: When a `Pet` contains undeclared properties, `toBuilder()` drops them because it copies only the six schema fields. Copy `additionalProperties` as part of the documented shallow copy so rebuilding does not lose serialized data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ObjectWithDeprecatedFields.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ObjectWithDeprecatedFields.java:345">
P2: When this model contains an undeclared JSON property, `toBuilder().build()` drops it because the new copy path transfers only declared fields. Preserve `additionalProperties` through the builder as well.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Name.java">

<violation number="1">
P2: Because `snake_case` and `123Number` are OpenAPI read-only properties, removing `READ_ONLY` makes generated `Name` objects include server-managed values in request JSON. Preserve read-only property access while handling response deserialization through the creator path.</violation>

<violation number="2">
P2: When a `Name` contains undeclared properties, `toBuilder().build()` silently drops them because `toBuilder()` never copies `additionalProperties`. Include the additional-property map in the builder copy, or change the method contract if that loss is intentional.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/Foo.java">

<violation number="1">
P2: Calling `Foo.toBuilder().build()` loses every undeclared JSON field. `Foo` stores those fields in `additionalProperties` via `putAdditionalProperty`, but this method copies only `bar`. Add an `additionalProperties` builder member/setter and copy it in `toBuilder()`.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/model/AllOfModelArrayAnyOf.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jsonb/src/main/java/org/openapitools/client/model/AllOfModelArrayAnyOf.java:419">
P2: When a JSON-B model contains an undeclared property, the new `toBuilder()` drops it. Preserve `getAdditionalProperties()` in the builder copy so the documented shallow copy does not lose data that the custom deserializer captured and serializer emits.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/NewPet.java">

<violation number="1">
P2: With default access here, Jackson serializes `categoryAllOfRefDescriptionReadonly` as well as deserializes it. A populated `NewPet` can therefore send `category_allOf_ref_description_readonly` in request JSON despite the schema's `readOnly: true`; use `WRITE_ONLY` or an equivalent request serializer.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ScaleneTriangle.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ScaleneTriangle.java:251">
P2: When a model contains undeclared properties, `toBuilder()` drops them because it copies only `shapeType` and `triangleType`. Copy `additionalProperties` into the builder before returning it.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/PetWithRequiredTags.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/PetWithRequiredTags.java:453">
P2: When this model contains an undeclared property, `toBuilder().build()` drops it because the new builder copies only declared fields. Add builder support for `additionalProperties` and copy it in `toBuilder()` so the documented shallow-copy contract preserves JSON data.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/User.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/User.java:598">
P2: When a `User` contains an undeclared property, `toBuilder().build()` silently drops it because `toBuilder()` copies only declared fields. Preserve `additionalProperties` through the builder so the documented shallow copy remains complete.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/NewPet.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/NewPet.java:553">
P2: When a `NewPet` contains undeclared properties, `toBuilder()` silently drops them despite documenting a shallow copy of the instance. Preserve `additionalProperties` in the builder and in `toBuilder()` (and update the builder template so generated models retain this state).</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/AllOfRefToLong.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/AllOfRefToLong.java:215">
P2: When this model contains undeclared JSON fields, `toBuilder().build()` drops them because this chain copies only `id`. Copy `getAdditionalProperties()` through the builder, or otherwise preserve it in the builder's copy path.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ClassModel.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ClassModel.java:215">
P2: When a `ClassModel` contains undeclared JSON fields, `toBuilder()` drops them because the builder copies only `propertyClass`. Add builder support for `additionalProperties` and include it in this copy chain.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Drawing.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Drawing.java:333">
P2: toBuilder() does not copy the `additionalProperties` map, so for this model (which declares additionalProperties with @JsonAnySetter/@JsonAnyGetter) calling toBuilder().build() silently loses all undeclared properties. The javaBuilder.mustache template only chains the declared vars; extend it to also copy the additional-properties map when the model has `additionalProperties: true`.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/FormatTest.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/FormatTest.java:788">
P2: `toBuilder()` silently drops all undeclared additional properties. FormatTest supports `additionalProperties` via `@JsonAnySetter`/`@JsonAnyGetter` (`putAdditionalProperty`/`getAdditionalProperties`), but the generated Builder exposes no setter for it and `toBuilder()` never copies it, so `instance.toBuilder().build()` loses any undeclared properties. Add a copy of `additionalProperties` in `toBuilder()` (and ideally a builder method) so the builder round-trips the model faithfully.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ReadOnlyFirst.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ReadOnlyFirst.java:45">
P2: When `ReadOnlyFirst` is used in a request, Jackson now serializes the response-only `bar` property because this annotation removed `READ_ONLY`. Preserve creator-based response deserialization while excluding `readOnly` properties from outbound JSON.</violation>
</file>

<file name="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/TriangleInterface.java">

<violation number="1" location="samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/TriangleInterface.java:213">
P2: When `TriangleInterface` contains an undeclared property, `toBuilder()` drops it because the builder copies only `triangleType`. Preserve `additionalProperties` in the builder copy so `toBuilder()` fulfills its shallow-copy contract.</violation>
</file>

Note: This PR contains a large number of files. cubic selects up to 200 of the highest-priority eligible files for this review, so some files may not have been reviewed.
Requires human review: Auto-approval blocked because this review re-detected 7 unresolved issues already reported by Cubic.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

/**
* Create a builder with a shallow copy of this instance.
*/
public PetComposition.Builder toBuilder() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a PetComposition contains an undeclared JSON property, toBuilder().build() silently drops it because the builder has no additionalProperties copy path. Preserve the additional-properties map in toBuilder() (and expose a builder setter if needed) so the documented shallow copy retains the complete model state.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/PetComposition.java, line 446:

<comment>When a `PetComposition` contains an undeclared JSON property, `toBuilder().build()` silently drops it because the builder has no `additionalProperties` copy path. Preserve the additional-properties map in `toBuilder()` (and expose a builder setter if needed) so the documented shallow copy retains the complete model state.</comment>

<file context>
@@ -374,5 +374,84 @@ private String toIndentedString(Object o) {
+  /**
+  * Create a builder with a shallow copy of this instance.
+  */
+  public PetComposition.Builder toBuilder() {
+    return new PetComposition.Builder()
+      .id(getId())
</file context>

* Create a builder with a shallow copy of this instance.
*/
public Order.Builder toBuilder() {
return new Order.Builder()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When an Order has undeclared JSON properties, toBuilder() drops them from the rebuilt object. Copy additionalProperties as part of the builder conversion, including the corresponding builder support.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Order.java, line 428:

<comment>When an `Order` has undeclared JSON properties, `toBuilder()` drops them from the rebuilt object. Copy `additionalProperties` as part of the builder conversion, including the corresponding builder support.</comment>

<file context>
@@ -355,5 +355,84 @@ private String toIndentedString(Object o) {
+  * Create a builder with a shallow copy of this instance.
+  */
+  public Order.Builder toBuilder() {
+    return new Order.Builder()
+      .id(getId())
+      .petId(getPetId())
</file context>

@@ -0,0 +1,232 @@
/*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a GrandparentAnimal has undeclared properties, toBuilder() silently drops them because the builder copies only petType. Add builder support for additionalProperties and copy the map so the documented shallow-copy operation preserves serialized state.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/GrandparentAnimal.java, line 228:

<comment>When a `GrandparentAnimal` has undeclared properties, `toBuilder()` silently drops them because the builder copies only `petType`. Add builder support for `additionalProperties` and copy the map so the documented shallow-copy operation preserves serialized state.</comment>

<file context>
@@ -174,5 +174,59 @@ private String toIndentedString(Object o) {
+  */
+  public GrandparentAnimal.Builder toBuilder() {
+    return new GrandparentAnimal.Builder()
+      .petType(getPetType());
+  }
+
</file context>

Comment on lines +447 to +453
return new PetRef.Builder()
.id(getId())
.category(getCategory())
.name(getName())
.photoUrls(getPhotoUrls())
.tags(getTags())
.status(getStatus());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a PetRef contains an undeclared JSON property, toBuilder().build() drops it because toBuilder() copies only the six schema fields. Copy additionalProperties as part of the documented shallow clone.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/PetRef.java, line 447:

<comment>When a `PetRef` contains an undeclared JSON property, `toBuilder().build()` drops it because `toBuilder()` copies only the six schema fields. Copy `additionalProperties` as part of the documented shallow clone.</comment>

<file context>
@@ -374,5 +374,84 @@ private String toIndentedString(Object o) {
+  * Create a builder with a shallow copy of this instance.
+  */
+  public PetRef.Builder toBuilder() {
+    return new PetRef.Builder()
+      .id(getId())
+      .category(getCategory())
</file context>
Suggested change
return new PetRef.Builder()
.id(getId())
.category(getCategory())
.name(getName())
.photoUrls(getPhotoUrls())
.tags(getTags())
.status(getStatus());
PetRef.Builder builder = new PetRef.Builder()
.id(getId())
.category(getCategory())
.name(getName())
.photoUrls(getPhotoUrls())
.tags(getTags())
.status(getStatus());
builder.instance.additionalProperties = getAdditionalProperties();
return builder;

return new OuterComposite.Builder()
.myNumber(getMyNumber())
.myString(getMyString())
.myBoolean(getMyBoolean());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: toBuilder() drops all undeclared JSON fields. Since OuterComposite stores those fields in additionalProperties, toBuilder().build() silently loses them; copy the map through the builder as part of this shallow copy.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson/src/main/java/org/openapitools/client/model/OuterComposite.java, line 288:

<comment>`toBuilder()` drops all undeclared JSON fields. Since `OuterComposite` stores those fields in `additionalProperties`, `toBuilder().build()` silently loses them; copy the map through the builder as part of this shallow copy.</comment>

<file context>
@@ -224,5 +224,69 @@ private String toIndentedString(Object o) {
+    return new OuterComposite.Builder()
+      .myNumber(getMyNumber())
+      .myString(getMyString())
+      .myBoolean(getMyBoolean());
+  }
+
</file context>

*/
public ClassModel.Builder toBuilder() {
return new ClassModel.Builder()
.propertyClass(getPropertyClass());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a ClassModel contains undeclared JSON fields, toBuilder() drops them because the builder copies only propertyClass. Add builder support for additionalProperties and include it in this copy chain.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ClassModel.java, line 215:

<comment>When a `ClassModel` contains undeclared JSON fields, `toBuilder()` drops them because the builder copies only `propertyClass`. Add builder support for `additionalProperties` and include it in this copy chain.</comment>

<file context>
@@ -161,5 +161,59 @@ private String toIndentedString(Object o) {
+  */
+  public ClassModel.Builder toBuilder() {
+    return new ClassModel.Builder()
+      .propertyClass(getPropertyClass());
+  }
+
</file context>

* Create a builder with a shallow copy of this instance.
*/
public Drawing.Builder toBuilder() {
return new Drawing.Builder()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: toBuilder() does not copy the additionalProperties map, so for this model (which declares additionalProperties with @JsonAnySetter/@JsonAnyGetter) calling toBuilder().build() silently loses all undeclared properties. The javaBuilder.mustache template only chains the declared vars; extend it to also copy the additional-properties map when the model has additionalProperties: true.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/Drawing.java, line 333:

<comment>toBuilder() does not copy the `additionalProperties` map, so for this model (which declares additionalProperties with @JsonAnySetter/@JsonAnyGetter) calling toBuilder().build() silently loses all undeclared properties. The javaBuilder.mustache template only chains the declared vars; extend it to also copy the additional-properties map when the model has `additionalProperties: true`.</comment>

<file context>
@@ -268,5 +268,74 @@ private String toIndentedString(Object o) {
+  * Create a builder with a shallow copy of this instance.
+  */
+  public Drawing.Builder toBuilder() {
+    return new Drawing.Builder()
+      .mainShape(getMainShape())
+      .shapeOrNull(getShapeOrNull())
</file context>

/**
* Create a builder with a shallow copy of this instance.
*/
public FormatTest.Builder toBuilder() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: toBuilder() silently drops all undeclared additional properties. FormatTest supports additionalProperties via @JsonAnySetter/@JsonAnyGetter (putAdditionalProperty/getAdditionalProperties), but the generated Builder exposes no setter for it and toBuilder() never copies it, so instance.toBuilder().build() loses any undeclared properties. Add a copy of additionalProperties in toBuilder() (and ideally a builder method) so the builder round-trips the model faithfully.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/FormatTest.java, line 788:

<comment>`toBuilder()` silently drops all undeclared additional properties. FormatTest supports `additionalProperties` via `@JsonAnySetter`/`@JsonAnyGetter` (`putAdditionalProperty`/`getAdditionalProperties`), but the generated Builder exposes no setter for it and `toBuilder()` never copies it, so `instance.toBuilder().build()` loses any undeclared properties. Add a copy of `additionalProperties` in `toBuilder()` (and ideally a builder method) so the builder round-trips the model faithfully.</comment>

<file context>
@@ -672,5 +672,139 @@ private String toIndentedString(Object o) {
+  /**
+  * Create a builder with a shallow copy of this instance.
+  */
+  public FormatTest.Builder toBuilder() {
+    return new FormatTest.Builder()
+      .integer(getInteger())
</file context>

@JsonTypeName("ReadOnlyFirst")
public class ReadOnlyFirst {
public static final String JSON_PROPERTY_BAR = "bar";
@JsonProperty(value = JSON_PROPERTY_BAR)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When ReadOnlyFirst is used in a request, Jackson now serializes the response-only bar property because this annotation removed READ_ONLY. Preserve creator-based response deserialization while excluding readOnly properties from outbound JSON.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/ReadOnlyFirst.java, line 45:

<comment>When `ReadOnlyFirst` is used in a request, Jackson now serializes the response-only `bar` property because this annotation removed `READ_ONLY`. Preserve creator-based response deserialization while excluding `readOnly` properties from outbound JSON.</comment>

<file context>
@@ -42,7 +42,7 @@
 public class ReadOnlyFirst {
   public static final String JSON_PROPERTY_BAR = "bar";
-  @JsonProperty(value = JSON_PROPERTY_BAR, access = JsonProperty.Access.READ_ONLY)
+  @JsonProperty(value = JSON_PROPERTY_BAR)
   @javax.annotation.Nullable
   private String bar;
</file context>

/**
* Create a builder with a shallow copy of this instance.
*/
public TriangleInterface.Builder toBuilder() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When TriangleInterface contains an undeclared property, toBuilder() drops it because the builder copies only triangleType. Preserve additionalProperties in the builder copy so toBuilder() fulfills its shallow-copy contract.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/okhttp-jackson3/src/main/java/org/openapitools/client/model/TriangleInterface.java, line 213:

<comment>When `TriangleInterface` contains an undeclared property, `toBuilder()` drops it because the builder copies only `triangleType`. Preserve `additionalProperties` in the builder copy so `toBuilder()` fulfills its shallow-copy contract.</comment>

<file context>
@@ -161,5 +161,59 @@ private String toIndentedString(Object o) {
+  /**
+  * Create a builder with a shallow copy of this instance.
+  */
+  public TriangleInterface.Builder toBuilder() {
+    return new TriangleInterface.Builder()
+      .triangleType(getTriangleType());
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants