Speakeasy Logo
Skip to Content

Comparison guide: OpenAPI/Swagger Java client generation

At Speakeasy, the team specializes in producing idiomatic SDKs in various programming languages, including Java. The approach to SDK generation prioritizes a rich developer experience that enables API providers to concentrate on refining APIs and empowers developer-users to efficiently leverage services.

In this article, we’ll compare creating a Java SDK using Speakeasy to creating one using the OpenAPI Generator .

Below is a table that summarizes the key differences between the two SDKs:

Feature
Minimum version
Speakeasy
Java 11+ (modern features)
OpenAPI Generator
Java 8+ (legacy support)
Notes
Dependencies
Speakeasy
✅ Minimal dependencies
OpenAPI Generator
⚠️ Many third-party dependencies
Notes
HTTP client
Speakeasy
Native Java 11
OpenAPI Generator
⚠️ Third-party OkHttp dependency
Notes
JSON processing
Speakeasy
Jackson  (enterprise-ready, faster)
OpenAPI Generator
⚠️ Gson  (simpler, limited config)
Notes
Builder pattern
Speakeasy
✅ Modern builder pattern
OpenAPI Generator
❌ Traditional setters only
Notes
Null safety
Speakeasy
✅ Proactive with
support
OpenAPI Generator
❌ Basic retrospective validation
Notes
Retry support
Speakeasy
✅ Built-in configurable retries
OpenAPI Generator
❌ Not supported
Notes
Documentation
Speakeasy
✅ Comprehensive, with examples
OpenAPI Generator
⚠️ Basic documentation
Notes
Collections
Speakeasy
✅ Modern list implementations
OpenAPI Generator
⚠️ Mix of arrays and lists
Notes
Field access
Speakeasy
✅ Encapsulated (getter methods)
OpenAPI Generator
❌ Direct field access
Notes
OAuth support
Speakeasy
✅ Built-in OAuth 2.0
OpenAPI Generator
⚠️ Requires additional library
Notes
Pagination
Speakeasy
✅ Supported
OpenAPI Generator
❌ Not supported
Notes

Read more about these headline features of Speakeasy-created Java SDKs in the March 2024 release notes, or consult the Speakeasy Java SDK documentation.

For a detailed technical comparison, read on!

Installing the CLIs

For this comparison, we need both the Speakeasy and OpenAPI Generator CLIs installed to generate the Java SDKs from the specification YAML file. We’re using macOS, so we use Homebrew to install the CLIs.

Installing the Speakeasy CLI

Install the Speakeasy CLI by running the following command in the terminal:

You can check the version to ensure installation was successful:

If you encounter any errors, take a look at the Speakeasy SDK creation documentation.

Installing the OpenAPI Generator CLI

Install the OpenAPI Generator CLI by running the following command in the terminal:

You can check the version:

Browse the OpenAPI Generator documentation  if any errors occur.

Downloading the Swagger Petstore specification

We need an OpenAPI specification YAML file to generate SDKs for. We’ll use the Swagger Petstore specification, which you can find at https://petstore3.swagger.io/api/v3/openapi.yaml .

Download the file in and save it as petstore.yaml with the following command in the terminal:

Validating the specification file

Let’s validate the spec using both the Speakeasy CLI and OpenAPI Generator.

Validation using Speakeasy

Run the following command in the terminal where the specification file is located:

The Speakeasy validator returns the following:

The Speakeasy CLI validation result gives us a handy tool for switching between the errors, warnings, and hints tabs with the option to navigate through the results on each tab.

In this instance, Speakeasy generated ten warnings. Let’s correct them before continuing.

Notice that some of the warnings contain a default response. For completeness, we’d like to explicitly return a 200 HTTP response. We’ll make the following modifications in the petstore.yaml file.

When the updatePetWithForm operation executes successfully, we expect an HTTP 200 response with the updated Pet object to be returned.

Insert the following after responses on line 250:

Similarly, following successful createUser and updateUser operations, we’d like to return an HTTP 200 response with a User object.

Add the following text to both operations below responses:

Now we’ll add the same response to four operations. Copy the following text:

Paste this response after responses for the following operations:

  • deletePet
  • deleteOrder
  • logoutUser
  • deleteUser

We are left with three warnings indicating potentially unused or orphaned objects and operations.

For unused objects, locate the following lines of code and delete them:

To remove the unused request bodies, locate the following lines and delete them:

Now if you validate the file with the Speakeasy CLI, you’ll notice there are no warnings:

Validation using OpenAPI Generator

To validate the petstore.yaml specification file with OpenAPI Generator, run the following command in the terminal:

The OpenAPI Generator returns the following response, indicating no issues detected.

Now that we have made the petstore.yaml file more complete by fixing the warnings, let’s use it to create SDKs.

Creating SDKs

We’ll create Java SDKs using Speakeasy and OpenAPI Generator and then compare them.

Creating an SDK with Speakeasy

Create a Java SDK from the petstore.yaml specification file using Speakeasy by running the following command in the terminal:

The generator will return some logging results while the SDK is being created and a success indicator on completion.

Creating an SDK with OpenAPI Generator

