# spring-boot-starter-actor
**Repository Path**: c9567/spring-boot-starter-actor
## Basic Information
- **Project Name**: spring-boot-starter-actor
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-09-24
- **Last Updated**: 2026-10-08
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
|
Spring Boot Starter Actor
Bring the power of the actor model to your Spring Boot applications with Pekko (an open-source fork of Akka).
|
[](https://discord.com/channels/1439734161614045205/1439734162100846655)
[](https://seonwkim.github.io/spring-boot-starter-actor/)
## Why spring-boot-starter-actor?
I'm a Java developer, and I love using the actor model. However, Spring is everywhere in production. The goal of this project is to help Spring Boot projects easily integrate actor models with a great developer experience.
**Key Features:**
- Auto-configure necessary actor components (e.g., ActorSystem) within Spring Boot's context
- Dependency injection for actors
- Simplify cluster and sharding
- Built-in metrics using ByteBuddy to intercept actors and collect metrics
With spring-boot-starter-actor, you can build stateful distributed systems without third-party middleware (e.g., Redis, Kafka).
**Architecture**
```mermaid
graph TB
subgraph "Node 1"
U1[UserActor 1]
subgraph CR["ChatRoomActor"]
T[Topic]
end
end
subgraph "Node 2"
U2[UserActor 2]
end
subgraph "Node 3"
U3[UserActor 3]
end
WS1[🔌 WebSocket] --> U1
WS2[🔌 WebSocket] --> U2
WS3[🔌 WebSocket] --> U3
U1 -.->|subscribe| T
U2 -.->|subscribe| T
U3 -.->|subscribe| T
U1 -->|send message| CR
T -->|broadcast| U1
T -->|broadcast| U2
T -->|broadcast| U3
style CR fill:#8B5CF6,stroke:#7C3AED,color:#fff
style T fill:#A78BFA,stroke:#8B5CF6,color:#fff
style U1 fill:#06B6D4,stroke:#0891B2,color:#fff
style U2 fill:#06B6D4,stroke:#0891B2,color:#fff
style U3 fill:#06B6D4,stroke:#0891B2,color:#fff
```
## Quick Start
### Prerequisites
- Java 11 or higher
- Spring Boot 2.x or 3.x
### Installation
Add the dependency to your project:
**Gradle:**
```gradle
dependencyManagement {
imports {
// Pekko requires Jackson 2.17.3+
mavenBom("com.fasterxml.jackson:jackson-bom:2.17.3")
}
}
// Spring Boot 2.7.x
implementation 'io.github.seonwkim:spring-boot-starter-actor:0.3.0'
// Spring Boot 3.2.x
implementation 'io.github.seonwkim:spring-boot-starter-actor_3:0.3.0'
```
**Maven:**
```xml
com.fasterxml.jackson
jackson-bom
2.17.3
pom
import
io.github.seonwkim
spring-boot-starter-actor
0.3.0
io.github.seonwkim
spring-boot-starter-actor_3
0.3.0
```
Latest
versions: [spring-boot-starter-actor](https://central.sonatype.com/artifact/io.github.seonwkim/spring-boot-starter-actor) | [spring-boot-starter-actor_3](https://central.sonatype.com/artifact/io.github.seonwkim/spring-boot-starter-actor_3)
### Enable Actor Support
Add `@EnableActorSupport` to your application:
```java
@SpringBootApplication
@EnableActorSupport
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
```
### Create Your First Actor
Create an actor by implementing `SpringActor`:
```java
@Component
public class GreeterActor implements SpringActor {
public interface Command {
}
public static class Greet extends AskCommand implements Command {
public final String name;
public Greet(String name) {
this.name = name;
}
}
@Override
public SpringActorBehavior create(SpringActorContext actorContext) {
return SpringActorBehavior.builder(Command.class, actorContext)
.onMessage(Greet.class, (ctx, msg) -> {
msg.reply("Hello, " + msg.name + "!");
return Behaviors.same();
})
.build();
}
}
```
### Use Actors in Your Services
Inject `SpringActorSystem` and interact with actors:
```java
@Service
public class GreeterService {
private final SpringActorSystem actorSystem;
public GreeterService(SpringActorSystem actorSystem) {
this.actorSystem = actorSystem;
}
public CompletionStage greet(String name) {
return actorSystem.getOrSpawn(GreeterActor.class, "greeter")
.thenCompose(actor -> actor
.ask(new GreeterActor.Greet(name))
.withTimeout(Duration.ofSeconds(5))
.execute()
);
}
}
```
## Core Concepts
### Actor Lifecycle Management
**Spawn a New Actor:**
```java
// Create and start a new actor
CompletionStage> actorHandle = actorSystem
.actor(MyActor.class)
.withId("my-actor-1")
.withTimeout(Duration.ofSeconds(5)) // Optional
.spawn();
```
**Get Existing Actor:**
```java
// Get reference to existing actor (returns null if not found)
CompletionStage> actorHandle = actorSystem
.get(MyActor.class, "my-actor-1");
```
**Get or Spawn (Recommended):**
```java
// Automatically gets existing or spawns new actor
CompletionStage> actorHandle = actorSystem
.getOrSpawn(MyActor.class, "my-actor-1");
```
**Check if Actor Exists:**
```java
CompletionStage exists = actorSystem
.exists(MyActor.class, "my-actor-1");
```
**Stop an Actor:**
```java
actorHandle.thenAccept(actor -> actor.stop());
```
### Communication Patterns
**Fire-and-forget (tell):**
```java
actor.tell(new ProcessOrder("order-123"));
```
**Request-response (ask):**
```java
CompletionStage response = actor
.ask(new GetValue())
.withTimeout(Duration.ofSeconds(5))
.execute();
```
**With error handling:**
```java
CompletionStage response = actor
.ask(new GetValue())
.withTimeout(Duration.ofSeconds(5))
.onTimeout(() -> "default-value")
.execute();
```
### Spring Dependency Injection
Actors are Spring components with full DI support:
```java
@Component
public class OrderActor implements SpringActor {
private final OrderRepository orderRepository;
public OrderActor(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public interface Command {
}
public record ProcessOrder(String orderId) implements Command {
}
@Override
public SpringActorBehavior create(SpringActorContext actorContext) {
return SpringActorBehavior.builder(Command.class, actorContext)
.onMessage(ProcessOrder.class, (ctx, msg) -> {
Order order = orderRepository.findById(msg.orderId);
// Process order...
return Behaviors.same();
})
.build();
}
}
```
## Configuration
### Local Mode (Default)
```yaml
spring:
actor:
pekko:
actor:
provider: local
```
### Cluster Mode
```yaml
spring:
actor:
pekko:
actor:
provider: cluster
remote:
artery:
canonical:
hostname: "127.0.0.1"
port: 2551
cluster:
seed-nodes:
- "pekko://MyActorSystem@127.0.0.1:2551"
```
## Advanced Features
### Sharded Actors (Cluster Mode)
For distributed systems, use sharded actors that are automatically distributed across cluster nodes:
**Define a Sharded Actor:**
```java
@Component
public class UserSessionActor implements SpringShardedActor {
public static final EntityTypeKey TYPE_KEY =
EntityTypeKey.create(Command.class, "UserSession");
public interface Command extends JsonSerializable {
}
public record UpdateActivity(String activity) implements Command {
}
public static class GetActivity extends AskCommand implements Command {
public GetActivity() {
}
}
@Override
public EntityTypeKey typeKey() {
return TYPE_KEY;
}
@Override
public SpringShardedActorBehavior create(SpringShardedActorContext ctx) {
return SpringShardedActorBehavior.builder(Command.class, ctx)
.withState(entityCtx -> new UserSessionBehavior(ctx.getEntityId()))
.onMessage(UpdateActivity.class, UserSessionBehavior::onUpdateActivity)
.onMessage(GetActivity.class, UserSessionBehavior::onGetActivity)
.build();
}
private static class UserSessionBehavior {
private final String userId;
private String activity = "idle";
UserSessionBehavior(String userId) {
this.userId = userId;
}
Behavior onUpdateActivity(UpdateActivity msg) {
this.activity = msg.activity;
return Behaviors.same();
}
Behavior onGetActivity(GetActivity msg) {
msg.reply(activity);
return Behaviors.same();
}
}
}
```
**Using Sharded Actors:**
```java
// Get reference (entity created on-demand)
SpringShardedActorHandle actor = actorSystem
.sharded(UserSessionActor.class)
.withId("user-123")
.get();
// Fire-and-forget
actor.tell(new UpdateActivity("logged-in"));
// Request-response
CompletionStage activity = actor
.ask(new GetActivity())
.withTimeout(Duration.ofSeconds(5))
.execute();
```
**Key Differences from Regular Actors:**
- Created automatically when first message arrives (no `spawn()` needed)
- Always available, even if not currently running
- Automatically distributed across cluster nodes
- Passivated after idle timeout (configurable)
- Use `get()` to obtain reference (not `spawn()`)
### Supervision and Fault Tolerance
Build self-healing systems with supervision strategies:
**Available Strategies:**
```java
// Restart on failure (default)
SupervisorStrategy.restart()
// Restart with limit (e.g., 3 times within 1 minute)
SupervisorStrategy.restart().withLimit(3, Duration.ofMinutes(1))
// Stop on failure
SupervisorStrategy.stop()
// Resume and ignore failure
SupervisorStrategy.resume()
```
**Spawn Actors with Supervision:**
```java
// Top-level actor
actorSystem.actor(WorkerActor.class)
.withId("worker-1")
.withSupervisionStrategy(SupervisorStrategy.restart().withLimit(3, Duration.ofMinutes(1)))
.spawn();
```
**Spawn Child Actors with Supervision:**
```java
@Component
public class SupervisorActor implements SpringActor {
public interface Command {
}
@Override
public SpringActorBehavior create(SpringActorContext actorContext) {
return SpringActorBehavior.builder(Command.class, actorContext)
.onMessage(DelegateWork.class, (ctx, msg) -> {
SpringActorHandle self = new SpringActorHandle<>(ctx.getSystem().scheduler(), ctx.getSelf());
// Spawn supervised child
self.child(WorkerActor.class)
.withId("worker-1")
.withSupervisionStrategy(SupervisorStrategy.restart())
.spawn();
return Behaviors.same();
})
.build();
}
}
```
**Child Actor Operations:**
```java
// Spawn new child
CompletionStage> child = parentRef
.child(ChildActor.class)
.withId("child-1")
.spawn();
// Get existing child
CompletionStage> existing = parentRef
.child(ChildActor.class)
.withId("child-1")
.get();
// Get or spawn (recommended)
CompletionStage> childRef = parentRef
.child(ChildActor.class)
.withId("child-1")
.getOrSpawn();
```
## Running Examples
### Chat Application (Distributed)
Run a distributed chat application across multiple nodes:
```bash
# Start 3-node cluster on ports 8080, 8081, 8082
$ sh cluster-start.sh chat io.github.seonwkim.example.SpringPekkoApplication 8080 2551 3
# run frontend
$ cd example/chat/frontend
$ npm run dev
# Stop cluster
$ sh cluster-stop.sh
```
## Monitoring
WIP
## Documentation
Full
documentation: [https://seonwkim.github.io/spring-boot-starter-actor/](https://seonwkim.github.io/spring-boot-starter-actor/)
## Community & Support
Join our community to ask questions, share ideas, and get help:
- **Discord**: [Join our Discord server](https://discord.com/channels/1439734161614045205/1439734162100846655) -
Real-time chat with the community
- **Issues**: [GitHub Issues](https://github.com/seonwkim/spring-boot-starter-actor/issues) - Bug reports and feature
requests
- **Discussions**: [GitHub Discussions](https://github.com/seonwkim/spring-boot-starter-actor/discussions) - Q&A and
general discussions
## Contributing
Contributions welcome! Please:
1. Create an issue describing your contribution
2. Open a PR with clear explanation
3. Run `./gradlew spotlessApply` for formatting
4. Ensure tests pass
See [roadmap/ROADMAP.md](roadmap/ROADMAP.md) for the implementation roadmap.
## License
This project is licensed under the Apache License 2.0.