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.47k stars 6.5k forks source link

[BUG][MAVEN] Classpath $ref to external file are not resolved correctly #19073

Closed Saljack closed 2 months ago

Saljack commented 3 months ago

Bug Report Checklist

Description

18576 PR for openapi-generator-maven-plugin inputSpec -- Allow jar: URLs introduced support for rewriting inputSpec in openapi-generator-maven-plugin but it broke references to external files.

We have a similar maven plugin configuration:

 <plugin>
        <groupId>org.openapitools</groupId>
        <artifactId>openapi-generator-maven-plugin</artifactId>

        <dependencies>
          <dependency>
            <groupId>com.example</groupId>
            <artifactId>your-artificat-with-openapi</artifactId>
            <version>your-version</version>
          </dependency>

        </dependencies>

        <executions>
          <execution>
            <id>openapi</id>
            <goals>
              <goal>generate</goal>
            </goals>
            <configuration>
              <!-- The path of OpenAPI in your file. The origin path in project is /src/main/resources/... -->
              <inputSpec>openapi/openapi.yaml</inputSpec>
            </configuration>
          </execution>

        <executions>
 </plugin>

Then we have multiple OpenAPI files in artifacts (e.g. openapi.yaml, model-openapi.yaml) and use references between them.

schema:
  $ref: "model-openapi.yaml#/components/schemas/User"

During the build with openapi-generator-maven-plugin it fails and throws this exception:

Exception while resolving:
java.lang.RuntimeException: Unable to load RELATIVE ref: ./model-openapi.yaml
    at io.swagger.v3.parser.util.RefUtils.readExternalClasspathRef (RefUtils.java:150)
    at io.swagger.v3.parser.ResolverCache.loadRef (ResolverCache.java:162)
    at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalSchema (ExternalRefProcessor.java:89)
    at io.swagger.v3.parser.processors.SchemaProcessor.processReferenceSchema (SchemaProcessor.java:238)
    at io.swagger.v3.parser.processors.SchemaProcessor.processSchema (SchemaProcessor.java:59)
    at io.swagger.v3.parser.processors.ResponseProcessor.processResponse (ResponseProcessor.java:56)
    at io.swagger.v3.parser.processors.OperationProcessor.processOperation (OperationProcessor.java:86)
    at io.swagger.v3.parser.processors.PathsProcessor.processPaths (PathsProcessor.java:88)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:72)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:59)
    at io.swagger.v3.parser.OpenAPIV3Parser.resolve (OpenAPIV3Parser.java:240)
    at io.swagger.v3.parser.OpenAPIV3Parser.readContents (OpenAPIV3Parser.java:183)
    at io.swagger.v3.parser.OpenAPIV3Parser.readLocation (OpenAPIV3Parser.java:97)
    at io.swagger.parser.OpenAPIParser.readLocation (OpenAPIParser.java:16)
    at org.openapitools.codegen.plugin.CodeGenMojo.calculateInputSpecHash (CodeGenMojo.java:1012)
    at org.openapitools.codegen.plugin.CodeGenMojo.execute (CodeGenMojo.java:985)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:206)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke (Method.java:580)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:283)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348)
Caused by: java.lang.RuntimeException: Could not find model-openapi.yaml on the classpath
    at io.swagger.v3.parser.util.ClasspathHelper.loadFileFromClasspath (ClasspathHelper.java:33)
    at io.swagger.v3.parser.util.RefUtils.readExternalClasspathRef (RefUtils.java:147)
    at io.swagger.v3.parser.ResolverCache.loadRef (ResolverCache.java:162)
    at io.swagger.v3.parser.processors.ExternalRefProcessor.processRefToExternalSchema (ExternalRefProcessor.java:89)
    at io.swagger.v3.parser.processors.SchemaProcessor.processReferenceSchema (SchemaProcessor.java:238)
    at io.swagger.v3.parser.processors.SchemaProcessor.processSchema (SchemaProcessor.java:59)
    at io.swagger.v3.parser.processors.ResponseProcessor.processResponse (ResponseProcessor.java:56)
    at io.swagger.v3.parser.processors.OperationProcessor.processOperation (OperationProcessor.java:86)
    at io.swagger.v3.parser.processors.PathsProcessor.processPaths (PathsProcessor.java:88)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:72)
    at io.swagger.v3.parser.OpenAPIResolver.resolve (OpenAPIResolver.java:59)
    at io.swagger.v3.parser.OpenAPIV3Parser.resolve (OpenAPIV3Parser.java:240)
    at io.swagger.v3.parser.OpenAPIV3Parser.readContents (OpenAPIV3Parser.java:183)
    at io.swagger.v3.parser.OpenAPIV3Parser.readLocation (OpenAPIV3Parser.java:97)
    at io.swagger.parser.OpenAPIParser.readLocation (OpenAPIParser.java:16)
    at org.openapitools.codegen.plugin.CodeGenMojo.calculateInputSpecHash (CodeGenMojo.java:1012)
    at org.openapitools.codegen.plugin.CodeGenMojo.execute (CodeGenMojo.java:985)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:126)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:328)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:316)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:212)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:174)
    at org.apache.maven.lifecycle.internal.MojoExecutor.access$000 (MojoExecutor.java:75)
    at org.apache.maven.lifecycle.internal.MojoExecutor$1.run (MojoExecutor.java:162)
    at org.apache.maven.plugin.DefaultMojosExecutionStrategy.execute (DefaultMojosExecutionStrategy.java:39)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:159)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:105)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:73)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:53)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:118)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:261)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:173)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:101)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:906)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:283)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:206)
    at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:103)
    at java.lang.reflect.Method.invoke (Method.java:580)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:283)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:226)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:407)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:348)

As you can see the problem is with resolved path. The correct path should be ./openapi/model-openapi.yaml and not just ./model-openapi.yaml.

Therefore you cannot use references to external files if these files are not in the root path of a jar.

openapi-generator version

openapi-generator 7.7.0 it works fine with 7.6.0

OpenAPI declaration file content or url
Steps to reproduce

Try to build with openapi-generator-maven-plugin

Related issues/PRs

This PR https://github.com/OpenAPITools/openapi-generator/pull/18576 broke it.

This is connected to java.net.URI.resolve() that is used internally in swagger-parser https://bugs.openjdk.org/browse/JDK-8020755

Suggest a fix

Process only inputSpec if it starts with jar: or introduce a new configuration for disabling this processing.

Saljack commented 3 months ago

There is a workaround how to use the latest openapi-generator. You can use openapi-generator-maven-plugin 7.6.0 and upgrade dependency for openapi-generator:

 <plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <!-- Old version maven plugin -->
    <version>7.6.0</version>

    <dependencies>
        <!-- Newer openapi-generator -->
        <dependency>
          <groupId>org.openapitools</groupId>
          <artifactId>openapi-generator</artifactId>
          <version>7.7.0</version>
      </dependency>
    </dependencies>
</plugin>