Closed dmitry-weirdo closed 1 year ago
It is possible to have jakarta.*
imports with the following configOpts
<configOptions>
<library>spring-boot</library>
<oas3>true</oas3>
<useSpringController>true</useSpringController>
<!-- javax.* to jakarta.* -->
<useSpringBoot3>true</useSpringBoot3>
<useSpringfox>false</useSpringfox>
</configOptions>
it is also the case for the kotlin-spring generator, and it seems there is no useSpringBoot3
config option...
But there is already a MR For this, so I'll hope it will be in the December release 🙂
At first, the question was about java
generator (client), NOT ONLY the spring
generator (server).
Well, for the server, the jakarta.*
annotations are generated with spring
generator with spring-boot
library, yes.
However, there are no auth
classes generated for the server generator.
So the question is — I need a client generator with jakarta.*
annotations.
What for do I need this?
The problem arises for the clients of the external APIs.
To set the API key
For java
generator with rest-template
library, I set it like this (ApiClient
and ApiKeyAuth
are the generated classes):
@PostConstruct
private void setFdcApiKey() {
final ApiClient apiClient = fdcApi.getApiClient();
final ApiKeyAuth apiKeyAuth = (ApiKeyAuth) apiClient.getAuthentication(configProperty.getFdcApiClientKeyAuthentication());
apiKeyAuth.setApiKey(configProperty.getFdcApiKey());
}
To set the bearer token into the Authorization
header
rasApi
and apiClient
are the generated classes
this.apiClient.addDefaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + AuthenticationFilter.getBearerToken());
this.rasApi.setApiClient(this.apiClient);
The client generator works for me with 6.3.0 and above (with useJakartaEe=true
). Latest version is 6.6.0. Did you try that?
UPDATE: previously referred to snapshots - now not necessary.
@dsyer 6.3.0-SNAPSHOT
is not in the public maven repo yet, from where can I download it?
I see this link from README.md
, but this is not a built artifact.
Ok, I think I built it from master
with a command like this (according to https://github.com/OpenAPITools/openapi-generator/issues/14049 — since the default build is failing):
mvn clean install -DskipTests -Dmaven.javadoc.skip=true
The sonatype snapshot repos are public. You might need to declare them explicitly though (eg see the sample at https://github.com/dsyer/openapi-demo).
The client generator works for me with 6.3.0-SNAPSHOT (with useJakartaEe=true) as well. NOTE the snapshot I had produced BOTH javax and jakarta annotations, so hopefully that will be resolved before the release.
@jwilmoth-nc In my case only jakarta annotations where produced which is desired:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi-generator-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/openapi.yaml</inputSpec>
<!-- See https://openapi-generator.tech/docs/generators/java/ for config options -->
<generatorName>java</generatorName>
<configOptions>
<apiPackage>...</apiPackage>
<modelPackage>...</modelPackage>
<sourceFolder>src/gen/java/main</sourceFolder>
<dateLibrary>java8</dateLibrary>
<java8>true</java8>
<library>native</library>
<openApiNullable>false</openApiNullable>
<useBeanValidation>true</useBeanValidation>
<interfaceOnly>true</interfaceOnly>
<useJakartaEe>true</useJakartaEe>
</configOptions>
<generateApis>false</generateApis>
<generateApiTests>false</generateApiTests>
<generateApiDocumentation>false</generateApiDocumentation>
<generateModels>true</generateModels>
<generateModelDocumentation>false</generateModelDocumentation>
<generateModelTests>false</generateModelTests>
<generateSupportingFiles>false</generateSupportingFiles>
</configuration>
</execution>
</executions>
</plugin>
For my locally built 6.3.0-SNAPSHOT
the annotations are working (added <useJakartaEe>true</useJakartaEe>
to each of the configs, both server, and client).
Will try to use the external maven repo now, thanks for the hint.
My server config example:
<execution>
<id>my-service-backend</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/../etc/api/my_service.yaml</inputSpec>
<generatorName>spring</generatorName>
<configOptions>
<sourceFolder>src/main/java/main</sourceFolder>
<interfaceOnly>true</interfaceOnly>
<dateLibrary>java8</dateLibrary>
<openApiNullable>false</openApiNullable>
<apiPackage>my.generated.rest</apiPackage>
<modelPackage>my.generated.rest.model</modelPackage>
<hideGenerationTimestamp>true</hideGenerationTimestamp>
<useJakartaEe>true</useJakartaEe>
</configOptions>
<typeMappings>
<typeMapping>Double=java.math.BigDecimal</typeMapping>
</typeMappings>
</configuration>
</execution>
My client config example:
<execution>
<id>my-client</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/../etc/api/my.yaml</inputSpec>
<generatorName>java</generatorName>
<library>resttemplate</library>
<configOptions>
<sourceFolder>src/main/java/main</sourceFolder>
<dateLibrary>java8</dateLibrary>
<openApiNullable>false</openApiNullable>
<packageName>my.generated.ras</packageName>
<apiPackage>my.generated.ras.api</apiPackage>
<modelPackage>my.generated.ras.model</modelPackage>
<hideGenerationTimestamp>true</hideGenerationTimestamp>
<useJakartaEe>true</useJakartaEe>
</configOptions>
</configuration>
</execution>
UPDATE: Yes, it's working with the SonaType plugin repo:
<pluginRepository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
@jwilmoth-nc Your old classes are most probably from the old build. Please try to execute mvn clean
before the new regeneration.
@dmitry-weirdo a rebuild of the project with the -U
flag to force a new version of the snapshot worked.
Works for me. Maybe if you could post a complete reproducer, minimal project?
Guys, I am havin the same error output even if I set the tag useJakartaEe to true. I have an OpenAPI v.3 json file and just want to generate a client for it. Here is the pom I use:
`<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<!-- RELEASE_VERSION -->
<version>6.3.0</version>
<!-- /RELEASE_VERSION -->
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api.json</inputSpec>
<generatorName>java</generatorName>
<configOptions>
<asyncNative>true</asyncNative>
<useJakartaEe>true</useJakartaEe>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>`
which gives me the output when 'mvn clean compile'ing: "package jakarta.annotation does not exist" many times. What am I doing wrong?
Maybe you forgot to add a dependency (e.g. jakarta.annotation:jakarta.annotation-api:2.1.1
)?
For my locally built
6.3.0-SNAPSHOT
the annotations are working (added<useJakartaEe>true</useJakartaEe>
to each of the configs, both server, and client).Will try to use the external maven repo now, thanks for the hint.
My server config example:
<execution> <id>my-service-backend</id> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.basedir}/../etc/api/my_service.yaml</inputSpec> <generatorName>spring</generatorName> <configOptions> <sourceFolder>src/main/java/main</sourceFolder> <interfaceOnly>true</interfaceOnly> <dateLibrary>java8</dateLibrary> <openApiNullable>false</openApiNullable> <apiPackage>my.generated.rest</apiPackage> <modelPackage>my.generated.rest.model</modelPackage> <hideGenerationTimestamp>true</hideGenerationTimestamp> <useJakartaEe>true</useJakartaEe> </configOptions> <typeMappings> <typeMapping>Double=java.math.BigDecimal</typeMapping> </typeMappings> </configuration> </execution>
My client config example:
<execution> <id>my-client</id> <goals> <goal>generate</goal> </goals> <configuration> <inputSpec>${project.basedir}/../etc/api/my.yaml</inputSpec> <generatorName>java</generatorName> <library>resttemplate</library> <configOptions> <sourceFolder>src/main/java/main</sourceFolder> <dateLibrary>java8</dateLibrary> <openApiNullable>false</openApiNullable> <packageName>my.generated.ras</packageName> <apiPackage>my.generated.ras.api</apiPackage> <modelPackage>my.generated.ras.model</modelPackage> <hideGenerationTimestamp>true</hideGenerationTimestamp> <useJakartaEe>true</useJakartaEe> </configOptions> </configuration> </execution>
UPDATE: Yes, it's working with the SonaType plugin repo:
<pluginRepository> <id>sonatype</id> <url>https://oss.sonatype.org/content/repositories/snapshots</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository>
This worked for me, thank you !
N.B. the latest release is now 6.6.0 (no need for snapshots). I wonder when someone is going to close this issue as "resolved".
Hi everyone, even if this is now closed I still have a problem and see an error while generating. Here is the pom file: `<?xml version="1.0" encoding="UTF-8"?>
<groupId>myGroupId</groupId>
<artifactId>myArtifact</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>1.8.5</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>1.15.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>logging-interceptor</artifactId>
<version>4.11.0</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator</artifactId>
<version>6.6.0</version>
</dependency>
<!--<dependency>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.43</version>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.6.0</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api.json</inputSpec>
<generatorName>java</generatorName>
<configOptions>
<asyncNative>true</asyncNative>
<useJakartaEe>true</useJakartaEe>
<sourceFolder>src/gen/java</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
<!--<plugin>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>3.0.46</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/api.json</inputSpec>
<language>java</language>
<configOptions>
<sourceFolder>src/gen/java/main</sourceFolder>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>-->
</plugins>
</build>
`
What I see is a "cannot find symbol error":
target/generated-sources/openapi/src/gen/java/org/openapitools/client/api/MessagesV3Api.java[239,43] cannot find symbol symbol: class CreateMessageEnvelopeDTO location: class org.openapitools.client.api.MessagesV3Api
What am I missing?
If you need help configuring the plugin maybe ask on Stack Overflow. It doesn't look like it's a bug, but hard to say without a sample.
If you need help configuring the plugin maybe ask on Stack Overflow. It doesn't look like it's a bug, but hard to say without a sample.
I already have posted a question there. What I have is a json file api specification:
{ "openapi": "3.0.1", "info": { "title": "OpenAPI definition", "version": "v0" }, "servers": [ {"url":"https://int.zbp.bund.de","description":"ZBP-INT"} ], "security": [ { "bearerAuth": [] } ], "tags": [ { "name": "Messages V3", "description": "Get, create or manipulate messages." } ], "paths": { "/v3/mailbox/messages": { "put": { "tags": [ "Messages V3" ], "summary": "Insert a message into a Mailbox", "description": "## This endpoint inserts a message into the specified mailbox.\n**Returns** an object with ids for the newly created message\n", "operationId": "putMessageV3", "requestBody": { "description": "Multipartform of a signed CreateMessageDTO and attachments.\n\nJson part should always be first and must contain content length of the attachment in the Attachments list.\n\n### curl example:\n\n```-F 'json={....}'```\n```-F 'files=@sample.txt;type=text/plain'```\n\n", "content": { "multipart/form-data": { "schema": { "$ref": "#/components/schemas/CreateMessageMultiPartDoc" }, "encoding": { "files": { "contentType": "application/octet-stream", "headers": { "Content-Length": { "description": "This contains the length of the file in bytes.", "required": true, "style": "simple", "schema": { "type": "integer" } } } } } } } }, "responses": { "200": { "description": "The id of the created message is returned.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/CreateMessageResponseDTO" } } } }, "400": { "description": "
ZBP_400_006: field missing for filename in Attachment in json content.\n\n\n
ZBP_400_001: Type mismatch for parameter {parameter}\n\n
ZBP_400_001: parameter {parameter} not valid\n\n
ZBP_400_001: {constraintViolation}", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponseDTO" } } } }, "401": { "description": "
ZBP_401_001: malformed authorization token", "content": { "application/json": { "schema": { "type": "object", "properties": { "errorCode": { "type": "string", "description": "the machine readable error code for the current error" }, "description": { "type": "string", "description": "a human readable description of the error" } } } } } }, "403": { "description": "
ZBP_403_002: Given signature does not match with message content. Please re-sign and try again.\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponseDTO" } } } }, "404": { "description": "
ZBP_404_003: Can't find this mailbox.", "content": { "application/json": { "schema": { "type": "object", "properties": { "errorCode": { "type": "string", "description": "the machine readable error code for the current error" }, "description": { "type": "string", "description": "a human readable description of the error" } } } } } }, "409": { "description": "
ZBP_409_001: no trust level\n\n
ZBP_409_002: no subject in token\n\n
ZBP_409_003: wrong trust level", "content": { "application/json": { "schema": { "type": "object", "properties": { "errorCode": { "type": "string", "description": "the machine readable error code for the current error" }, "description": { "type": "string", "description": "a human readable description of the error" } } } } } }, "413": { "description": "
ZBP_413_001: Number of allowed attachments exceeded.\n\n
ZBP_413_002: Sum of attachments size exceeded limit.\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponseDTO" } } } }, "429": { "description": "
ZBP_429_001: Rate limit was exceeded.", "content": { "application/json": { "schema": { "type": "object", "properties": { "errorCode": { "type": "string", "description": "the machine readable error code for the current error" }, "description": { "type": "string", "description": "a human readable description of the error" } } } } } }, "500": { "description": "
ZBP_500_006: error processing request\n\n\n
ZBP_500_011: internal servlet error occurred\n\n
ZBP_500_012: Please check logs for more information", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponseDTO" } } } }, "503": { "description": "
ZBP_503_001: error uploading to file storage\n", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponseDTO" } } } } } } } }, "components": { "schemas": { "CreateMessageEnvelopeDTO": { "type": "object", "properties": { "content": { "type": "string", "example": "{\n \"mailboxUuid\": \"12345678-1234-1234-1234-123456789012\",\n \"stork_qaa_level\": 0,\n \"sender\": \"string\",\n \"title\": \"string\",\n \"content\": \"string\",\n \"service\": \"string\",\n \"senderUrl\": \"string\",\n \"reference\": \"string\",\n \"retrievalConfirmationAddress\": \"string\",\n \"replyAddress\": \"string\",\n \"attachments\": [\n {\n \"filename\": \"string\",\n \"sha512sum\": \"string\"\n \"content-length\": \"long\"\n }\n ]\n }" }, "sha512sum": { "type": "string", "description": "the signature of the above content" } } }, "CreateMessageMultiPartDoc": { "type": "object", "properties": { "json": { "$ref": "#/components/schemas/CreateMessageEnvelopeDTO" }, "files": { "type": "array", "items": { "type": "string", "description": "files to upload. Needs Content-Length header.\n\n### curl example:\n\n```-F 'files=@sample.txt;type=text/plain;headers=\"Content-Length: 200000\"```", "format": "binary" } } }, "description": "File parts need Content-Length header.\n\n### curl example:\n\n```-F 'files=@sample.txt;type=text/plain;headers=\\\"Content-Length: 200000\\\"```\n\n(swagger-ui is broken and ignores encoding.)\n" }, "ErrorResponseDTO": { "type": "object", "properties": { "errorCode": { "type": "string", "description": "the machine readable error code for the current error" }, "description": { "type": "string", "description": "a human readable description of the error" } } }, "CreateMessageResponseDTO": { "type": "object", "properties": { "mailboxHandle": { "type": "string", "description": "the uuid of the mailbox", "format": "uuid" }, "messageId": { "type": "integer", "description": "the long id for the message for compatibility reasons", "format": "int64" }, "messageUuid": { "type": "string", "description": "the uuid of the message", "format": "uuid" } } }, "CreateMessageDTO": { "type": "object", "properties": { "mailboxUuid": { "type": "string", "description": "This is the mailbox for the message", "format": "uuid" }, "stork_qaa_level": { "type": "integer", "description": "the stork qaa level of the message", "format": "int32" }, "sender": { "type": "string", "description": "the sender of the message" }, "title": { "type": "string", "description": "the title of the message" }, "content": { "type": "string", "description": "the content of the message" }, "service": { "type": "string", "description": "the service of the message" }, "senderUrl": { "type": "string", "description": "the senderUrl of the message" }, "reference": { "type": "string", "description": "the case reference of the message" }, "retrievalConfirmationAddress": { "type": "string", "description": "the retrieval confirmation address of the message" }, "replyAddress": { "type": "string", "description": "the reply address of the message" }, "attachments": { "type": "array", "items": { "$ref": "#/components/schemas/CreateAttachmentDTO" } } } }, "CreateAttachmentDTO": { "type": "object", "properties": { "filename": { "type": "string", "description": "the filename of the attachment" }, "sha512sum": { "type": "string", "description": "This is the sha512 checksum of the file. It will be verified on upload." }, "contentLength": { "type": "integer", "description": "Content length of the attachment", "format": "int64" } } } }, "securitySchemes": { "bearerAuth": { "type": "http", "description": "Create your token with your certificate.", "scheme": "bearer", "bearerFormat": "JWT" } } } }
Code formatting is weird though. I dont know how to improve it. Ctrl+e gives backticks and I paste the content there. You see the result ^^
If this spec file helps Id be thankful!
Spring Boot has never migrated to jakarta 3.x:
jakarta.annotation:jakarta.annotation-api:2.1.1
+--- org.springframework.boot:spring-boot-starter:3.3.3
| +--- org.springframework.boot:spring-boot-starter-web:3.3.3
| | \--- runtimeClasspath
| +--- org.springframework.boot:spring-boot-starter-json:3.3.3
| | \--- org.springframework.boot:spring-boot-starter-web:3.3.3 (*)
| \--- org.springframework.boot:spring-boot-starter-aop:3.3.2 (requested org.springframework.boot:spring-boot-starter:3.3.2)
| \--- com.apple.jvm.commons.spring:metrics-annotations-spring-boot-starter:3.3.0
| \--- runtimeClasspath
\--- org.springframework.boot:spring-boot-starter-tomcat:3.3.3
\--- org.springframework.boot:spring-boot-starter-web:3.3.3 (*)
They are still using annotation-api of version 2.1.1 which doesn't have validation annotations:
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
But has jakarta.annotation.Generated
annotation.
The jakarta.validation
annotations are in a completely different jar file aren't they (not a later version of that one)? I don't see how that's relevant anyway since the (non) issue is about code being generated with javax.*
annotations.
I don't see how that's relevant anyway since the (non) issue is about code being generated with javax.* annotations.
In your docs for plugins you mention that generated code depends on swagger-parser
dependency: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/plugins.md. OpenAPI spring
client generator generates incompatible code with any spring boot version if I include swagger-parser
, because it produces (with useJakartaEe=true
):
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
...
This will not compile with the latest version of swagger-parser-v3
because it depends on swagger-core
which depends on jakarta.validation-api
of version 2.0.2. This version uses javax.validation
package.
When the property useJakartaEe
is set to false
, generator produces:
...
import javax.annotation.Generated;
This import is incompatible with spring-boot-starter
which uses jakarta.annotation-api
of version 2.1.1 but compatible with swagger-parser
's jakarta.validation-api
.
Sounds like a bug in swagger-parser
then (maybe connected to this: https://github.com/swagger-api/swagger-parser/issues/1981)? The expected behaviour of useJakartaEe=false
is to generate code with javax.*
annotations, so that seems to be working.
Bug Report Checklist
Description
Modern Spring Boot 3 switched from
javax.*
annotations tojakarta.*
. It leads to a problem — code generated with the OpenAPI Generator does not compile anymore.Examples:
openapi-generator version
The last released version is used:
Generation Details
Maven config looks like this, tried both
spring
andjava
asgeneratorName
.Steps to reproduce
Related issues/PRs
Yes, there are related issues, especially about
javax.annotation.Generated
. For example:They are not fixed, specifying
<hideGenerationTimestamp>true</hideGenerationTimestamp>
just does not fill the timestamp, but the import is stillimport javax.annotation.Generated;
.Suggest a fix
We need a new generator that works for the new Spring version, which is planned to be released around 24.Nov.2022. It should use only the
jakarta.*
annotations instead ofjavax.*
annotations.