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
20.61k stars 6.29k forks source link

[REQ] Support multiple YAML files for openapi-generator-maven-plugin #6379

Open khaiqnguyen93 opened 4 years ago

khaiqnguyen93 commented 4 years ago

I have a project that needs to use multiple YAML files, but the inputSpec doesn't support this. I try a workaround solution by adding multiple executions of the maven plugin into the pom, this issue can be temporarily solved. But in case I need to generate for many more files (YAML1, YAML2, YAML3,...), and in case my execution contains a big block of code like below:

<execution>
    <goals>
        <goal>generate</goal>
    </goals>
    <configuration>
        <inputSpec>${basedir}/api-spec/${swagger.version}/example1.yaml</inputSpec>
        <output>${basedir}</output>
        <templateDirectory>${basedir}/template/${swagger.version}</templateDirectory>
        <additionalProperties>apiVersion=${swagger.version},useApiAnnotation=false</additionalProperties>
        <generateSupportingFiles>false</generateSupportingFiles>
        <generateModelTests>false</generateModelTests>
        <generateApiTests>false</generateApiTests>
        <generateModelDocumentation>false</generateModelDocumentation>
        <generateApiDocumentation>false</generateApiDocumentation>
        <generatorName>jaxrs-spec</generatorName>
        <configOptions>
            <sourceFolder>src/main/java</sourceFolder>
            <implFolder>src/main/java</implFolder>
            <apiPackage>${swagger.api.package}</apiPackage>
            <interfaceOnly>true</interfaceOnly>
            <java8>true</java8>
            <modelPackage>${swagger.model.package}</modelPackage>
            <useSwaggerAnnotations>false</useSwaggerAnnotations>
            <generatePom>false</generatePom>
            <useBeanValidation>false</useBeanValidation>
        </configOptions>
        <typeMappings>
            <typeMapping>Date=String</typeMapping>
            <typeMapping>LocalDate=String</typeMapping>
        </typeMappings>
    </configuration>
</execution>
<execution>
           ..
</execution>
<execution>
           ...
</execution>

The above workaround is not good, can you support us for a feature that supports multiple YAML files?

sreenath1506 commented 3 years ago

Do we have a fix available for this

reitsma commented 3 years ago

Actually, it is possible. I use a setup where I define the plugin in a pluginManagement section and a project with a plugin definition that generates two sets of models, one even inheriting from the other. The managed plugin looks like this:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>${version-openapi-generator}</version>
    <configuration>
        <generatorName>jaxrs-spec</generatorName>
        <configOptions>
            <sortParamsByRequiredFlag>false</sortParamsByRequiredFlag>
            <java8>true</java8>
            <interfaceOnly>true</interfaceOnly>
            <sourceFolder>src/main/java</sourceFolder>
            <useSwaggerAnnotations>false</useSwaggerAnnotations>
            <useBeanValidation>false</useBeanValidation>
            <dateLibrary>java8</dateLibrary>
            <generatePom>false</generatePom>
            <disableHtmlEscaping>true</disableHtmlEscaping>
            <returnResponse>true</returnResponse>
            <openApiSpecFileLocation>${project.build.directory}/generated-sources/openapi/src/main/resources/META-INF</openApiSpecFileLocation>
            </configOptions>
        <configHelp>false</configHelp>
        <skipValidateSpec>false</skipValidateSpec>
        <generateApiTests>false</generateApiTests>
        <generateModels>true</generateModels>
        <generateModelTests>false</generateModelTests>
        <generateModelDocumentation>false</generateModelDocumentation>
        <generateSupportingFiles>false</generateSupportingFiles>
        <withXml>false</withXml>
    </configuration>
</plugin>

Then the plugin in the project pom looks like:

<plugin>
  <groupId>org.openapitools</groupId>
  <artifactId>openapi-generator-maven-plugin</artifactId>
  <executions>
      <execution>
          <id>base-model</id>
          <goals>
                <goal>generate</goal>
          </goals>
          <configuration>
                        <inputSpec>${project.basedir}/grapevine-api.yaml</inputSpec>
                        <apiPackage>com.vidinexus.grapevine.api</apiPackage>
                        <modelPackage>com.vidinexus.grapevine.api.model</modelPackage>
          </configuration>
      </execution>
      <execution>
          <id>inquiry</id>
          <goals>
                <goal>generate</goal>
          </goals>
          <configuration>
            <inputSpec>${project.basedir}/inquiry-api.yaml</inputSpec>
            <apiPackage>com.vidinexus.grapevine.api</apiPackage>
            <modelPackage>com.vidinexus.grapevine.api.model.inquiry</modelPackage>
            <languageSpecificPrimitives>Item,GeoLocation</languageSpecificPrimitives>
            <importMappings>Item=com.vidinexus.grapevine.api.model.Item, GeoLocation=com.vidinexus.grapevine.api.model.GeoLocation</importMappings>
            <typeMappings>Item=com.vidinexus.grapevine.api.model.Item</typeMappings>
  <generateApis>false</generateApis>
          </configuration>
      </execution>
  </executions>
</plugin>

Result: two sets of files are generated, one after the other. I myself was quite surprised it worked. I got a hint from here: https://maven.apache.org/guides/mini/guide-default-execution-ids.html.

ole-v-v commented 1 year ago

Will you excuse a late question? Do we know that the managed plugin is necessary? With versions 6.3.0 and 6.4.0I tried a naïve way with just two executions in the same plugin in my pom.xml, but it seems the plugin is overwriting generated Java files when generating for the second input file in spite of me specifying different package names. This leads to requests being routed to the wrong API and hence failing. Should I expect a managed plugin to fix this? Generating from Swagger2.0 JSON files using the java generator.

mlebihan commented 10 months ago

@reitsma

I have to generate an API from those yaml I've received, all going into the same model, api generation folders:

catalogresponses.yaml
config.yaml
coverages.yaml
featuretypes.yaml
manifests.yaml

owsservices.yaml
settings.yaml
workspaces.yaml
catalog.yaml
coveragestores.yaml

datastores.yaml
layers.yaml
namespaces.yaml
styles.yaml

1) I don't understand really your inheritance system: who shall inherit from one another in my case?

2) Whatever, this would lead to add in my pom at least 70 lines (100 lines?) to perform my generation, as these 14 files would require 13 copy paste of the same block, with only one line changing inside each block.

Don't you think this would be difficult and clumsy, in comparison to setting:

<inputspec>a,b,c,d</inputspec>

or

<inputspec>a b c d</inputspec>

or

<inputspect>*.yaml</inputspec> ?

reitsma commented 10 months ago

@ole-v-v : I don't think the managed plugin is really necessary, it should be a convenience in case the plugin is used multiple POMs. My knowledge of maven is not extensive enough to be 100% sure. It is complicated matter if Maven configuration is your full-time job. And openApiGenerator is also not known for its ease of use.

reitsma commented 10 months ago

@mlebihan : The inheritance between the generated models appeared indeed an issue. In the above example I could not get the inheritance correctly modelled. I ended up by using a single yaml file as within a single file the modelling of the inheritance was feasible.

Answering your question 2: You are quite right, unless you also want different model packages for each section. In my case I had a base API and a few derived APIs. I did want to mix them in a single package and, as a consequence, I needed to specify each package.

But as I said: I abandoned the idea of multiple executions in the end, because I couldn't get the relations between the schemas correctly modelled.

Pierre491 commented 9 months ago

Hi I solved it like this: maven with ant plugin, which performs a for of a list and calls mvn generate-sources with variables, the yaml list takes up one line, and perhaps it is also possible to read it from an external file

It's kind of ugly, but if you keep the models and apiInterfaces in a separate project that you then import into your main project it's not too annoying, if you have 20+ yaml file my solution could be useful

(tested on windows, not tested on linux)

ant-build.xml ``` ${run.executable}> ${mvn.command} ```
Maven to execute only with right profile ``` generateSourceYaml false org.openapitools openapi-generator-maven-plugin ${openapi-generator.version} GenerateSpringAPIs generate generate-sources spring ${project.basedir}/src/main/resources/yaml/${yaml-service}.yaml ${project.build.directory}/generated-sources/ com.mycompany.openapi.model.${yaml-service} com.mycompany.openapi.service spring-boot true true false java8 true false true true false true true true ``` to execute with any profile (or starting profile) ``` org.apache.maven.plugins maven-antrun-plugin generate-sources-all-yaml run generate-sources avoid recursive loop run ant-build.xml org.apache.ant ant 1.10.14 org.apache.ant ant-jsch 1.10.14 ant-contrib ant-contrib 1.0b3 ```

If there was a smarter solution I would love it

SebastianSuchowiak commented 7 months ago

Hi, I was able to generate sources for two different specs. I added a second execution goal and specified different output directories for the specs using the option from the config:

<executions>
  <execution>
    <id>api-1</id>
    <inputSpec>${project.basedir}/api-1.yaml</inputSpec>
    ...
    <output>${project.build.directory}/generated-sources/openapi-1</output>
  </execution>
  <execution>
    <id>api-2</id>
    <inputSpec>${project.basedir}/api-2.yaml</inputSpec>
    ...
    <output>${project.build.directory}/generated-sources/openapi-2</output>
  </execution>
<executions>
rupert-jung-mw commented 4 months ago

For me, it only processes the first <execution>, the first one is ignored. I use different values. Version is 7.2.0 Update: My fault was to specify on both but as I had the same root folder, this deleted the first generated client.

valb3r commented 3 months ago

I think it is already supported with inputSpecRootDirectory (works properly with 7.4.0 version)

So the config can look like that:

         <plugin>
            <groupId>org.openapitools</groupId>
            <artifactId>openapi-generator-maven-plugin</artifactId>
            <version>${openapi-generator-maven-plugin.version}</version>
            <executions>
                <execution>
                    <id>Generate API from multiple YAML files</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                    <configuration>
                        <inputSpecRootDirectory>${project.basedir}/src/main/resources/folder-with-api-yamls</inputSpecRootDirectory>
                        <generatorName>spring</generatorName>
                        <generateApiTests>false</generateApiTests>
                        <generateModelTests>false</generateModelTests>
                        <configOptions>
                            <sourceFolder>src/main/java</sourceFolder>
                            <basePackage>com.mycompany.generated</basePackage>
                            <configPackage>com.mycompany.generated</configPackage>
                            <modelPackage>com.mycompany.generated</modelPackage>
                            <apiPackage>com.mycompany.generated</apiPackage>
                            <useSpringBoot3>true</useSpringBoot3>
                            <interfaceOnly>true</interfaceOnly>
                            <skipOverwrite>true</skipOverwrite>
                            <dateLibrary>java8</dateLibrary>
                            <java8>false</java8>
                            <useTags>true</useTags>
                            <defaultInterfaces>false</defaultInterfaces>
                            <implicitHeaders>false</implicitHeaders>
                        </configOptions>
                    </configuration>
                </execution>
            </executions>
        </plugin>
minesunny commented 2 months ago

inputSpecRootDirectory

Do you know how to use inputSpecRootDirectory with openapi-generator-cli

valb3r commented 2 months ago

@minesunny openapi-generator generate -g spring -o out --input-spec-root-directory <MY-DIRECTORY-PATH> worked well for me (openapi-generator version 7.4.0)

npm based generator works with that as well:

"openapi-gen-merged": "openapi-generator-cli generate -g typescript-angular -o src/app/api2 --input-spec-root-directory <MY-DIRECTORY-PATH>",
minesunny commented 2 months ago

@minesunny openapi-generator generate -g spring -o out --input-spec-root-directory <MY-DIRECTORY-PATH> worked well for me (openapi-generator version 7.4.0)

npm based generator works with that as well:

"openapi-gen-merged": "openapi-generator-cli generate -g typescript-angular -o src/app/api2 --input-spec-root-directory <MY-DIRECTORY-PATH>",

thank you,it does work

davidkubecka-ext43694 commented 1 week ago

I think it is already supported with inputSpecRootDirectory (works properly with 7.4.0 version)

This indeed works but all the generated classes are heaped onto a single package. Is there any way to have separate packages for separate source files?