Client-Side Adoption

Generate Java clients that reconstruct your published contract instead of redefining it.

This guide explains how to generate contract-aligned Java clients from an OpenAPI Generics document.

For server-side projection, see Server-Side Adoption.
For architecture details, see Architecture.


Contents


Quick Start

1. Inherit the codegen parent

<parent>
    <groupId>io.github.blueprint-platform</groupId>
    <artifactId>openapi-generics-java-codegen-parent</artifactId>
    <version>1.2.0</version>
</parent>

2. Configure OpenAPI Generator

Use the OpenAPI Generator plugin as usual, but set the generator name to:

<generatorName>java-generics-contract</generatorName>

That is the OpenAPI Generics integration point.

Other options such as library, apiPackage, modelPackage, invokerPackage, and Spring Boot/Jackson configuration remain normal OpenAPI Generator choices.

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>generate-client</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <generatorName>java-generics-contract</generatorName>
                <inputSpec>${project.basedir}/src/main/resources/api-docs.yaml</inputSpec>

                <!-- Standard OpenAPI Generator choice. Use the client library that fits your project. -->
                <library>restclient</library>

                <!-- Standard generated package layout. Generic wrappers are emitted under modelPackage. -->
                <apiPackage>com.example.client.api</apiPackage>
                <modelPackage>com.example.client.dto</modelPackage>
                <invokerPackage>com.example.client.invoker</invokerPackage>

                <configOptions>
                    <!-- Choose the Spring/Jackson options that match your runtime. -->
                    <useSpringBoot3>true</useSpringBoot3>
                    <serializationLibrary>jackson</serializationLibrary>
                    <openApiNullable>false</openApiNullable>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

Expected generated wrapper shape:

public class ServiceResponseCustomerDto
    extends ServiceResponse<CustomerDto> {
}

Container example:

public class ServiceResponsePageCustomerDto
    extends ServiceResponse<Page<CustomerDto>> {
}

Page<T> is imported from openapi-generics-contract; the wrapper class itself is generated under your configured modelPackage.

3. Generate

mvn clean install

Generated sources are added automatically under:

target/generated-sources/openapi/src/gen/java

BYOE

Reuse your existing response envelope instead of ServiceResponse<T>.

<additionalProperties>
    <additionalProperty>
        openapi-generics.envelope=com.example.contract.ApiResponse
    </additionalProperty>
</additionalProperties>

Generated wrappers extend your envelope while preserving the published contract semantics.


BYOC

Reuse existing DTOs instead of generating duplicates.

<additionalProperties>
    <additionalProperty>
        openapi-generics.response-contract.CustomerDto=com.example.contract.CustomerDto
    </additionalProperty>
</additionalProperties>

Mapped models are imported directly from your shared contract module.


Supported Contracts

Built-in contracts:

ServiceResponse<T>
ServiceResponse<List<T>>
ServiceResponse<Set<T>>
ServiceResponse<Page<T>>

BYOE envelopes support the same response shapes.

Application-defined generic containers (for example Paging<T> or Window<T>) participate in the same projection and reconstruction pipeline when published through OpenAPI Generics metadata.


Fallback Mode

Disable OpenAPI Generics template patching:

<openapi.generics.skip>true</openapi.generics.skip>

To return completely to standard OpenAPI Generator behavior, use:

<generatorName>java</generatorName>

Verification

After generation, verify that:

  • wrappers extend existing contracts rather than redefining them
  • contract-owned infrastructure models are not regenerated
  • BYOE and BYOC types resolve successfully
  • configured generic containers are reconstructed identically to built-in containers

Usage Boundary

Generated wrappers are transport bindings, not application contracts.

Application code should depend on shared contract types such as:

ServiceResponse<CustomerDto>

or

ApiResponse<CustomerDto>

rather than generated wrapper classes.

Keep generated clients behind an adapter boundary so application code remains independent of generated artifacts.


Further Reading


This site uses Just the Docs, a documentation theme for Jekyll.