---
title: "Get started with Java"
description: "Run a worker with configuration and business stages, then submit and inspect a typed pipeline."
category: "Java SDK"
---

Build an orders worker and a separate producer with **one SDK dependency**. The worker validates an order, stores it in pipeline context, then records `recorded=true`. This demonstration does not write to a database or charge a customer.

[Download the runnable Java demo](/downloads/pipelogiq-java-demo.zip). It includes the files below plus independent-producer, retry and schedule recipes. The [matching SDK source](/downloads/pipelogiq-java-sdk-0.5.0-source.zip) supplies the local packages used by every example on these pages.

## Before you start

You need JDK 17 or 21, a running Pipelogiq API and an application API key. Use that application's key in both terminals. These instructions use macOS/Linux; Windows command equivalents are included below.

No Spring, broker URL or model provider is needed for the first run. HTTP is the default transport. Java package names start with `io.pipelogiq.sdk`; the Maven group is `com.pipelogiq`.

## Install the current SDK from source

Extract the matching source archive, open its root directory containing `mvnw` and `pom.xml`, and run:

```sh
export PIPELOGIQ_SDK_DIR="$PWD"
chmod +x mvnw
./mvnw -B -pl sdk-runtime -am install -DskipTests
```

This builds the recommended `pipelogiq-sdk` artifact and its dependencies into your local Maven repository. It does not publish anything. The wrapper downloads Maven automatically. This guide deliberately works without assuming version `0.5.0` has already been published to Maven Central.

Then extract the Java demo and open `pipelogiq-java-demo`. Alternatively, create the following files yourself. The SDK path variable must remain the absolute path to the SDK source root, not the demo directory.

`pom.xml`:

```xml
<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>example</groupId>
  <artifactId>pipelogiq-java-demo</artifactId>
  <version>1.0.0</version>
  <properties>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>com.pipelogiq</groupId>
      <artifactId>pipelogiq-sdk</artifactId>
      <version>0.5.0</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.16.0</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.8.1</version>
      </plugin>
    </plugins>
  </build>
</project>
```

`pipelogiq.yml` in the demo's root directory:

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

## Write the worker and client

Create `src/main/java/example/` and put each public type in its own file. These five files are included in the download. The download also contains a separate inspection and testing CLI.

### Order.java

```java
package example;

import java.math.BigDecimal;

public record Order(String orderId, BigDecimal amount) {}
```

### ValidateOrder.java

```java
package example;

import io.pipelogiq.sdk.core.execution.*;

@Stage("ValidateOrder")
public final class ValidateOrder implements StageHandler<Order> {
  @Override
  public StageResult execute(Order order, StageContext context) {
    context.throwIfCancelled();
    if (order.orderId() == null || order.orderId().isBlank()) {
      return StageResult.validationError("Order ID is required");
    }
    if (order.amount() == null || order.amount().signum() <= 0) {
      return StageResult.validationError("Amount must be positive");
    }
    context.put("validatedOrder", order);
    context.logInfo("Order validated");
    return StageResult.success();
  }
}
```

### RecordOrder.java

```java
package example;

import io.pipelogiq.sdk.core.execution.*;

@Stage("RecordOrder")
public final class RecordOrder implements NoInputStageHandler {
  @Override
  public StageResult execute(StageContext context) {
    Order order = context.require("validatedOrder", Order.class);
    context.put("recorded", true);
    return StageResult.success("Recorded demo order " + order.orderId());
  }
}
```

`@Stage` supplies a stable wire name. The SDK infers the input type from `StageHandler<Order>`; `NoInputStageHandler` reads required context without a dummy input argument. `context.require` classifies missing or incompatible data for you.

### OrdersExample.java

```java
package example;

import io.pipelogiq.sdk.Pipelogiq;

/** Run from the examples directory; the SDK owns startup, readiness and SIGTERM shutdown. */
public final class OrdersExample {
  public static void main(String[] args) {
    Pipelogiq.worker().config("pipelogiq.yml").stages(ValidateOrder.class, RecordOrder.class).run();
  }
}
```

The SDK owns client creation, transport selection, registration, readiness, leases, input conversion, result delivery and shutdown. The process keeps running until stopped; worker startup does not submit a pipeline.

### CreateOrder.java

