Spring Boot Starter
The transact-spring-boot-starter provides Spring Boot auto-configuration for DBOS Transact.
DBOS requires a PostgreSQL database. If a non-PostgreSQL DataSource is provided or auto-detected, startup will throw an IllegalStateException.
Auto-Configured Beans
| Bean | Description |
|---|---|
DBOSConfig | Built from dbos.* properties. Declare your own to replace it; use DBOSConfigCustomizer to extend it. |
DBOS | The main DBOS instance, injected from DBOSConfig. |
DBOSLifecycle | SmartLifecycle that calls dbos.launch() on context start and dbos.shutdown() on context stop. Uses DEFAULT_PHASE (Integer.MAX_VALUE), so DBOS starts last (after all other beans) and stops first. |
DBOSAspect | AOP aspect that intercepts @Workflow and @Step calls on Spring-managed beans. |
DBOSWorkflowRegistrar | Scans all singleton beans after initialization and registers those with @Workflow methods. |
All beans are @ConditionalOnMissingBean — declare your own to replace any of them.
Configuration Properties
All properties are in the dbos.* namespace.
Application
| Property | Type | Default | Description |
|---|---|---|---|
dbos.application.name | String | — | Application name. Falls back to spring.application.name. One of the two must be set. |
dbos.application.version | String | — | Application version string used for version management. |
Datasource
| Property | Type | Default | Description |
|---|---|---|---|
dbos.datasource.url | String | — | JDBC URL for the DBOS system database. If unset, DBOS uses the application's primary DataSource bean. |
dbos.datasource.username | String | — | Database username. |
dbos.datasource.password | String | — | Database password. |
dbos.datasource.schema | String | dbos | Schema for DBOS system tables. |
dbos.datasource.migrate | boolean | true | Whether to run database migrations on startup. |
DBOS Conductor
| Property | Type | Default | Description |
|---|---|---|---|
dbos.conductor.key | String | — | DBOS Conductor API key. |
dbos.conductor.domain | String | — | DBOS Conductor domain. |
Admin Server
dbos.admin-server.* properties are deprecated since 0.9 and will be removed before 1.0. Use DBOS Conductor instead.
| Property | Type | Default | Description |
|---|---|---|---|
dbos.admin-server.enabled | boolean | false | Whether to enable the admin HTTP server. |
dbos.admin-server.port | int | 3001 | Port for the admin HTTP server. |
Other
| Property | Type | Default | Description |
|---|---|---|---|
dbos.executor-id | String | — | Unique executor ID for this instance. |
dbos.enable-patching | boolean | false | Enable workflow patching. |
dbos.listen-queues | List<String> | [] | Queues this executor should dequeue from. |
dbos.scheduler-polling-interval | Duration | — | Override the default scheduler polling interval. |
dbos.use-listen-notify | boolean | true | Whether to use PostgreSQL LISTEN/NOTIFY for real-time event delivery. Automatically set to false when CockroachDB is detected. |
DBOSConfigCustomizer
@FunctionalInterface
public interface DBOSConfigCustomizer {
DBOSConfig customize(DBOSConfig config);
}
Declare one or more DBOSConfigCustomizer beans to modify the auto-configured DBOSConfig without replacing it. Customizers run in @Order / Ordered sequence after the base config is assembled from dbos.* properties.
@Bean
@Order(1)
public DBOSConfigCustomizer myCustomizer() {
return config -> config.withAdminServer(true).withAdminServerPort(8081);
}
DBOSWorkflowRegistrar
Implements SmartInitializingSingleton. After all singletons are created, it scans every bean for methods annotated with @Workflow or @Step. Beans containing @Workflow methods are registered with DBOS for durable execution and recovery. @Step methods are not registered directly — they are intercepted at runtime by DBOSAspect.
Requirements:
- Beans with
@Workflowor@Stepmethods must be singletons. Prototype-scoped beans throwIllegalStateException. - DBOS registers the raw (unwrapped) bean target. Calls made via
thisinside a workflow body bypass the Spring proxy and are not intercepted byDBOSAspect. Use a self-injected proxy instead (see Spring Boot Integration tutorial)
Multiple beans of the same class:
| Situation | Instance name |
|---|---|
| Only one bean of the class | null string (default) |
Multiple beans — the @Primary one | null string (default) |
| Multiple beans — non-primary | Spring bean name |
@TransactionalStep
Module: dev.dbos:transact-spring-txstep-starter (separate from transact-spring-boot-starter).
Package: dev.dbos.transact.spring.txstep.
public @interface TransactionalStep {
String name() default "";
}
Marks a Spring-managed method as a step factory step.
The behaviour depends on calling context:
| Context | Behaviour |
|---|---|
Inside a @Workflow, not inside a step | Full step factory behaviour: runs in a REQUIRES_NEW transaction, output written to tx_step_outputs atomically with user database work. On workflow retry the recorded output is replayed without re-executing the method body. |
Outside a workflow, or inside any step (including another @TransactionalStep) | Behaves like @Transactional: runs with PROPAGATION_REQUIRED (joins an existing transaction or starts a new one), no DBOS checkpoint recorded. |
The annotated method must be called through a Spring proxy — calls via this bypass the aspect.
Parameters:
- name: Stable name for this step within the workflow. Defaults to the method name.
Supported stacks: Spring JDBC / JdbcTemplate, JDBI (jdbi3-spring), jOOQ (spring-boot-starter-jooq), JPA / Hibernate.
Installation
implementation("dev.dbos:transact-spring-boot-starter:<version>")
implementation("dev.dbos:transact-spring-txstep-starter:<version>")
<dependency>
<groupId>dev.dbos</groupId>
<artifactId>transact-spring-boot-starter</artifactId>
<version>VERSION</version>
</dependency>
<dependency>
<groupId>dev.dbos</groupId>
<artifactId>transact-spring-txstep-starter</artifactId>
<version>VERSION</version>
</dependency>
Auto-Configured Beans
| Bean | Description |
|---|---|
TransactionalStepAspect | AOP aspect that intercepts @TransactionalStep calls and delegates to TransactionalStepFactory. |
TransactionalStepFactory | Manages step lifecycle: idempotency check, transaction, and output recording. |
TransactionalStepRegistrar | Scans the Spring context post-startup and calls factory.initialize() (creates tx_step_outputs) only when annotated methods are found — no DB contact for apps that don't use the annotation. |
All beans are @ConditionalOnMissingBean.
Configuration
| Property | Default | Description |
|---|---|---|
dbos.txstep.schema | DBOS system schema | PostgreSQL schema for the tx_step_outputs table |
How it works
TransactionalStepAspectintercepts every@TransactionalStepcall and delegates toTransactionalStepFactory.- The factory calls
DBOS.runStep(), which checkstx_step_outputsfor a prior result. If one exists, it is returned immediately (idempotent replay). - Otherwise, a
REQUIRES_NEWSpring transaction is started. The method body runs, and the result is written totx_step_outputsusingDataSourceUtils.getConnection()— the same connection the transaction holds. - The transaction commits, making the user's write and the step output record atomic. If the method throws, the transaction rolls back and the error is recorded separately so retries can replay it.
See the Step Factory tutorial for per-stack examples (JDBC, JDBI, jOOQ, JPA).
DBOSAspect
An @Aspect that intercepts:
@Workflowmethods — routes the call throughdbos.integration().runWorkflow(...)for durable execution and recovery.@Stepmethods — delegates todbos.runStep(...)when called inside a workflow context; executes directly otherwise.
Spring AOP intercepts only calls that go through the Spring proxy. this.someStep() calls inside a workflow body are not intercepted. Inject a self-reference to ensure step calls are durable:
@Service
public class MyService {
@Autowired MyService self;
@Workflow
public String myWorkflow() {
return self.myStep(); // intercepted — durable
// this.myStep(); // NOT intercepted — runs outside DBOS
}
@Step
public String myStep() { return "result"; }
}