Search code examples
mavenswaggerswagger-uiopenapiopenapi-generator

Use artifact version number in OpenAPI spec definition


I have a maven project with my API definition using the OpenaAPI v3 specification.

I generate the code using the openapi-generator-maven-plugin and all works fine. I'm also able to access the swagger-ui and view and test my API.

The problem is that I don't want to maintain the version number twice. So I'd like to refer the version number from my maven pom in my api spec instead of duplicating it with the risk of it getting outdated.

I've tried maven resource filtering, which seems to work. Since the yaml file in the target folder gets it nicely replaced when I put ${project.version} in the version field in the spec, but when I open the swagger-ui it prints "${project.version}" literally instead of the actual version.

This is the plugin config from my pom:

<build>
      <resources>
        <resource>
          <directory>src/main/resources</directory>
          <filtering>true</filtering>
        </resource>
      </resources>
      <plugins>
        <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.build.resources[0].directory}/spec.yml</inputSpec>
                <ignoreFileOverride>${project.build.resources[0].directory}/.openapi-codegen-ignore</ignoreFileOverride>
                <language>spring</language>
                <library>spring-boot</library>
                <configOptions>
                  <!-- Use the newer java.time package instead of outdated java.util-->
                  <dateLibrary>java8</dateLibrary>
                </configOptions>
                <apiPackage>${default.package}.api</apiPackage>
                <modelPackage>${default.package}.model</modelPackage>
                <invokerPackage>${default.package}.invoker</invokerPackage>
                <generateApiTests>false</generateApiTests>
              </configuration>
            </execution>
          </executions>
       </plugin>
       ...
    </plugins>
</build>

This is my spec.yml:

openapi: 3.0.0
info:
  version: ${project.version}
...

Solution

  • Thanks to the comment from @bcoughlan I was able to get the maven-resources-plugin working as desired.

    Now it takes filters the *yml file from the src/main/resources folder and replaces the ${project.version} placeholder during the generates-sources phase. Because the openapi-generator-maven-plugin executes in the same phase and is defined later, it will be executed after the resource filtering and will operate on the api spec in the target folder as a result of ${project.build.outputDirectory}/spec.yml

          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
              <resources>
                <resource>
                  <directory>src/main/resources</directory>
                  <filtering>true</filtering>
                </resource>
              </resources>
            </configuration>
            <executions>
              <execution>
                <phase>generate-sources</phase>
                <goals>
                  <goal>resources</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <!-- Codegen plugin for api. Depends on maven-resources-plugin to have executed in the generate-sources phase! -->
          <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.build.outputDirectory}/spec.yml</inputSpec>
                    <ignoreFileOverride>${project.basedir}/.openapi-codegen-ignore</ignoreFileOverride>
                  <language>spring</language>
                  <library>spring-boot</library>
                  <configOptions>
                    <!-- Use the newer java.time package instead of outdated java.util-->
                    <dateLibrary>java8</dateLibrary>
                  </configOptions>
                  <apiPackage>${default.package}.api</apiPackage>
                  <modelPackage>${default.package}.model</modelPackage>
                  <invokerPackage>${default.package}.invoker</invokerPackage>
                  <generateApiTests>false</generateApiTests>
                </configuration>
              </execution>
            </executions>
          </plugin>
    

    Note: the openapi-generator-maven-plugin is almost the same as the swagger-codegen-maven-plugin. More about the difference can be found here: https://openapi-generator.tech/docs/fork-qna

    Note 2: When using spring-boot parent pom, you inherit resource.delimeter=@ property and ${project.version} notation no longer works. So replacing the placeholder with @project.version@ should fix that.