Contribute to help us improve!

Are there edge cases or problems that we didn't consider? Is there a technical pitfall that we should add? Did we miss a comma in a sentence?

If you have any input for us, we would love to hear from you and appreciate every contribution. Our goal is to learn from projects for projects such that nobody has to reinvent the wheel.

Let's collect our experiences together to make room to explore the novel!

To contribute click on Contribute to this page on the toolbar.

Open Api Generator

OpenApi is a specification to describe restful service endpoints in a human and computer readable format.

With the help of a generator, server and client code can be created from the Api definition. This will help to build projects more Api driven, faster, consistent and in a design first approach.

  • For the client-side, it’s easier to send requests to the Api by using a generated Api client

  • For the server-side, stubs are generated as interfaces to implement

Generator to use

There are different types of generators, it is suggested to use the OpenApi Generator.

It’s sugessted to use the maven/gradle plugin version for the client and server.

For the client, there is also a cli tool. The advantage of this tool is the creation of the client as a library in a local or remote maven repository. This will improve build times because the client only has to be generated once. After running the generator, view the created README for more details about installation and usage.

Setup

Create an openapi.yaml file from the Api and move it into the main/resources folder.

Configure the openapi generator maven plugin inside the pom.xml.

Use generated as package name

  • The code generated for the server should be located under <root-package>.generated.api

  • The code generated for the client should be located under <root-package>.generated.client

Before generating, choose the underlying httpClient library

When generating a client, the client encapsulates the HttpClient library, making it easy to exchange. The library can be set by changing the library option inside the plugin configuration.

Some minor changes need to be done when changing the library. For native Java library, the method for changing the server path is updateBaseUri. For other libraries, it is setBasePath. When switching, this needs to be changed. See the example for the details.

Dependent on the library, error handling can be different.

For client-side

A detailed guide on how to use the generated client code can be found here

Configure The APIClient and Specific clients in a Configuration Bean

The ApiClient should be configured in a Configuration Bean named {[ApiName]}Config

It is possible that the server url is already set inside the openapi.yaml file. You can set/overwrite the server path of the Api inside the application.properties using the configuration bean.

For different http libraries, the configuration bean has to be changed.

  • Spring

  • Quarkus

For every API resource model, create a bean to access a [<ResourceName>]Api Object.

For every API resource model, create a producer to access a [<ResourceName>]Api Object.

Code Snippets to integrate the generation in the build tools

  • Gradle

  • Maven

plugins {
   ...
    id "org.openapi.generator" version "6.2.0"
    ...
}

sourceSets.main.java.srcDirs += 'build/generated-sources/server/src/main/java' (1)

dependencies { (2)
  ...
  implementation 'io.swagger.parser.v3:swagger-parser:2.1.7'
  implementation 'org.openapitools:jackson-databind-nullable:0.2.4'
  ...
}


openApiGenerate {
    artifactId = "MyThaiApi-java-client"
    groupId = "com.devonfw.generated.client"
    apiPackage = "com.devonfw.generated.client.service"
    modelPackage = "com.devonfw.generated.client.model"
    invokerPackage = "com.devonfw.generated.client.handler"
    inputSpec = "${rootDir}/src/main/resources/MyThaiApi.yml" (3)
    output = "${buildDir}/generated-sources/client"
    generatorName = "java" (4)
    library = "native" (5)
    generateApiTests = "false"
    generateModelTests = "false"
    modelNameSuffix = "To"
}

tasks.compileJava.dependsOn(tasks.openApiGenerate) (5)
1 Add the generated sources to the sourceSets, otherwise the IDE will not know the generated files and mark them. Also autocompletion would not work.
2 Add the dependencies that are necessary for the generated sources
3 Path to the openapi spec
4 The generator java is a client generator. See https://openapi-generator.tech/docs/generators#config-generators.
5 The library defines with which http library the calls should be generated
<!--Generation dependencies-->
<dependencies>
 ...
		<dependency>
			<groupId>io.swagger.parser.v3</groupId>
			<artifactId>swagger-parser</artifactId>
			<version>2.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.openapitools</groupId>
			<artifactId>jackson-databind-nullable</artifactId>
			<version>0.2.3</version>
		</dependency>
...
</dependencies>

