Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
  • O openapi-generator
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 3,476
    • Issues 3,476
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 402
    • Merge requests 402
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • OpenAPI Tools
  • openapi-generator
  • Issues
  • #3432
Closed
Open
Issue created Jul 23, 2019 by Administrator@rootContributor

[BUG][JAVA][OKHTTP] UnsupportedOperationException when using okhhtpclient with gzip feature enabled

Created by: hatzlj

Description

When instantiating a java/okhttp based client (generated with 'useGzipFeature' enabled) with parameters for oauth authentication, the constructor throws a java.lang.UnsupportedOperationException because the generated ApiClient tries to add the GzipRequestInterceptor' to an Unmodifiable Collection of the 'OkHttpClient.

The error originates in the generated code of the ApiClient during initialization, because httpClient.interceptors().add(...) is called after httpClient = builder.build();:

private void init() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addNetworkInterceptor(getProgressInterceptor());
        builder.addInterceptor(new GzipRequestInterceptor());
        httpClient = builder.build();

        // Enable gzip request compression
        httpClient.interceptors().add(new GzipRequestInterceptor());

        verifyingSsl = true;

        json = new JSON();

        // Set default User-Agent.
        setUserAgent("OpenAPI-Generator/0.2.1-SNAPSHOT/java");

        authentications = new HashMap<String, Authentication>();
}
openapi-generator version

4.0.0

OpenAPI declaration file content or url
openapi: 3.0.2
info:
  version: 0.2.1
  title: My Api
servers:
  - url: 'https://my.domain.org'
security:
  - myAuth:
      - 'api:access'
paths:
  '/api/v1/test':
    post:
      summary: Create a new object
      description: >-
        Creates a new object
      operationId: createObject
      tags:
        - command
        - object
      requestBody:
        $ref: '#/components/requestBodies/Object.JsonApi.v1'
      responses:
        '202':
          description: 'Object is being created'
        default:
          $ref: '#/components/responses/Error.JsonApi.v1'

components:
  # ------------------------------------------------------------------------- SCHEMAS
  schemas:
    # ------------------------------------------------------------------------- BASE SCHEMAS

    Object:
      description: 'An object'
      type: object
      required:
        - type
      properties:
        id:
          type: string
          description: 'The domain object identifier'
          example: 'c24c0bfb-7a15-4f17-94e2-9b112491b882'
        type:
          type: string
          readOnly: true
          description: 'The type of the domain object'
          default: 'my.api.model.Object'

    Object.JsonApi.v1:
      description: 'Object details, JSON:API v1.0'
      type: object
      required:
        - data
      properties:
        data:
          $ref: '#/components/schemas/Object'

    ErrorMetadata:
      # only used in responses for now, no need to declare required properties
      description: 'Basic error object, JSON:API v1.0'
      type: object
      properties:
        code:
          type: string
          description: 'Application specific error code'
          readOnly: true
          example: 'ERR_0011'
        status:
          type: string
          description: 'The HTTP status code applicable to this problem'
          readOnly: true
          example: '400'
        detail:
          type: string
          description: 'A verbose, human readable description of the error, may be localized'
          readOnly: true
          example: 'The validation has failed due to a missing parameter.'

    # ------------------------------------------------------------------------- RESPONSES
  responses:
    Error.JsonApi.v1:
      description: Unexpected, unspecified error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorMetadata'
          example:
            errors:
              - code: 'ERR_0500'
                status: '500'
                details: "Something happened, but we cannot determine what exactly."

  # ------------------------------------------------------------------------- REQUEST BODIES
  requestBodies:
    Object.JsonApi.v1:
      description: Object
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Object.JsonApi.v1'

  # ------------------------------------------------------------------------- SECURITY SCHEMES
  securitySchemes:
    myAuth:
      type: oauth2
      flows:
        password:
          tokenUrl: /api/v1/oauth2/token
          refreshUrl: /api/v1/oauth2/token
          scopes:
            api:access: "Access My REST API"
Command line used for generation

used via the openapi-generator-maven-plugin

<plugin>
                <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>4.0.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <phase>process-sources</phase>
                        <configuration>
                            <verbose>false</verbose>
                            <inputSpec>minimal.yaml</inputSpec>
                            <skipValidateSpec>false</skipValidateSpec>
                            <generatorName>java</generatorName>
                            <output>${project.build.directory}/generated-sources/openapi</output>
                            <addCompileSourceRoot>true</addCompileSourceRoot>
                            <apiPackage>my.api.client</apiPackage>
                            <modelPackage>my.api.model</modelPackage>
                            <modelNamePrefix>DTO</modelNamePrefix>
                            <generateApis>true</generateApis>
                            <generateApiTests>false</generateApiTests>
                            <generateApiDocumentation>true</generateApiDocumentation>
                            <generateModels>true</generateModels>
                            <generateModelTests>false</generateModelTests>
                            <generateModelDocumentation>true</generateModelDocumentation>
                            <generateSupportingFiles>true</generateSupportingFiles>
                            <groupId>my.api</groupId>
                            <artifactId>client</artifactId>
                            <artifactVersion>${project.version}</artifactVersion>
                            <withXml>false</withXml>
                            <configOptions>
                                <library>okhttp-gson</library>
                                <title>${project.name}</title>
                                <fullJavaUtil>false</fullJavaUtil>
                                <sourceFolder>src/main/java</sourceFolder>
                                <dateLibrary>java8</dateLibrary>
                                <java8>true</java8>
                                <booleanGetterPrefix>is</booleanGetterPrefix>
                                <useBeanValidation>true</useBeanValidation>
                                <performBeanValidation>true</performBeanValidation>
                                <useGzipFeature>true</useGzipFeature>
                                <caseInsensitiveResponseHeaders>true</caseInsensitiveResponseHeaders>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
Steps to reproduce
  1. generate the client with the sample file (oauth authentication included)
  2. instantiate a client by
String clientId = "myClientId";
String clientSecret = "myClientSecret";
String username = "myUsername";
String password = "myPasswd";
Map<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
ApiClient client = new ApiClient(clientId, clientSecret, params);

acutal output: java.lang.UnsupportedOperationException expected output: client is instantiated with specified parameters for OAuth

Related issues/PRs

see also https://github.com/square/okhttp/issues/2219

Suggest a fix

fix the ApiClient Mustache Template in line 147 to add the GzipRequestInterceptor before the builder is built

private void init() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addNetworkInterceptor(getProgressInterceptor());
        // Enable gzip request compression (MOVED HERE)
        builder.addInterceptor(new GzipRequestInterceptor());
                
        httpClient = builder.build();

       // gzip request compression MOVED FROM HERE
        
        verifyingSsl = true;

        json = new JSON();

        // Set default User-Agent.
        setUserAgent("OpenAPI-Generator/0.2.1-SNAPSHOT/java");

        authentications = new HashMap<String, Authentication>();
}
Assignee
Assign to
Time tracking