Spring Boot Integration for Java SDKs
Speakeasy auto-generates Spring Boot starters
Configuration
Set generateSpringBootStarter: false in your gen.yaml to disable. Enabled by default.
Module Structure
build.gradle
Three modules provide complete Spring Boot integration:
- Auto-configuration: Bean registration with
@ConditionalOnMissingBean - Properties:
@ConfigurationPropertiesfrom OpenAPI spec - Starter: Dependency aggregator
Configuration Properties
Type-safe @ConfigurationProperties are auto-generated from your OpenAPI spec, namespaced under projectId:
@ConfigurationProperties(prefix = "my-api") // From your gen.yaml projectId
public class MyApiProperties {
// Core Configuration
private String serverUrl; // From OpenAPI servers section
private String server; // Server name (if using named servers)
private int serverIdx = 0; // Server index (0-based, defaults to first server)
// Server Variables (from OpenAPI spec)
private ServerVariables serverVariables = new ServerVariables();
// Security Configuration (flattened from OpenAPI security schemes)
private Security security = new Security();
// Global Parameters (from OpenAPI components)
private Globals globals = new Globals();
// SDK Behavior Configuration
private RetryConfig retryConfig = new RetryConfig();
private HttpClient httpClient = new HttpClient();
}Property Mapping:
- Servers: Indexed (
serverIdx) or named (server) with variables as enums - Security: Flattened schemes (API keys, OAuth, HTTP auth)
- Global Parameters: Headers, query params, path params from spec
- SDK Behavior: Retry policies, HTTP client settings
- Rich Types: OpenAPI enums → Java enums, duration strings →
Durationobjects
Auto-Configuration
Beans are conditionally registered based on classpath and properties:
@AutoConfiguration
@ConditionalOnClass(SDK.class)
@EnableConfigurationProperties(MyApiProperties.class)
public class MyApiAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SDK sdk(SDKConfiguration config) {
return new SDK(config); // Main SDK bean
}
@Bean // Individual sub-SDKs automatically available
@ConditionalOnMissingBean
public UsersSDK usersSDK(SDK sdk) {
return sdk.users();
}
@Bean // Conditional on property presence
@ConditionalOnProperty(prefix = "my-api.retry-config", name = "strategy")
public RetryConfig retryConfig(MyApiProperties properties) {
return convertToRetryConfig(properties.getRetryConfig());
}
@Bean // Conditional on security configuration
@ConditionalOnPropertyPrefix(prefix = "my-api.security")
public SecuritySource securitySource(MyApiProperties properties) {
return buildSecurityFromProperties(properties.getSecurity());
}
}Bean Registration:
- Core SDK: Always present with starter
- Sub-SDKs: Per API group (Users, Orders, etc.)
- Security: Conditional on
my-api.security.* - Retry: Conditional on
my-api.retry-config.strategy - Async: When async mode enabled
Usage
Configure via application.yml:
my-api: # Namespace from your projectId
server-url: "https://api.example.com"
server-variables: # Rich type mapping with enum support
environment: PROD # Enum values provide IDE dropdown selection
region: US_EAST_1 # Type-safe enum prevents configuration errors
security: # Structured security configuration
api-key: "${API_KEY}"
oauth:
client-id: "${CLIENT_ID}"
client-secret: "${CLIENT_SECRET}"
retry-config: # SDK behaviors with readable duration formats
strategy: BACKOFF # Enum with IDE autocomplete
backoff:
initial-interval: 500ms # Duration parsing: ms, s, m, h
max-interval: 30s # Human-readable format
max-elapsed-time: 5m # Automatically converted to Duration objects
globals: # Global parameters from OpenAPI spec
user-agent: "MyApp/1.0"
api-version: "2023-10"
http-client: # HTTP behavior configuration
enable-debug-logging: false
redacted-headers: ["Authorization", "X-API-Key"]Inject and use with zero boilerplate:
@RestController
public class UserController {
@Autowired
private UsersSDK usersSDK; // Direct sub-SDK injection
@Autowired
private AsyncUsersSDK asyncUsersSDK; // Async variant
// Synchronous usage
@GetMapping("/users/{id}")
public User getUser(@PathVariable String id) {
return usersSDK.getUser()
.userId(id)
.call();
}
// Reactive usage with WebFlux
@GetMapping("/users/{id}/async")
public Mono<User> getUserAsync(@PathVariable String id) {
return Mono.fromFuture(
asyncUsersSDK.getUser()
.userId(id)
.call() // Returns CompletableFuture<User>
);
}
// Streaming data
@GetMapping(value = "/users/stream", produces = "application/x-ndjson")
public Flux<User> streamUsers(@RequestParam String department) {
Publisher<User> userStream = asyncUsersSDK.listUsers()
.department(department)
.callAsPublisher(); // Returns Publisher<User> for pagination
return Flux.from(userStream);
}
}WebFlux Integration
Async SDKs integrate seamlessly with Spring WebFlux
CompletableFuture→MonoconversionPublisher→Fluxfor streaming (pagination, SSE, JSONL)- Non-blocking reactive streams
support
Publishing
No workflow changes required. Gradle auto-configures additional artifacts:
{project-name}-spring-boot-autoconfigure-{version}.jar{project-name}-spring-boot-starter-{version}.jar
Published alongside your main SDK to existing repositories.
Benefits
For API Producers:
- Zero deployment overhead
- Reduced support via familiar Spring Boot patterns
- Faster adoption by Spring developers
- Enterprise appeal with Actuator
and ecosystem compatibility
For SDK Users:
- Add starter dependency, configure via
application.yml - Type-safe properties with IDE support
- Rich type mapping (enums, durations)
- WebFlux integration when async enabled
Compatibility: Spring Boot 2.x/3.x, Java 11+
Last updated on