openapi-generator
openapi-generator copied to clipboard
[BUG][JAVA] Generate from spec within JAR-dependency - File found then File _not found_
Description
When migrated from swagger-codegen-maven-plugin to openapi-generator-maven-plugin we are no longer able to generate Java code from an OpenAPI specification located in a Maven JAR-dependency. The specification file is first found, then at a later stage it's no longer found.
Please note that the codegen is successful with the exact same configuration if I put the api.yml in the local project and point <inputSpec> to the local file, e.g.
<inputSpec>${project.basedir}/src/main/resources/api.yml</inputSpec>
Hence:
- The OpenAPI 3.0.2 YML file is correct.
- The generator (maven plugin) configuration is OK.
Detailed Description
When building verbose I can see that the generator first prints my YML-file (api.yml) as JSON (OK):
{
"openapi" : "3.0.2",
"info" : {
"title" : "Example API",
"description" : "Example API",
"contact" : {
"name" : "John Doe",
"email" : "[email protected]"
},
"version" : "1.0"
},
...
}
Then writing model files (schemas), e.g.
[INFO] writing file C:\code\example-impl\functions\target\generated-sources\swagger\com\example\api\model\SomeModel.java
Then Model Info is printed (OK):
############ Model info ############
{...}
Then Supporting file info is printed (OK):
############ Supporting file info ############`
{...}
Then writing supporting files:
[INFO] writing file C:\code\example-impl\functions\target\generated-sources\swagger/com/example/api\ApiClient.java
[INFO] writing file C:\code\example-impl\functions\target\generated-sources\swagger/com/example/api\ApiException.java
...
So far everything looks ok and the YML-file has obviously been found by the plugin. But directly after the supporting files have been generated I get a FileNotFoundException:
[ERROR] C:\code\example-impl\api.yml [0:0]: unexpected error in Open-API generation
java.io.FileNotFoundException: api.yml (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at com.google.common.io.Files$FileByteSource.openStream(Files.java:129)
at com.google.common.io.Files$FileByteSource.openStream(Files.java:119)
at com.google.common.io.ByteSource.copyTo(ByteSource.java:245)
at com.google.common.io.ByteSource.hash(ByteSource.java:329)
at org.openapitools.codegen.plugin.CodeGenMojo.execute(CodeGenMojo.java:637)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.MojoExecutor.executeForkedExecutions(MojoExecutor.java:352)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:197)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
[ERROR]
java.io.FileNotFoundException: api.yml (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at com.google.common.io.Files$FileByteSource.openStream(Files.java:129)
at com.google.common.io.Files$FileByteSource.openStream(Files.java:119)
at com.google.common.io.ByteSource.copyTo(ByteSource.java:245)
at com.google.common.io.ByteSource.hash(ByteSource.java:329)
at org.openapitools.codegen.plugin.CodeGenMojo.execute(CodeGenMojo.java:637)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:134)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:207)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.MojoExecutor.executeForkedExecutions(MojoExecutor.java:352)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:197)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:116)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:80)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:307)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:193)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:106)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:863)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:199)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
at org.codehaus.classworlds.Launcher.main(Launcher.java:47)
The maven plugin is located at C:\code\example-impl\functions\pom.xml
I run mvn clean install from C:\code\example-impl\ which has a parent pom.xml to the functions\pom.xml (functions is a module).
One thing I noticed is that the error message above looks for the file at C:\code\example-impl\api.yml, i.e. the folder of the POM I'm running. If I run mvn clean install on the module POM C:\code\example-impl\functions\pom.xml then it's the same error, but it now fails with:
[ERROR] C:\code\example-impl\functions\api.yml [0:0]: unexpected error in Open-API generation
java.io.FileNotFoundException: api.yml (The system cannot find the file specified)
at java.io.FileInputStream.open0(Native Method)
The file is inside the JAR-dependency, not on any of the project paths.
My plugin definition:
In C:\code\example-impl\functions\pom.xml:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>3.3.4</version>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>example-api</artifactId>
<version>${example-api.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<validateSpec>true</validateSpec>
<inputSpec>api.yml</inputSpec>
<generatorName>java</generatorName>
<modelNamePrefix>ExApi</modelNamePrefix>
<verbose>true</verbose>
<configOptions>
<sourceFolder>swagger</sourceFolder>
<dateLibrary>java8</dateLibrary>
</configOptions>
<typeMappings>
<typeMapping>OffsetDateTime=Instant</typeMapping>
</typeMappings>
<importMappings>
<importMapping>java.time.OffsetDateTime=java.time.Instant</importMapping>
</importMappings>
<library>jersey2</library>
<output>${project.build.directory}/generated-sources</output>
<modelPackage>${default.package}.api.model</modelPackage>
<generateModels>true</generateModels>
<generateApis>false</generateApis>
<generateApiTests>false</generateApiTests>
<generateApiDocumentation>false</generateApiDocumentation>
<generateModelTests>false</generateModelTests>
<generateModelDocumentation>false</generateModelDocumentation>
</configuration>
</execution>
</executions>
</plugin>
openapi-generator version
3.3.4
OpenAPI declaration file content or url
N/A
Steps to reproduce
See description.
Related issues/PRs
None found.
Suggest a fix
Here is a workaround until this is fixed: Using maven-dependency-plugin, unpack the jar , copy open api yaml to a local directory, point generator to the local directory. The generator will be happy now.
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<id>unpack</id>
<phase>generate-sources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>your-group-id</groupId>
<artifactId>your-artifact-id</artifactId>
<version>your-version</version>
<type>jar</type>
<overWrite>false</overWrite>
<includes>**/*.yaml</includes>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes/</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>5.0.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>
${project.build.directory}/classes/openapi.yaml
</inputSpec>
<generatorName>spring</generatorName>
<apiPackage>com.example.gen</apiPackage>
<modelPackage>com.example.gen.model</modelPackage>
<configOptions>
<interfaceOnly>true</interfaceOnly>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
...
Is this issue fixed? Can I generate directly from the file in a jar file?
It works for me. We have artifacts only as dependencies of the openapi-generator-maven-plugin . So it is fixed it worked also in version 3 of this plugin. There is no reason to use maven-dependency-plugin.
@Saljack Could you please provide an example of specifying inputSpec from maven dependency?
@ILyaCyclone Here you are:
<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>
<!-- You can add multiple dependencies -->
</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>
<!-- Another configuration -->
</configuration>
</execution>
<!-- You can add multiple executions-->
<executions>
</plugin>
Is it possible to do it with gradle? Doesn't work for me currently, the plugin complains that it cannot find the inputSpec file, searching for it in project root.
Edit: succeeded with the suggested workaround (unpacked the JAR with the OpenAPI specification), just wondered if, being still relatively new to gradle, I'm missing something and the workaround can be avoided.