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>();
}
4.0.0
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"
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>
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
see also https://github.com/square/okhttp/issues/2219
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>();
}
Same happens also within the constructor when adding the RetryingOauth interceptor
public ApiClient(String clientId, String clientSecret, Map<String, String> parameters) {
init();
RetryingOAuth retryingOAuth = new RetryingOAuth("/api/v1/oauth2/token", clientId, OAuthFlow.password, clientSecret, parameters);
authentications.put(
"myAuth",
retryingOAuth
);
httpClient.interceptors().add(retryingOAuth);
// Prevent the authentications from being modified.
authentications = Collections.unmodifiableMap(authentications);
}
will add a separate Bug report if necessary when this one is verified.
fix the ApiClient Mustache Template in line 147 to add the GzipRequestInterceptor before the builder is built
@hatzlj please file a PR so that we can review the fix more easily.
ok, i will try to do so as soon as possible
Any update on this? My team currently ran into this issue and we would like a fix in
I provided the referenced pull request to fix this issue. Waiting for approval and merge by maintainers.