openapi-processor-maven

License Apache%202.0 blue openapi processor maven plugin?label=Maven%20Central

a maven plugin based on the openapi-processor-api to handle any openapi-processor without an explicit dependency on the processor.

unfortunately it is necessary to configure a few additional jvm parameter to run the processor with JDK 16+

plugin configuration

The first step of the configuration is to add the plugin, and the processor(s) to an existing project pom.xml into the <plugins/> block.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ... >
    <build>
        <plugins>
            <plugin>
                <groupId>io.openapiprocessor</groupId>
                <artifactId>openapi-processor-maven-plugin</artifactId>
                <!-- update to the latest version, see maven central badge at top -->
                <version>2024.1</version>

                <!-- ... next step ... -->
            </plugin>
        </plugins>
    </build>
</project>

The processors are dependencies of the plugin, and they are expected in the <plugin/> block added in the first step.

<plugin>
    <dependencies>
        <dependency>
            <groupId>io.openapiprocessor</groupId>
            <artifactId>openapi-processor-spring</artifactId>
            <version>2023.6.1</version>
        </dependency>
        <dependency>
            <groupId>io.openapiprocessor</groupId>
            <artifactId>openapi-processor-json</artifactId>
            <version>2023.6.1</version>
        </dependency>
    </dependencies>

    <!-- ... next step ... -->
</plugin>

Then it should know where the processors will find the input OpenAPI yaml files using the <apiPath/> element:

<plugin>
    <configuration>
        <id>processor-api</id>
        <apiPath>${project.basedir}/src/api/openapi.yaml</apiPath>
    </configuration>

    <!-- ... next step ... -->
</plugin>
  • <id/>, maven wants this. It is not used by the processor.

  • <apiPath/>, defines the path to the openapi yaml file. This is usually the same for all processors and adding it directly into the plugin <configuration/> block sets it for all processors.

Next step is to configure the goals for processing. The plugin has only a single goal process that can run any processor. It is configured by an <execution/> element to run a specific processor.

If maven should run multiple processors, multiple <execution/> s are needed.

Here is an example to run openapi-processor-spring that explains the configuration details:

<plugin>
    <executions>
        <execution>
            <id>spring-interfaces</id> (1)
            <phase>generate-sources</phase> (2)

            <configuration>
                <id>spring</id> (3)

                <!-- true is default -->
                <addSourceRoot>true</addSourceRoot> (9)

                <!--
                <apiPath>${project.basedir}/src/api/openapi.yaml</apiPath>
                --> (4)

                <options> (5)
                    <values>
                        <targetDir>${project.basedir}/target/generated-sources/openapi</targetDir> (6)
                        <mapping>${project.basedir}/src/api/mapping.yaml</mapping> (7)
                        <parser>INTERNAL</parser>
                        <showWarnings>true</showWarnings>
                    </values>

                    <nested>
                        <name>foo</name>
                        <values>
                            <bar>foo-bar</foobar>
                        </values>
                    </nested>

                </options>
            </configuration>

            <goals>
                <goal>process</goal> (8)
            </goals>
        </execution>
    </executions>
</plugin>
1 <id/>: execution id of the goal (choose your id). It is necessary to configure multiple executions.
2 <phase/> phase (mandatory): openapi-processor-spring generates java code, so the <phase/> should be generate-source. This tells maven to run the goal before compiling anything.
3 <id/> processor id (mandatory): this configures the openapi-processor the goal should run. The processor id must match exactly with the name of the processor. The convention is, that the last part of the processor artifact name is the processor id.

If the artifact of a processor is called openapi-processor-x, the last part x is the id of the processor. For example for openapi-processor-spring the id is spring, for openapi-processor-json the id is json.

4 <apiPath/> (optional): the path to the open api yaml file. If set inside an <execution> <configuration/> it overrides the parent apiPath set in the <plugin> <configuration/>.
5 <options/> (mandatory): processor specific options, the configuration of a single processor can have any number of additional parameters defined by the processor (all options will be passed as a map to the processor with the option name as the key). The nested <values/> element defines that map.

To allow any level of nesting it is possible to create <nested/> option maps, i.e. <nested/> can contain another <nested/> element and so on. In the configuration above the plugin would pass the following map to the processor:

json notation
{
  "targetDir": "<basedir path>/target/generated-sources/openapi",
  "mapping": "<basedir path>/src/api/mapping.yaml",
  "parser": "INTERNAL",
  "showWarnings":true,
  "foo": {
    "bar": "foo-bar"
  }
}
6 <targetDir/> target directory (mandatory): the directory the processor should use for its output. By convention a processor should use this key to as the output directory.
7 the rest of the options are processor specific. See openapi-processor-spring.
8 <goal/> goal (mandatory): this is the goal maven should run. Since the plugin does only have a single goal the value is always process.
9 <addSourceRoot/> *addSourceRoot (optional): this defaults to true and automatically adds the targetDir as compile source root folder. It can be disabled by setting it to false.

multiple processors

To run a second processor add another <execution> element. Here is an example that configures openapi-processor-spring and openapi-processor-json:

<plugin>
    <executions>
        <execution>
            <id>spring-interfaces</id>
            <phase>generate-sources</phase>

            <configuration>
                <id>spring</id>
                <!-- ... -->
            </configuration>
        </execution>

        <execution>
            <id>json-resource</id>
            <phase>generate-resources</phase> (1)

            <configuration>
                <id>json</id>
                <!-- ... -->
            </configuration>
        </execution>
    </executions>
</plugin>
1 uses generate-resources phase for the json output, to consider it as a resource.

executing the goal

The <execution> s created in the previous chapter will automatically run the processor in the given <phase> s with commands like ./mvnw compile.

Running the goal directly with ./mvnw openapi-processor:process to check the source code generation will not work because there is no configuration without <phase>.

selecting an execution

This can be solved in two ways:

First, it is possible to the run the goal with an explicit <execution> like this:

./mvnw openapi-processor:process@spring-interfaces

where spring-interfaces is the <id> of the execution.

adding a default execution

The other solution is to change the execution that should run by default to a default <execution>. When running ./mvnw openapi-processor:process from the shell, maven will look for an <execution> with the id <id>default-cli</id> and if available run it.

<plugin>
    <executions>
        <execution>
            <id>default-cli</id> (1)
            <phase>generate-sources</phase>

            <configuration>
                <id>spring</id>
                <!-- ... -->
            </configuration>
        </execution>
    </executions>
</plugin>
1 using maven’s default execution id instead of a user selected id.

With this configuration maven will use it when directly running the process goal from the shell, and it will also run it when the given phase is active.

using the processor output

source files

Starting with the release 2024.1 it is no longer necessary to manually add the generated sources to the build. The plugin will automatically add the targetDir as compile source root.

It can be disabled by setting the plugin configuration <addSourceRoot> to false.

resource files

If the output of the processor (e.g. generated by openapi-processor-json) should be used as resource add a resource directory.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
    <build>
        <resources>
          <resource>
            <directory>${project.build.directory}/generated-resources/json</directory>
          </resource>
        </resources>
    </build>
</project>

Samples

See the maven sample in the samples for a working spring boot example.