```java
package example;

import io.pipelogiq.sdk.Pipelogiq;
import java.math.BigDecimal;
import java.time.Duration;

/** Run with OrdersExample (or SpringOrdersApplication) already listening. */
public final class CreateOrder {
  public static void main(String[] args) {
    try (var client = Pipelogiq.connect("pipelogiq.yml")) {
      var created = client.pipeline("Process order")
          .idempotencyKey("demo-order-intro-123")
          .stage(ValidateOrder.class, new Order("intro-123", new BigDecimal("42.50")))
          .stage(RecordOrder.class)
          .send();
      var completed = client.pipelines()
          .waitForCompletion(created.id(), Duration.ofSeconds(60));
      System.out.println("Pipeline " + completed.id() + ": " + completed.status());
      System.out.println("Recorded: " + completed.context("recorded", Boolean.class));
    }
  }
}
```

The producer owns one typed client for its operation. Pipeline drafts do not open separate connections and do not need their own `close()`. There is no application polling loop: `waitForCompletion` is bounded by the timeout supplied to it.

## Build and start the worker

From `pipelogiq-java-demo`, build once:

```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.OrdersExample
```

Keep this terminal running. After successful bootstrap, the dashboard shows worker `orders-java` online in the application associated with your API key. The example does not promise a particular console readiness message.

For Windows PowerShell, install the SDK with `.\mvnw.cmd -B -pl sdk-runtime -am install -DskipTests` from its root, save that absolute path in `$env:PIPELOGIQ_SDK_DIR`, then use these commands from the demo root:

```powershell
& "$env:PIPELOGIQ_SDK_DIR\mvnw.cmd" -q compile dependency:copy-dependencies
$env:PIPELOGIQ_API_URL = "http://localhost:8081"
$env:PIPELOGIQ_API_KEY = "your-application-api-key"
java -cp 'target/classes;target/dependency/*' example.OrdersExample
```

Other commands on these pages use the macOS/Linux `:` classpath separator. Use `;` on Windows. In a new terminal, export the API settings again. Set `PIPELOGIQ_SDK_DIR` again only if you need another build.

## Submit and observe

In a second terminal, open the same demo directory, set the same API variables, and run the small producer:

```sh
java -cp 'target/classes:target/dependency/*' example.CreateOrder
```

It submits the order and waits up to 60 seconds. Expect:

```text
Pipeline <id>: COMPLETED
Recorded: true
```

Open that pipeline in the dashboard to inspect both completed stages, logs and context. Running `CreateOrder` again reuses its fixed `demo-order-intro-123` idempotency key and returns the existing pipeline. Change the business ID and key together for a deliberately new order.

### Use the optional inspection CLI

The downloadable project also includes `CreatePipelineExample`, a utility for submitting different orders, inspecting status, and exercising failures and idempotency. It is not required by the five-file application above. If you created those files manually, obtain this optional utility from the demo download before running these commands:

```sh
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample submit order-001 42.50
```

It prints `Pipeline ID: <id>`. Replace `123` below with that ID:

```sh
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample get 123
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample wait 123 60
```

`get` reads a snapshot, which may still be pending or running. `wait` prints `COMPLETED`, `Recorded: true` and the statuses of `ValidateOrder` and `RecordOrder`. This utility uses `demo-order-<orderId>` as its idempotency key; choose a fresh order ID for a new request.

Try the two expected-behavior checks:

```sh
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample validate-failure rejected-001
java -cp 'target/classes:target/dependency/*' example.CreatePipelineExample idempotency repeated-001
```

The first prints a `FAILED` pipeline with `VALIDATION_ERROR` and `Recorded: false`. The second prints equal IDs and `Same pipeline: true`, then observes completion. A local wait timeout does not cancel server work; inspect or wait again using the same ID.

Press Ctrl+C in the worker terminal to stop gracefully. To repeat the experiment over AMQP, set `PIPELOGIQ_TRANSPORT=amqp` before starting the worker and use a new order ID. Broker settings come from server bootstrap; see [configuration](/docs/java/configuration#switch-to-amqp).

## If the first run does not complete

| Symptom | First check |
| --- | --- |
| Dependency cannot be resolved | Install the matching source into the same local Maven repository. |
| Missing API key | Export the key in each terminal or service environment. |
| Configuration file not found | Run from the demo root containing `pipelogiq.yml`. |
| Readiness failure | Verify API URL, authentication and transport reachability. |
| Pipeline stays pending | Keep a worker online with the same application key and matching stage names. |
| Previous result appears again | Reusing an order ID reuses its idempotency key. |

Continue with [workflow recipes](/docs/java/workflows), [schedules](/docs/java/schedules), [Spring Boot](/docs/java/spring-boot) or [agent testing](/docs/java/testing). The [troubleshooting guide](/docs/java/troubleshooting) covers failure diagnosis in more detail.
