OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.58k stars 6.52k forks source link

[BUG] `java` and `spring` client generators: old `javax` classes are used, not compatible with Spring Boot 3 that migrated to `jakarta.*` classes #14010

Closed dmitry-weirdo closed 1 year ago

dmitry-weirdo commented 1 year ago

Bug Report Checklist

Description

Modern Spring Boot 3 switched from javax.* annotations to jakarta.*. It leads to a problem — code generated with the OpenAPI Generator does not compile anymore.

Examples:

import javax.annotation.Generated; // incorrect annotation, it must be jakarta.annotation.Generated

@Generated(value = "org.openapitools.codegen.languages.SpringCodegen")
@Validated
@Tag(name = "my-service", description = "Endpoints for My Service health-check")
public interface MyServiceApi {
import javax.servlet.http.HttpServletResponse; // it must be jakarta.servlet.http.HttpServletResponse
import java.io.IOException; // it must be jakarta.validation.constraints.*

public class ApiUtil {
    public static void setExampleResponse(NativeWebRequest req, String contentType, String example) {
import javax.validation.Valid; // it must be jakarta.validation.Valid
import javax.validation.constraints.*; 

    default ResponseEntity<Void> addEdamamInput(
        @Parameter(name = "EdamamData", description = "", required = true) @Valid @RequestBody List<EdamamData> edamamData
    ) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }
openapi-generator version

The last released version is used:

        <openapi-generator-maven-plugin.version>6.2.1</openapi-generator-maven-plugin.version>
Generation Details

Maven config looks like this, tried both spring and java as generatorName.

                    <execution>
                        <id>ras-client</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/../etc/api/ras.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> <!-- does not change the package of javax.annotation.Generated -->
                            </configOptions>
                        </configuration>
                    </execution>
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 still import 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 of javax.* annotations.

msaiducar commented 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>
ravermeister commented 1 year ago

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 🙂

dmitry-weirdo commented 1 year ago

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);
dsyer commented 1 year ago

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.

dmitry-weirdo commented 1 year ago

@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
dsyer commented 1 year ago

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).

jwilmoth-nc commented 1 year ago

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.

pfrollo commented 1 year ago

@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>
dmitry-weirdo commented 1 year ago

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>
dmitry-weirdo commented 1 year ago

@jwilmoth-nc Your old classes are most probably from the old build. Please try to execute mvn clean before the new regeneration.

jwilmoth-nc commented 1 year ago

@dmitry-weirdo a rebuild of the project with the -U flag to force a new version of the snapshot worked.

dsyer commented 1 year ago

Works for me. Maybe if you could post a complete reproducer, minimal project?

ArthurEirich commented 1 year ago

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?

dsyer commented 1 year ago

Maybe you forgot to add a dependency (e.g. jakarta.annotation:jakarta.annotation-api:2.1.1)?

CosmicDarine commented 1 year ago

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 !

dsyer commented 1 year ago

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".

ArthurEirich commented 1 year ago

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?

dsyer commented 1 year ago

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.

ArthurEirich commented 1 year ago

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\nZBP_400_001: Type mismatch for parameter {parameter}\n\nZBP_400_001: parameter {parameter} not valid\n\nZBP_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\nZBP_409_002: no subject in token\n\nZBP_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\nZBP_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\nZBP_500_011: internal servlet error occurred\n\nZBP_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!

Praytic commented 1 month ago

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.

dsyer commented 1 month ago

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.

Praytic commented 1 month ago

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.

dsyer commented 1 month ago

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.