Publishing schemas from Spring Boot applications
The Spring Boot Schema Publisher starter automatically publishes Taxi schemas from your Spring Boot applications to Orbital on startup.
This is useful for microservices architectures where individual services own their own schema definitions and need to automatically register them with a central Orbital instance.
Adding the dependency
Add the starter dependency to your Spring Boot application’s pom.xml:
<dependency>
<groupId>com.orbitalhq</groupId>
<artifactId>schema-publisher-spring-boot-starter</artifactId>
<version>${orbital.version}</version>
</dependency>You also need to declare the Orbital repository:
<repositories>
<repository>
<id>orbital-releases</id>
<url>https://repo.orbitalhq.com/release</url>
</repository>
<!-- snapshot is only required if you're using snapshots -->
<repository>
<id>orbital-snapshots</id>
<url>https://repo.orbitalhq.com/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>Or for Gradle (build.gradle):
implementation 'com.orbitalhq:schema-publisher-spring-boot-starter:${orbitalVersion}'Once added, the starter will automatically:
- Discover Taxi schemas in your application at startup
- Publish them to the configured Orbital server
Configuration
The project uses reasonable defaults, so generally the only properties that requires configuration are:
- The base URL of your server
- The publisherId (which defaults to
${spring.application.name})
Defaults can be overridden by configuring the publisher in your application.yml:
orbital:
schema:
publisher:
enabled: true # Enable/disable publishing (default: true)
base-url: https://my-service-prod/ # Sets the base URL, where Orbital should try to call this application
publisher-id: my-service # Publisher ID (default: ${spring.application.name})
orbital-url: http://localhost:9022 # Orbital server URL (default: http://localhost:9022)
connection-timeout: 5000 # Connection timeout in ms (default: 5000)Or in application.properties:
orbital.schema.publisher.enabled=true
orbital.schema.publisher.base-url=https://my-service-prod/
orbital.schema.publisher.publisher-id=my-service
orbital.schema.publisher.orbital-url=http://localhost:9022
orbital.schema.publisher.connection-timeout=5000Configuration properties
| Property | Description | Default |
|---|---|---|
orbital.schema.publisher.enabled | Enable or disable schema publishing | true |
orbital.schema.publisher.base-url | The base url for this spring boot application | Not set |
orbital.schema.publisher.publisher-id | Unique identifier for this publisher | Value of spring.application.name |
orbital.schema.publisher.orbital-url | URL of the Orbital server | http://localhost:9022 |
orbital.schema.publisher.connection-timeout | Connection timeout in milliseconds | 5000 |
Schema generation
At runtime, the plugin will introspect Spring @RestController and @Service components, and automatically generate Taxi service and operation schemas, along with the associated
models for return types an inputs.
If you’re using Taxi annotations on your Java/Kotlin classes, these will be discovered and converted to Taxi schemas:
import lang.taxi.annotations.DataType;
@DataType("com.acme.payments.PaymentRequest")
public class PaymentRequest {
@DataType("com.acme.payments.PaymentId")
private String paymentId;
@DataType("com.acme.payments.Amount")
private BigDecimal amount;
// getters and setters...
}Using semantic types in code
When the schema is generated, type information is read at runtime. By default, only raw primitive types are available (such as String, Int, Decimal, etc).
To use richer semantic types, you can use the @DataType annotation (lang.taxi.annotations.DataType)
import lang.taxi.annotations.DataType;
@DataType("com.acme.payments.PaymentRequest")
public class PaymentRequest {
@DataType("com.acme.payments.PaymentId")
private String paymentId;
@DataType("com.acme.payments.Amount")
private BigDecimal amount;
}Importing vs Declaring types
By default, types declared with @DataType are declared as new types in the generated schema.
eg - the above code snippet would result in the following Taxi being generated:
namespace com.acme.payments
// Types are declared
type PaymentId inherits String
type Amount inherits Decimal
model PaymentRequest {
paymentId: PaymentId
amount: Amount
}
If you want to use existing types already decalared in a shared taxonomy, then declare the @DataType as imported:
@DataType("com.acme.payments.PaymentRequest")
public class PaymentRequest {
@DataType(value = "com.acme.payments.PaymentId", imported = true)
private String paymentId;
@DataType(value = "com.acme.payments.Amount", imported = true)
private BigDecimal amount;
}This would generate the following:
// Types are imported
import com.acme.payments.Amount
import com.acme.payments.PaymentId
namespace com.acme.payments
model PaymentRequest {
paymentId: PaymentId
amount: Amount
}
A good rule of thumb is that Types should be imported (shared), whereas models should be published (declared by your service). This aligns with the Taxi best practice of share types, not models.
Kotlin Type Aliases
You can take advantage of Kotlin type aliases to make your code more semantic, and cleaner:
@DataType(value = "com.acme.films.RentalDuration", imported = true)
typealias RentalDuration = Int
// elsewhere
data class FilmRental(duration: RentalDuration) Using generated Taxi types
Taxi supports generating Java and Kotlin code, using the Kotlin plugin.
This plugin will generate semantic types into a reusable library, which you can import into your spring boot microservice.
For example, given the following taxi code:
namespace films
[[ The Id of a film ]]
type FilmId inherits Int
[[ The title of the film ]]
type Title inherits StringIn a Taxi project with the Kotlin plugin enabled:
name: com.petflix/films
version: 0.1.0
sourceRoot: src/
plugins: {
taxi/kotlin: {
maven: {
groupId: "com.petflix"
artifactId: "films-taxonomy"
}
}
}When taxi build is run, a full Maven project is generated, which you can publish to your local Maven repository, and then
pull into your Spring boot project.
@RestController
class FilmsApi {
@GetMapping("/films/{id}")
fun findById(id: FilmId): Film {
// implementation
}
}For more information, consult the docs on Taxi’s Kotlin plugin
Disabling the publisher
To disable schema publishing (useful for local development or testing), set:
orbital:
schema:
publisher:
enabled: falseYou can also use Spring profiles to control when publishing is enabled:
# application-prod.yml
orbital:
schema:
publisher:
enabled: true
orbital-url: https://orbital.production.acme.com
# application-dev.yml
orbital:
schema:
publisher:
enabled: falseEnvironment-specific configuration
Use environment variables or Spring’s configuration management to configure different Orbital servers per environment:
orbital:
schema:
publisher:
orbital-url: ${ORBITAL_SERVER_URL:http://localhost:9022}
base-url: ${THIS_SERVICE_BASE_URL}Then set the environment variable in your deployment:
export ORBITAL_SERVER_URL=https://orbital.production.acme.comTroubleshooting
Publisher fails to connect on startup
If the Orbital server is not available when your application starts, the publisher will log an error but will not prevent your application from starting.
The publisher continues to retry to publish to Orbital.
To adjust the connection timeout:
orbital:
schema:
publisher:
connection-timeout: 10000 # 10 secondsNext steps
Once your schemas are published to Orbital, you can: