Automate SDK creation for Spring Boot APIs
Supported SDK languages:
TypeScript / Javascript | Java / Kotlin | Python | C# | Go | PHP |
---|---|---|---|---|---|
✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
- Before getting started make sure you have a liblab account and the liblab CLI installed.
- If you don't have an existing project but want to try out liblab then check out our standalone tutorials.
Providing an SDK for your API can significantly ease the development process for users, ensuring quicker integration and encouraging wider adoption due to the streamlined development experience.
In this doc you'll learn how to take your existing Spring Boot API and generate user-friendly SDKs for most major programming languages using the liblab SDK generator. After a short bit of setup you'll have a pipeline that will automatically generate SDKs for your API whenever you make changes.
Initializing the SDK
First, create a new directory to store your SDK. This directory should be separate from your existing project directory:
mkdir Spring-Boot-sdk
cd Spring-Boot-sdk
And initialize your project to create a liblab.config.json
file:
liblab init
Getting an OpenAPI Spec File
In order to auto-generate SDKs from a Spring Boot project you need an OpenAPI Spec File. The OpenAPI file contains information that describes your API like servers, paths, operations, parameters, responses, and security schemas.
Adding Springdoc
You can generate OpenAPI specs for your Spring Boot project using Springdoc. This library allows you to automatically generate OpenAPI files in JSON or YAML formats based on spring configurations, class structure, and annotations. Let's walk through the steps to do so.
This step assumes your project is similar to a project built with Spring Initializr with Maven and Spring WebMvc.
If you're using a different web framework then refer to the full Springdoc documentation to setup dependencies for other frameworks like Spring WebFlux, Spring Hateoas, and Spring Data Rest.
Once you're setup all other steps will be the same.
- Maven
- Gradle
First, navigate to your existing project directory and add the following dependency to your pom.xml
file under the <dependencies>
section:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.8.3</version>
</dependency>
First, navigate to your existing project directory and add this to your build.gradle
file:
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.3'
Springdoc automatically generates an OpenAPI 3.1.0 spec for your API when you start your project. By default your OpenAPI spec will be available at http://server:port/context-path/v3/api-docs
(ex. http://localhost:8080/v3/api-docs
).
Configuring Springdoc
To customize metadata such as the title, description, and server URLs, create a new configuration file named OpenApiConfig.java
. Place this file in the same package as your main application class. Here's an example that you can use as a starting point.
The most important thing to configure is the servers
list. Typically during this stage you would set this to a url for local development. This URL can always be changed later and liblab offers many options for configuring your server URL environment.
package com.example.api_example;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Spring Boot API")
.description("Simple Spring Boot API")
.version("1.0.0"))
.servers(List.of(
new Server().url("http://localhost:8080").description("Local Server")
));
}
}
For additional information on configuring the OpenAPI spec metadata, check the Springdoc documentation.
Annotating Your Routes
You don't need to annotate every route at once. You can start by annotating a single route or even just part of a route (e.g., the 200 response) to get the hang of the annotations. liblab will only build routes for endpoints that are present on your OpenAPI file.
Springdoc automatically generates the OpenAPI spec based on the code annotations and type information available for all endpoints. However it's often necessary to add additional annotations to ensure the OpenAPI spec properly reflects your API.
You can annotate your code with two tools:
- Data Transfer Object classes (DTOs)
- Swagger annotations
Use DTOs to define the structured data for requests and responses. Use Swagger annotations to describe the endpoint schema, descriptions, HTTP methods, and many other attributes. When used together a typical endpoint will describe:
- Human-readable
summary
anddescription
of the method. - The HTTP
responseCode
(e.g. 200, 400),mediaType
,content
, and descriptions of what the method returns. - DTOs that define the schema for each
content
section.
Annotating the DTO Class
As an example lets setup a DTO that represents a greeting message. Once completed it will produce a JSON response like this:
{
"message": "Greetings from Spring Boot!",
"timestamp": "2025-01-20T12:00:00Z"
}
For this example, assume a subpackage called dto
with a Greeting.java
class inside it. The project structure would look like this:
src/
└── main/
└── java/
└── com/
└── example/
└── api_example/
├── dto/
│ └── Greeting.java
├── YourApplication.java
├── OpenApiConfig.java
└── YourController.java
Here's the Greeting.java
code with the annotations for the hypothetical endpoint where @Schema
is used to define the data structure (ie. description
, example
, required
):
package com.example.api_example.dto;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "Get a greeting object containing a message and a timestamp")
public class Greeting {
@Schema(description = "The greeting message", example = "Greetings from Spring Boot!", required = true)
private String message;
@Schema(description = "The timestamp when the greeting was generated", example = "2025-01-20T12:00:00Z", required = true)
private String timestamp;
// Constructor
public Greeting(String message, String timestamp) {
this.message = message;
this.timestamp = timestamp;
}
// Getters and setters
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}
Adding these @Schema
annotations will result in an OpenAPI spec with an endpoint that looks something like the below. These and other annotations are important because they provide information that can later be used by liblab's SDK generator to automatically generate SDKs in multiple languages.
Click to see the OpenAPI spec for the DTO class
// ...
"paths": {
"/greeting": { // Path is not actually defined yet. See the next section.
"get": {
"description": "Get a greeting object containing a message and a timestamp",
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Greeting"
}
}
}
}
}
}
}
},
// ...
"components":{
"schemas": {
"Greeting": {
"required": [
"message",
"timestamp"
],
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "The greeting message",
"example": "Greetings from Spring Boot!"
},
"timestamp": {
"type": "string",
"format": "date-time",
"description": "The timestamp when the greeting was generated",
"example": "2025-01-20T12:00:00Z"
}
}
}
}
},
Annotating the Controller Class
There are many annotations available to describe your API endpoints. For a complete list of annotations refer to Swagger's annotation documentation
You can extend and complete your endpoints by annotating your controller classes to add @Operation
, @ApiResponse
, @Content
, and @Schema
Swagger annotation. The example below has annotations added to describe a single endpoint that receives a GET request and can return an HTTP 200
or an HTTP 400
response.
package com.example.api_example;
import com.example.api_example.dto.Greeting;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
@RestController
public class HelloController {
@GetMapping("/greeting")
@Operation(
summary = "Get a greeting message",
description = "Returns a greeting message with a timestamp.",
responses = {
@ApiResponse(
responseCode = "200",
description = "Successful response",
content = @Content(
schema = @Schema(implementation = Greeting.class)
)
),
@ApiResponse(
responseCode = "400",
description = "Bad request example",
content = @Content(
mediaType = "application/json",
schema = @Schema(example = "{\"error\":\"Invalid request\"}")
)
)
}
)
public Greeting index() {
return new Greeting("Greetings from Spring Boot!", Instant.now().toString());
}
}
Click to see the OpenAPI spec for the controller class
{
"openapi": "3.1.0",
"info": {
"title": "Spring Boot API",
"description": "Simple Spring Boot API",
"version": "1.0.0"
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Local Server"
}
],
"paths": {
"/greeting": {
"get": {
"tags": [
"your-controller"
],
"summary": "Get a greeting message",
"description": "Returns a greeting message with a timestamp.",
"operationId": "index",
"responses": {
"200": {
"description": "Successful response",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Greeting"
}
}
}
},
"400": {
"description": "Bad request example",
"content": {
"application/json": {
"schema": {
"type": "string",
"example": {
"error": "Invalid request"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Greeting": {
"type": "object",
"description": "Greeting object containing a message and a timestamp",
"properties": {
"message": {
"type": "string",
"description": "The greeting message",
"example": "Greetings from Spring Boot!"
},
"timestamp": {
"type": "string",
"description": "The timestamp when the greeting was generated",
"example": "2025-01-20T12:00:00Z"
}
},
"required": [
"message",
"timestamp"
]
}
}
}
}
Copy Your Spec
Once you're done adding the Swagger's annotations, restart your Spring Boot server:
./mvnw spring-boot:run
To view your OpenAPI spec, navigate to the /api-docs
endpoint on your server (e.g. http://localhost:8080/v3/api-docs
).
If the OpenAPI spec appears, then you're ready to proceed. Save your openapi.json
file to the liblab project directory you created during the initializing step. This is typically something like:
cd ../Spring-Boot-sdk
curl -o openapi.json http://localhost:8080/v3/api-docs
Configuring liblab
Now you'll need to make some minor updates to your liblab.config.json
file in your Spring-Boot-sdk folder:
- Point the
specFilePath
parameter to the location of your OpenAPI spec file (ex../openapi.json
). - Specify the
baseUrl
of your API. This is the URL that the SDK will use to make requests to your API.
The top of the file should then looks something like this:
{
"sdkName": "Spring-Boot-sdk",
"apiVersion": "1.0.0",
"apiName": "Spring-Boot-api",
"specFilePath": "./openapi.json",
"baseUrl": "http://localhost:PORT",
"languages": [
"go",
"java",
"python",
"typescript",
"csharp"
],
"auth": [
"bearer"
]
}
liblab's SDK generator supports many more advanced URL and environment configuration options than the basic configuration shown here.
Explore the configuration documentation to discover all the available settings and enhancements or review the SDK customization options for tailored adjustments.
Generate the SDK
During build you might see warnings about the OpenAPI spec. These are often minor issues that can be fixed later.
Now that you have an OpenAPI spec file and have finished setting the liblab.config.json
file, it's time to generate our SDK:
liblab build
The CLI will validate the OpenAPI spec and notify you about any issues with it or the liblab.config.json
.
The output will look something like this:
✓ No issues detected in the liblab config file.
No hooks found, SDKs will be generated without hooks.
⚠ Validation succeeded with warnings
Created /Users/username/projects/Spring-Boot-sdk/output/api-schema-validation.json with the full linting results
Detected 8 potential issues with the spec:
⚠ Info object must have "contact" object.
⚠ Info "description" must be present and non-empty string.
⚠ Operation "description" must be present and non-empty string. (3 occurrences)
⚠ Operation tags must be defined in global tags. (3 occurrences)
? It is important to fix your spec before continuing with a build. Not fixing the spec
may yield a subpar SDK and documentation. Would you like to attempt to build the SDK
anyway? (Y/n)
You can go ahead and confirm by typing Y
.
Next you'll see the builds started and once they're done you'll see a message like this:
Ignoring the spec errors and attempting to build with the spec
Your SDKs are being generated. Visit the liblab portal (https://app.liblab.com/apis/Spring-Boot-sdk/builds/1234) to view more details on your build(s).
✓ C# built
✓ Go built
✓ Java built
✓ Python built
✓ TypeScript built
✓ Generate package-lock.json for TypeScript
Successfully generated SDKs for Python, Java, Go, TypeScript, C#. ♡ You can find them inside: /Users/username/projects/Spring-Boot-sdk/output
If we go inside the output
directory, we will see a directory for each of our SDKs:
ls output/
api-schema-validation.json go python
csharp java typescript
Try out your SDK
The following instructions assume you have already set up the respective development environment for the language you are testing. If necessary refer to each language's official documentation before proceeding.
Learn more about the language versions liblab generated SDKs support.
The generated SDKs are intended to be deployed to package managers for end users. The instructions below to test your SDK locally will differ from user-facing instructions.
- TypeScript / JavaScript
- Python
- Java
- C#
cd output/typescript/examples
npm run setup
npm run start
cd output/python/examples
chmod +x install.sh
./install.sh
source .venv/bin/activate
python3 sample.py
cd output/java/example
chmod +x run.sh
./run.sh
cd output/csharp/Example
dotnet run --framework net9.0
Next Steps
Now that you've packaged your SDKs you can learn how to integrate them with your CI/CD pipeline and publish them to their respective package manager repositories.
We currently have guides for: