OpenAPITools / OpenAPITools/openapi-generator
[BUG][JAVA][OKHTTP] UnsupportedOperationException when using okhhtpclient with gzip feature enabled
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
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
- generate the client with the sample file (oauth authentication included)
- 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>();
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/ApiClient.mustache around line 147, where the generated ApiClient adds the gzip interceptor. Regenerate the client with the provided Maven plugin configuration and instantiate it with the OAuth parameters; done means initialization completes without UnsupportedOperationException when useGzipFeature is enabled.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100