<build>
  <plugins>
    ...
    <plugin>
				<groupId>org.openapitools</groupId>
				<artifactId>openapi-generator-maven-plugin</artifactId>
				<version>6.1.0</version>
				<executions>
					<execution>
						<goals>
							<goal>generate</goal>
						</goals>
						<configuration>
							<artifactId>MyThaiApi-java-client</artifactId>
							<groupId>com.devonfw.generated.client</groupId>
							<apiPackage>com.devonfw.generated.client.service</apiPackage>
							<modelPackage>com.devonfw.generated.client.model</modelPackage>
							<invokerPackage>com.devonfw.generated.client.handler</invokerPackage>
							<inputSpec>${project.basedir}/src/main/resources/MyThaiApi.yml</inputSpec>
							<output>${project.build.directory}/auto-generated</output>
							<generatorName>java</generatorName>
							<library>native</library>
							<generateApiTests>false</generateApiTests>
							<generateModelTests>false</generateModelTests>
							<modelNameSuffix>TO</modelNameSuffix>
						</configuration>
					</execution>
				</executions>
			</plugin>
    </plugins>

For server-side

A detailed guide on how to use the generated server code can be found here

The content type for the response is defined inside the openapi file. If there are multiple response types and xml should be used as default, add the following in the plugin configuration.

<singleContentTypes>false</singleContentTypes>
<withXml>true</withXml>

Code Snippets to integrate the generation in the build tools

  • Gradle

  • Maven

plugins {
   ...
    id "org.openapi.generator" version "6.2.0"
    ...
  }

sourceSets.main.java.srcDirs += 'build/generated-sources/server/src/main/java' (1)

dependencies { (2)
  ...
  implementation 'io.swagger.parser.v3:swagger-parser:2.1.7'
  implementation 'org.openapitools:jackson-databind-nullable:0.2.4'
  ...
}


openApiGenerate {
    // other settings omitted
    inputSpec = "${rootDir}/src/main/openapi/BookingOpenApi.yaml" (3)
    outputDir = "${buildDir}/generated-sources/server"
    generatorName = "spring"
    library = "spring-boot" (4)
    modelNameSuffix = "To"
    apiPackage = "com.devonfw.generated.api.service"
    modelPackage = "com.devonfw.generated.api.model"
    invokerPackage = "com.devonfw.generated.api.handler"
    configOptions = [
            sourceFolder      : "src/main/java",
            interfaceOnly     : "true",
            serializableModel : "true",
            singleContentTypes: "true",
    ]
}

tasks.compileJava.dependsOn(tasks.openApiGenerate) (5)
1 Add the generated sources to the sourceSets, otherwise the IDE will not know the generated files and mark them. Also autocompletion would not work.
2 Add the dependencies that are necessary for the generated sources
3 Path to the openapi spec
4 Depending on the library the annotations are different. Here we define spring-boot.
5 Add a dependeny from compile to openApiGenerate so that the sources are generated before the compile task.
<!--Generation dependencies-->
<dependencies>
 ...
		<dependency>
			<groupId>io.swagger.parser.v3</groupId>
			<artifactId>swagger-parser</artifactId>
			<version>2.1.2</version>
		</dependency>
		<dependency>
			<groupId>org.openapitools</groupId>
			<artifactId>jackson-databind-nullable</artifactId>
			<version>0.2.3</version>
		</dependency>
...
</dependencies>

<build>
  <plugins>
    ...
    <plugin>
				<groupId>org.openapitools</groupId>
				<artifactId>openapi-generator-maven-plugin</artifactId>
				<version>6.1.0</version>
				<executions>
					<execution>
						<id>server-generator</id>
						<goals>
							<goal>generate</goal>
						</goals>
						<configuration>
							<inputSpec>${project.basedir}/src/main/resources/MyThaiApi.yml</inputSpec>
							<output>${project.build.directory}/generated-sources/server</output>
							<generatorName>spring</generatorName>
							<library>spring-boot</library>
							<modelNameSuffix>To</modelNameSuffix>
							<apiPackage>com.devonfw.generated.api.service</apiPackage>
							<modelPackage>com.devonfw.generated.api.model</modelPackage>
							<invokerPackage>com.devonfw.generated.api.handler</invokerPackage>
							<configOptions>
								<sourceFolder>src/java/main</sourceFolder>
								<interfaceOnly>true</interfaceOnly>
								<serializableModel>true</serializableModel>
								<singleContentTypes>true</singleContentTypes>
							</configOptions>
						</configuration>
					</execution>
				</executions>
			</plugin>
    </plugins>