Run the following command in the terminal to generate a Java SDK using OpenAPI Generator:

The generator returns various logs and finally a successful generation message.

SDK code compared: Project structure

Let’s compare the two project structures by printing a tree structure of each SDK directory’s src folder.

Run the following command to get the Speakeasy SDK structure:

The results of the project structure are displayed as follows:

Now run the following command for the OpenAPI Generator SDK folder:

The OpenAPI Generator SDK structure looks like this:

The Speakeasy-created SDK contains more generated files than the SDK from OpenAPI Generator, which is partly due to the Speakeasy SDK being less dependent on third-party libraries.

Model and usage

Let’s take a look at how Speakeasy generates model classes for creating and updating a Pet object.

The Speakeasy model follows the builder pattern to construct objects with many optional parameters, making the code more readable and easier to use.

Let’s see how the OpenAPI Generator SDK performs the same operation:

The OpenAPI Generator SDK focuses on manual serialization and deserialization using Gson, providing setter methods for individual properties of the Pet object.

The two SDKs have distinctly different approaches to handling object creation, validation, and JSON serialization, with the Speakeasy-generated SDK emphasizing fluid and declarative object creation using modern patterns and annotations for handling JSON data.

Let’s look more closely at how the Pet model attributes are declared in each SDK.

Notice how the Speakeasy SDK uses Jackson annotations for the JSON serialization and deserialization of objects.

Compare this to the OpenAPI Generator SDK Pet model that uses Gson annotations:

Let’s take a moment and identify what the differences are between the Jackson vs GSON libraries and what features each has.

The Gson JSON library is easy to use and implement and well-suited to smaller projects. It provides an API for JSON support but doesn’t support extensive configuration options.

On the other hand, Jackson is designed to be more configurable and flexible when it comes to JSON serialization and deserialization. Jackson is the standard JSON-support library in many popular Java frameworks (like Spring, Jersey, and RESTEasy), it’s widely used in the Java community, and it’s actively supported and frequently updated. Jackson is also generally faster and offers extensive configuration options.

The use of the Jackson library in the Speakeasy-generated SDK provides us with a firm foundation for building fast and scalable applications.

HTTP communication

Java 11 (the minimum version supported by Speakeasy) significantly improved HTTP communication with the java.net.http package providing a powerful HTTPClient class for enhanced HTTP communication.

Given the OpenAPI Generator SDK is Java 8 compatible, we suspected it might use some third-party libraries. On inspection, our suspicions were confirmed: The SDK uses a third-party library to handle HTTP communication.

Take a look at the following method to add a new Pet object (from the PetApi.java file):

The addPet method in turn calls the addPetWithHttpInfo(pet) method:

Note how the method uses the okhttp3.Call object.

We examined the dependencies configured in the build.gradle file and discovered the okhttp dependency:

Having established that the OpenAPI Generator SDK uses the OkHttp library, we were curious to see how the Speakeasy-generated SDK handles HTTP communication.

Take a look at this extract from the addPetJson method in the Pet.java file of the Speakeasy SDK:

This method uses HTTPClient, HTTPRequest, and HTTPResponse objects. If we look at the import statements, we can see that these objects are generated from the following classes:

The HTTPClient and HTTPRequest interfaces are both generated by Speakeasy.

We can see the HTTPClient interface implemented in SpeakeasyHTTPClient.java to establish the HTTP communication method:

The Speakeasy SDK uses the Java HTTP APIs that were introduced in Java 11. Some of the benefits of using the built-in Java HTTP APIs are:

  • Standardization: By using the HTTP Client API supported in Java 11, the SDK uses the standards provided and supported by modern Java SDK providers. The HttpClient class integrates more easily with the other Java APIs in the Java SDK.
  • Asynchronous support: Asynchronous HTTP communication is not available in Java 8, making it harder to build scalable applications. The HTTP Client API asynchronous HTTP communication available in Java 11 provides a CompletableFuture object immediately after calling the API, which gives developers more control.
  • Performance and efficiency: The HTTP Client is created using a builder and allows for configuring client-specific settings, such as the preferred protocol version (HTTP/1.1 or HTTP/2). It also supports Observable APIs.
  • Security, stability, and long-term support: As a standard Java API, the HTTP Client is more stable and secure, and benefits from the long-term support cycles of new Java versions.

Retries

The SDK created by Speakeasy can automatically retry requests.

You can enable retries globally or per request using the x-speakeasy-retries extension in your OpenAPI specification document.

Let’s add the x-speakeasy-retries extension to the addPet method in the petstore.yaml file:

If you re-generate the SDK now, the new retry configuration will be included.

For more information on configuring retries in your SDK, take a look at the retries documentation.

SDK dependencies

Let’s compare dependencies in the two SDKs.

Here are the OpenAPI Generator SDK dependencies in build.gradle:

Here are the Speakeasy SDK dependencies from build.gradle:

The OpenAPI Generator SDK implements more libraries than the Speakeasy SDK, possibly due to the compatibility requirements and limitations of Java 8. Depending on fewer third-party implementations provides the Speakeasy SDK with some advantages:

  • Less maintenance: Projects with fewer dependencies have a lower maintenance overhead and less versioning to keep track of long term.
  • Reduced risk of dependency-related issues: Third-party dependencies increase the risk of bugs and security failures that depend on the third-party provider to fix. A security flaw in a third-party dependency makes your application vulnerable.
  • Improved performance: Code generally works better in standard Java APIs as they have been through rigorous testing and QA cycles before being made available to the public.
  • Easier adoption: Projects tend to more readily accept SDK builds that rely on fewer third-party dependencies, due to strict policies regarding the use and management of these dependencies.

Handling non-nullable fields

Let’s see how Speakeasy’s enhanced null safety and Optional support work on fields in the Pet object.

Take a look at the following declaration taken from the Pet object in the Speakeasy SDK org.openapis.openapi.models.components.Pet.java file:

Note that the @JsonInclude annotation indicates it is NON-ABSENT and the Optional class is used. The status field here is an enum (Status) wrapped in the Optional class.

Let’s examine the Status enum object:

Let’s compare the Speakeasy SDK status field declaration to the same field in the OpenAPI Generator SDK. The following declaration is taken from the org.openapitools.client.model.Pet.java file:

At first glance, the OpenAPI Generator SDK also uses an enum approach, representing the status field as an enum called StatusEnum with three possible values: AVAILABLE, PENDING, and SOLD. A lot of code is generated around this field to handle the enum, but the Pet object does not indicate that the OpenAPI Generator SDK status field is non-nullable at this point.

In contrast, Speakeasy uses a direct approach to non-nullable fields. The Speakeasy SDK also uses a Status enum for the status field, but it is wrapped in the Optional class provided by the Java standard APIs.

Declaring the status field as the Status type wrapped in the Optional class has some benefits to the developer:

  • It helps to avoid possible NullPointerException errors when accessing a null value.
  • It provides a modern way for developers to identify the absence of a value using the isPresent() method from the Optional class API and exposes other usable methods like orElse() and orElseThrow().
  • It clearly states the intent and use of the code, which helps to reduce bugs in the long run.

Let’s see how client validation works by passing a null value to the findPetsByStatus() method, which expects Optional<? extends Status> status. We create the following builder pattern for a new request:

When we execute this bit of code, we get the following exception:

The same exception is generated if we remove the name field from the builder declaration of a new Pet object:

When we execute the above code, we get the exception:

The null check validation generates this exception when the Pet object is initiated and certain values are null. If we look at the class constructor in our Pet.java model in the Speakeasy SDK:

We can see that the exception is generated in the Utils.checkNotNull() method:

Therefore, if we omit the name field or pass a null value in the findPetByStatus() method, an exception is generated by the check null validation because the name and status fields explicitly set to null in this case.

Let’s try creating a Pet object without a name field using the OpenAPI Generator SDK:

When we execute the above code, we get a mixed result. The following exception is generated:

It appears that the Pet object was created on the API, but the call failed retrospectively on the client side. The exception was generated by the SDK’s validation process, which checks the JSON response received from the API. You can see the created object in the JSON response included in the exception:

Validation failed because the name was missing from the JSON string. This validation method is not helpful, as it checks the response after the API call rather than before the request is sent. Consequently, an invalid object was created on the API and the client process failed.

Speakeasy’s proactive client validation and method of handling non-nullable fields with the use of the Optional class is elegant. Code that is easy to read, understand, and use, and that also helps to build null safety is essential for building robust, maintainable SDKs.

Generated documentation

Both Speakeasy and OpenAPI Generator generate SDK documentation for the generated code.

Each generator creates a README file to help users get started with the SDK. The OpenAPI Generator README outlines the SDK’s compatibility with Java, Maven, and Gradle versions and identifies the available API routes. The Speakeasy README file is more complete and documents more examples.

Speakeasy also generates additional documentation in the docs directory, including more detailed explanations of the models and operations; examples of creating, updating, and searching objects; error handling; and guidance on handling exceptions specific to the OpenAPI specification file. A handy “Getting Started” section details how to build the SDK.

In general, we found the Speakeasy documentation to be more complete and helpful. We tested many API call examples from the documentation, and conclude that the Speakeasy docs are production-ready.

Supported Java versions

The Speakeasy-generated SDK supports Java 11+ environments, and the SDK generated by OpenAPI Generator supports Java 8+.

While the OpenAPI SDK supports more codebases including those still using Java 8, the Speakeasy SDK leverages the enhancements provided by Java 11. Java 8 was released in March 2014, and was the most widely used version of Java until version 11 was released in September 2019.

In 2023, New Relic reported that Java 11 is used in around 56% of production applications, while Java 8 is still in use at around 33%. Both versions are important long-term support (LTS) versions.

Summary

We’ve seen how easy it is to generate a powerful, idiomatic SDK for Java using Speakeasy.

If you’re building an API that developers rely on and would like to publish full-featured Java SDKs that follow best practices, we highly recommend giving the Speakeasy SDK generator a try.

For more customization options for your SDK using the Speakeasy generator, please see the Speakeasy documentation.

Join our Slack community to let us know how we can improve our Java SDK generator or suggest features.

Last updated on