diff --git a/openapi/frameworks/assets/springboot/speakeasy-suggestions.png b/openapi/frameworks/assets/springboot/speakeasy-suggestions.png
new file mode 100644
index 00000000..16b377e3
Binary files /dev/null and b/openapi/frameworks/assets/springboot/speakeasy-suggestions.png differ
diff --git a/openapi/frameworks/springboot.mdx b/openapi/frameworks/springboot.mdx
index 6a673f31..61110af7 100644
--- a/openapi/frameworks/springboot.mdx
+++ b/openapi/frameworks/springboot.mdx
@@ -1,37 +1,36 @@
---
-title: How to generate an OpenAPI/Swagger document with Spring Boot
-description: "Generating an OpenAPI specification with Spring Boot and using it to create SDKs with Speakeasy."
+title: How To Generate an OpenAPI Document With Spring Boot
+description: "Generating an OpenAPI document with Spring Boot and using it to create SDKs with Speakeasy."
---
import { Callout } from "@/mdx/components";
-
# Generating an OpenAPI document and SDK from Spring Boot
-You have a Spring Boot API and need to generate SDKs or API documentation for other teams. Rather than writing and maintaining separate OpenAPI specs, we will walk through how to generate them directly from your Spring Boot code, and then use them to create and customize an SDK.
+You have a Spring Boot API and need to generate SDKs or API documentation for other teams. Rather than writing and maintaining separate OpenAPI documents, we will walk through how to generate them directly from your Spring Boot code and then use them to create and customize an SDK.
We'll work with real code you can run locally, building a simple bookstore API to demonstrate how to properly document API structures, including inheritance between models, endpoint definitions, response types, and error handling. The examples illustrate how Spring Boot annotations map to OpenAPI concepts, so you can see how your code translates into API specifications.
The example below will guide you through the process of creating a Spring Boot project, adding the necessary dependencies, writing Spring Boot controllers with OpenAPI annotations, and generating an OpenAPI document from it.
- To skip this setup and follow along with our example, clone the [example application](https://github.com/speakeasy-api/spring-boot-openapi-example).
+ To skip this setup and follow along with our example, clone the [example application](https://github.com/speakeasy-api/examples/tree/main/framework-springboot). The example uses Java 21.
-## Step 1: Set up a Spring Boot project
+## Setting up a Spring Boot project
First, create a new Spring Boot project using [Spring Initializr](https://start.spring.io/). Select the following options:
- Project: Maven
- Language: Java
-- Spring Boot: 2.7.x (or the latest stable version)
+- Spring Boot: 3.5.x (or the latest stable version)
- Project Metadata: Fill in as appropriate
- Dependencies: Spring Web
Download the project and extract it to your preferred directory.
-## Step 2: Add OpenAPI dependencies
+## Adding OpenAPI dependencies
Open the `pom.xml` file and add the following dependency:
@@ -39,11 +38,11 @@ Open the `pom.xml` file and add the following dependency:
org.springdoc
springdoc-openapi-starter-webmvc-ui
- 2.1.0
+ 2.8.8
```
-## Step 3: Configure application properties
+## Configuring application properties
Open the `src/main/resources/application.properties` file and add the following configuration:
@@ -61,15 +60,13 @@ These properties configure the application name that identifies your service, th
After starting your application, you can view the OpenAPI document at `http://localhost:8080/api-docs` and access the interactive Swagger UI at `http://localhost:8080/swagger-ui.html`.
-## Step 4: Write a Spring Boot application
+## Writing a Spring Boot application
-All the code in this step can be found in our example application.
+You can find all the code for this step in the example application.
Open the `src/main/java/com/bookstore/BookstoreApplication.java` file in your text editor to see where to begin when adding OpenAPI annotations to your project.
-## Defining API Documentation with Spring Boot Annotations
-
-### Main Application Configuration
+### Defining the main application configuration with annotations
The `BookstoreApplication` class is the entry point for the API, and it's also where we define the main OpenAPI documentation properties:
@@ -116,9 +113,12 @@ public class BookstoreApplication {
The `@OpenAPIDefinition` annotation populates the OpenAPI document with essential context for anyone who wants to use the API. The `title`, `version`, and `description` fields describe what the API does, its current state, and how it can be used.
-The `@Server` annotation defines available endpoints for the API. In the example, there are two options: a production server at `https://api.bookstore.example.com` that uses live data, and a localhost server at `http://localhost:8080` for testing with sample data.
+The `@Server` annotation defines available endpoints for the API. In the example, there are two options:
+
+- A production server at `https://api.bookstore.example.com` that uses live data
+- A localhost server at `http://localhost:8080` for testing with sample data
-### Defining Data Models
+### Defining data models with annotations
Next, let's look at how you can use OpenAPI annotations to describe API data structures in the `Models.java` file:
@@ -242,7 +242,7 @@ enum OrderStatus {
}
```
-This appears in the OpenAPI specification as a string field with a set of allowed values.
+This appears in the OpenAPI document as a string field with a set of allowed values.
Finally, we define an error response model:
@@ -259,7 +259,7 @@ class ErrorResponse {
}
```
-### Defining API Endpoints
+### Defining API endpoints with annotations
Now, let's define the API endpoints in the `PublicationsController.java` file:
@@ -310,12 +310,11 @@ public ResponseEntity> getPublication(
}
```
-The `@Operation` and `@ApiResponses` annotations document what the endpoint does and what responses to expect. For example, `getPublication` is annotated to show that it returns a publication successfully (`200` status) or an error (`404` status) if the publication isn't found.
+The `@Operation` and `@ApiResponses` annotations document what the endpoint does and what responses to expect. For example, `getPublication` is annotated to show that it returns a publication successfully (`200` status) or returns an error (`404` status) when the publication isn't found.
The `@Parameter` annotation describes the requirements for input parameters, such as the ID path parameter in this example.
-
-## Step 5: View the generated OpenAPI document
+## Examining the generated OpenAPI document
Now that we've built the Spring Boot application, let's generate and examine the OpenAPI document to understand how the Java code translates into API specifications.
@@ -334,12 +333,9 @@ curl http://localhost:8080/api-docs.yaml -o openapi.yaml
This command saves the OpenAPI document as `openapi.yaml` in your current directory.
-
-## Examining the Generated OpenAPI Document
-
Let's explore the generated OpenAPI document to see how the Spring Boot annotations translate into an OpenAPI specification.
-### OpenAPI Version Information
+### The OpenAPI Specification version information
The OpenAPI document begins with version information:
@@ -347,9 +343,9 @@ The OpenAPI document begins with version information:
openapi: 3.1.0
```
-This version is determined by the configuration in our application.properties file. It tells API consumers which OpenAPI spec version to expect.
+This version is determined by the configuration in our `application.properties` file. It tells API consumers which version of the OpenAPI Specification to expect.
-### API Information
+### API information
Next comes the `info` object, which is generated from the `@OpenAPIDefinition` annotation:
@@ -372,7 +368,7 @@ info:
Notice how each field in the Java annotation maps directly to its counterpart in the OpenAPI document output. This one-to-one mapping makes it easy to understand how your code affects the final API documentation.
-### Server Information
+### Server information
Server configurations defined with `@Server` annotations appear in the servers array:
@@ -384,7 +380,7 @@ servers:
description: Development server (uses test data)
```
-### Polymorphic Models
+### Polymorphic models
One of the more complex aspects of the API is how polymorphic models are represented. The `Publication` class has been translated into a schema that supports polymorphism through a discriminator:
@@ -435,7 +431,7 @@ Key aspects to notice:
- The `@JsonTypeInfo` annotation determines the discriminator property
- The `@JsonSubTypes` annotation defines the possible concrete implementations
-### API Endpoints
+### API endpoints
Finally, let's examine how controller methods translate into API endpoints. Here's how the `getPublication` endpoint appears in the OpenAPI document:
@@ -460,6 +456,7 @@ Finally, let's examine how controller methods translate into API endpoints. Here
content:
application/json:
schema:
+ type: object
oneOf:
- $ref: '#/components/schemas/Book'
- $ref: '#/components/schemas/Magazine'
@@ -472,11 +469,12 @@ Finally, let's examine how controller methods translate into API endpoints. Here
```
The mapping is clear:
-- The `@Operation` annotation provides the summary and description
-- Each `@ApiResponse` maps to an entry in the responses object
-- The `@Parameter` annotation documents the path parameter
-# Create an SDK from the OpenAPI document
+- The `@Operation` annotation provides the summary and description.
+- Each `@ApiResponse` maps to an entry in the responses object.
+- The `@Parameter` annotation documents the path parameter.
+
+## Creating an SDK from the OpenAPI document
Now that we have an OpenAPI document for the Spring Boot API, we can create an SDK using Speakeasy.
@@ -492,26 +490,64 @@ Now, generate a TypeScript SDK using the following command:
speakeasy quickstart
```
-Follow the onscreen prompts to provide the configuration details for the new SDK such as the name, schema location, and output path. Enter `openapi.yaml` when prompted for the OpenAPI document location and select your preferred language, for example, TypeScript, when prompted for which language you would like to generate.
+Follow the onscreen prompts to provide the configuration details for the new SDK, such as the name, schema location, and output path. Enter `openapi.yaml` when prompted for the OpenAPI document location and select your preferred language (for example, TypeScript) when prompted for which language you would like to generate.
+
+You'll see the steps taken by Speakeasy to create the SDK in the terminal:
-After running this command, you'll find the generated SDK code in the specified output directory. This SDK can be used by clients to interact with your Spring Boot API in a type-safe manner.
+```bash Terminal
+│ Workflow - running
+│ Workflow - success
+│ └─Target: sdk - success
+│ └─Source: Bookstore API - success
+│ └─Validating Document - success
+│ └─Diagnosing OpenAPI - success
+│ └─Tracking OpenAPI Changes - success
+│ └─Snapshotting OpenAPI Revision - success
+│ └─Storing OpenAPI Revision - success
+│ └─Validating gen.yaml - success
+│ └─Generating Typescript SDK - success
+│ └─Setup Environment - success
+│ └─Load and Validate Document - success
+│ └─Generate SDK - success
+│ └─Compile SDK - success
+│ └─Setup Environment - success
+│ └─Load and Validate Document - success
+│ └─Generate SDK - success
+│ └─Generating Code Samples - success
+│ └─Snapshotting Code Samples - success
+│ └─Snapshotting Code Samples - success
+│ └─Uploading Code Samples - success
+```
-# Customize the SDK
+Speakeasy [validates](/docs/core-concepts#validation) the OpenAPI document to check that it's ready for code generation. Validation issues will be printed in the terminal. The generated SDK will be saved as a folder in your project.
-Let's add retry logic to the SDK's `listPublications` operation to handle network errors gracefully. We'll do this using an OpenAPI extension that [Speakeasy provides](/docs/customize-sdks/retries), `x-speakeasy-retries`.
+If you get ESLint styling errors, run the `speakeasy quickstart` command from outside your project.
-Instead of modifying the OpenAPI document directly, we'll add this extension to the Spring Boot controller and regenerate the OpenAPI document and SDK.
+Speakeasy also suggests improvements for your SDK using [Speakeasy Suggest](/docs/prep-openapi/maintenance), which is an AI-powered tool in Speakeasy Studio. You can see suggestions by opening the link to your Speakeasy Studio workspace in the terminal:
-First, add these imports to `src/main/java/com/bookstore/PublicationsController.java`:
+
+After running this command, you'll find the generated SDK code in the specified output directory. This SDK can be used by clients to interact with your Spring Boot API in a type safe manner.
+
+In the SDK `README.md` file, you'll find documentation about your Speakeasy SDK. TypeScript SDKs generated with Speakeasy include an installable [Model Context Protocol (MCP) server](https://www.speakeasy.com/docs/model-context-protocol) where the various SDK methods are exposed as tools that AI applications can invoke.
+Your SDK documentation includes instructions for installing the MCP server.
+
+Note that the SDK is not ready for production use. To get it production-ready, follow the steps outlined in your Speakeasy workspace.
+
+## Customizing the SDK
+
+The example app added retry logic to the SDK's `listPublications` operation to handle network errors gracefully. This was done using one of [Speakeasy's OpenAPI extensions](/docs/speakeasy-reference/extensions), `x-speakeasy-retries`.
+
+Instead of modifying the OpenAPI document directly, this extension was added to the Spring Boot controller, and the OpenAPI document and SDK were regenerated.
+
+These imports were added to `src/main/java/com/bookstore/PublicationsController.java`:
```java PublicationsController.java
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
```
-Then modify the `listPublications` operation to include the retry configuration:
-
+The `listPublications` operation was modified to include the retry configuration:
```java PublicationsController.java mark=2:7
@Operation(summary = "List all publications", description = "Get a list of all publications in the store", extensions = {
@@ -536,13 +572,13 @@ Then modify the `listPublications` operation to include the retry configuration:
}
```
-Now that we've added the `x-speakeasy-retries` extension to the `listPublications` operation, we can regenerate the OpenAPI document:
+The OpenAPI document was then regenerated:
```bash Terminal
curl http://localhost:8080/api-docs.yaml -o openapi.yaml
```
-The OpenAPI document will include the retry configuration for the `listPublications` operation:
+The OpenAPI document includes the retry configuration for the `listPublications` operation:
```yaml openapi.yaml
x-speakeasy-retries:
@@ -557,16 +593,20 @@ x-speakeasy-retries:
retryConnectionErrors: true
```
-Now we can use Speakeasy to recreate the SDK:
+After recreating the SDK using Speakeasy:
```bash
speakeasy quickstart
```
-The created SDK will now include retry logic for the `listPublications` operation, automatically handling network errors and `5XX` responses.
-
+The created SDK now includes retry logic for the `listPublications` operation, automatically handling network errors and `5XX` responses.
### Issues and feedback
Need some assistance or have a suggestion? Reach out to our team at [support@speakeasy.com](mailto:support@speakeasy.com).
+If you haven't already, take a look at our [blog](/blog) to learn more about OpenAPI, SDK generation, and more, including:
+
+- [Native JSONL support in your SDKs](/blog/release-jsonl-support)
+- [Comprehensive SDK testing](/blog/release-sdk-testing)
+- [Model Context Protocol: TypeScript SDKs for the agentic AI ecosystem](/blog/release-model-context-protocol)