openapi-generator icon indicating copy to clipboard operation
openapi-generator copied to clipboard

[BUG][JAVA] Generate from spec within JAR-dependency - File found then File _not found_

Open thokaab opened this issue 6 years ago • 6 comments

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

thokaab avatar Apr 25 '19 08:04 thokaab

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

geojins avatar Mar 20 '21 02:03 geojins

Is this issue fixed? Can I generate directly from the file in a jar file?

xuelishen avatar Nov 07 '23 14:11 xuelishen

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 avatar Nov 22 '23 09:11 Saljack

@Saljack Could you please provide an example of specifying inputSpec from maven dependency?

ILyaCyclone avatar Jan 04 '24 12:01 ILyaCyclone

@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>

Saljack avatar Jan 04 '24 12:01 Saljack

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.

coffee4dev avatar Apr 26 '24 10:04 coffee4dev