v0.5.0
Java SDK

Run a Java worker with Spring Boot

Run a dedicated Spring worker service with discovered stage beans, managed lifecycle and execution scopes.

The Spring Boot starter binds application.yml, discovers stage beans, starts the configured transport and stops the worker with the application context. Deploy this application as a dedicated worker service. Producer applications remain separate and do not import the worker's stage beans into their Spring context.

Download the Spring demo. It uses the same Order, ValidateOrder and RecordOrder business classes as getting started, plus a Spring entry point.

Install the starter

From the matching SDK source root:

sh
./mvnw -B -pl sdk-spring-boot-starter -am install -DskipTests

Use this dependency instead of the plain application's entry dependency; it includes the SDK runtime:

xml
<dependency>
  <groupId>com.pipelogiq</groupId>
  <artifactId>pipelogiq-sdk-spring-boot-starter</artifactId>
  <version>0.5.0</version>
</dependency>

The starter targets Spring Boot 3 and Java 17+. The downloadable application contains a complete POM, so it can be compiled with the matching SDK's Maven wrapper without assuming Central publication.

Configure the application

Create src/main/resources/application.yml:

yaml
spring:
  main:
    keep-alive: true

pipelogiq:
  api-url: ${PIPELOGIQ_API_URL:http://localhost:8081}
  api-key: ${PIPELOGIQ_API_KEY}
  worker-name: ${PIPELOGIQ_WORKER_NAME:orders-java-spring}
  environment: development
  transport: ${PIPELOGIQ_TRANSPORT:http}
  max-concurrency: 4

spring.main.keep-alive: true keeps this non-web worker process alive after application startup. The starter manages its startup and shutdown; keep the process running continuously like any other worker service.

These settings use Spring's property sources, profiles and placeholder resolution. They do not invoke the standalone YAML file loader. Explicit placeholders let this sample use the same PIPELOGIQ_* environment names as the plain demo. See configuration for timeouts and transport options.

Register the business stages as beans

src/main/java/example/spring/SpringOrdersApplication.java:

java
package example.spring;

import example.RecordOrder;
import example.ValidateOrder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import({ValidateOrder.class, RecordOrder.class})
public class SpringOrdersApplication {
  public static void main(String[] args) {
    SpringApplication.run(SpringOrdersApplication.class, args);
  }
}

@Import turns these existing classes into beans without adding Spring annotations to the business stages. Alternatively, use @Component scanning or declare @Bean factory methods. Keep @Stage for stable wire names and implement StageHandler<T> or NoInputStageHandler as usual.

The starter publishes typed PipelogiqClient and low-level PipelogiqApiClient beans when the application has not provided its own. In this worker service, stages can borrow the typed client through StageContext when they need to create related work. A separate producer-only Spring application can use the starter with no stage beans; then no worker is created.

Build, run and submit

From the extracted pipelogiq-java-spring-demo directory, with PIPELOGIQ_SDK_DIR pointing to the SDK source root:

sh
"$PIPELOGIQ_SDK_DIR/mvnw" -q compile dependency:copy-dependencies
export PIPELOGIQ_API_URL='http://localhost:8081'
export PIPELOGIQ_API_KEY='your-application-api-key'
java -cp 'target/classes:target/dependency/*' example.spring.SpringOrdersApplication

Stop any basic demo worker first if you want this Spring worker to execute the submitted order. Keep the Spring process running. In another terminal, open the same demo, set the API settings, and submit:

sh
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample submit spring-001 42.50
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample wait 123 60

Replace 123 with the printed ID. Expect COMPLETED, Recorded: true and two completed stages. Ctrl+C closes the Spring context and drains the worker. Set PIPELOGIQ_TRANSPORT=amqp before starting to exercise the same application over AMQP.

Use the client in a separate Spring producer

A different Spring application, such as an HTTP API, can receive the application-scoped client through constructor injection. Do not register stage beans in that producer application. Share DTOs and stable StageRef contracts instead of depending on worker implementation classes:

java
package example.spring;

import example.Order;
import io.pipelogiq.sdk.core.PipelogiqClient;
import io.pipelogiq.sdk.core.client.PipelineResponse;
import io.pipelogiq.sdk.core.client.StageRef;
import org.springframework.stereotype.Service;

@Service
public final class OrderSubmissionService {
  private static final StageRef<Order> VALIDATE = StageRef.of("ValidateOrder", Order.class);
  private static final StageRef<Void> RECORD = StageRef.noInput("RecordOrder");
  private final PipelogiqClient client;

  public OrderSubmissionService(PipelogiqClient client) {
    this.client = client;
  }

  public PipelineResponse submit(Order order) {
    return client.pipeline("Process order " + order.orderId())
        .idempotencyKey("spring-order-" + order.orderId())
        .stage(VALIDATE, order)
        .stage(RECORD)
        .send();
  }
}

This class belongs to the producer application, not the worker service shown above. Do not close the injected client after each request; Spring owns it. Use named async operations when the surrounding application needs CompletableFuture composition, while keeping the bean alive for their duration.

Choose a stage lifetime

Bean lifetimeBehavior
Singleton, the Spring defaultBorrowed stage instance; may execute concurrently and must be thread-safe
Prototype stageNew handler for an invocation; the starter destroys that handler afterward
pipelogiq-stage scopePer-invocation stage/dependency graph with destruction callbacks

For an invocation-scoped stage or dependency, use:

java
import io.pipelogiq.sdk.spring.PipelogiqStageScope;
import org.springframework.context.annotation.Scope;

@Scope(PipelogiqStageScope.NAME)

Place the annotation on the corresponding bean class or @Bean factory method. Scope both the stage and the dependencies that must share its attempt lifetime. A prototype handler alone does not automatically give every dependency managed per-attempt cleanup. Borrowed singleton dependencies remain application-owned.

Control startup in tests

Set pipelogiq.auto-startup: false to create the managed worker without connecting automatically. A test can then inspect its configuration and beans without requiring a live server. This is not a production hosting mode and does not replace transport integration tests.

Do not write your own shutdown hook in a Spring application. Let the context stop the worker before its dependent resources are closed. A closed worker handle cannot be restarted; create a new application context or worker for another lifetime.

Download this page as MarkdownMatches the 0.5.0 source release

Start here