mirror of https://github.com/dapr/java-sdk.git
Refactoring actor example. (#182)
Co-authored-by: Young Bu Park <youngp@microsoft.com>
This commit is contained in:
parent
838224f18a
commit
082c4a46fc
|
@ -11,70 +11,72 @@ import io.dapr.actors.client.ActorProxyBuilder;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client for Actor runtime.
|
* Client for Actor runtime to invoke actor methods.
|
||||||
* 1. Build and install jars:
|
* 1. Build and install jars:
|
||||||
* mvn clean install
|
* mvn clean install
|
||||||
* 2. Run the client:
|
* 2. Run the client:
|
||||||
* dapr run --app-id demoactorclient --port 3006 -- mvn exec:java \
|
* dapr run --app-id demoactorclient --port 3006 -- mvn exec:java \
|
||||||
* -pl=examples -Dexec.mainClass=io.dapr.examples.actors.http.DemoActorClient
|
* -pl=examples -Dexec.mainClass=io.dapr.examples.actors.http.DemoActorClient
|
||||||
*/
|
*/
|
||||||
public class DemoActorClient {
|
public class DemoActorClient {
|
||||||
|
|
||||||
private static final int NUM_ACTORS = 3;
|
private static final int NUM_ACTORS = 3;
|
||||||
|
|
||||||
private static final int NUM_MESSAGES_PER_ACTOR = 10;
|
|
||||||
|
|
||||||
private static final String METHOD_NAME = "say";
|
|
||||||
|
|
||||||
private static final ExecutorService POOL = Executors.newFixedThreadPool(NUM_ACTORS);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main method.
|
* The main method.
|
||||||
* @param args Unused.
|
* @param args Input arguments (unused).
|
||||||
* @throws Exception An Exception.
|
* @throws InterruptedException If program has been interrupted.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws InterruptedException {
|
||||||
ActorProxyBuilder builder = new ActorProxyBuilder("DemoActor");
|
ActorProxyBuilder builder = new ActorProxyBuilder("DemoActor");
|
||||||
|
|
||||||
List<CompletableFuture<Void>> futures = new ArrayList<>(NUM_ACTORS);
|
List<Thread> threads = new ArrayList<>(NUM_ACTORS);
|
||||||
|
|
||||||
|
// Creates multiple actors.
|
||||||
for (int i = 0; i < NUM_ACTORS; i++) {
|
for (int i = 0; i < NUM_ACTORS; i++) {
|
||||||
ActorProxy actor = builder.build(ActorId.createRandom());
|
ActorProxy actor = builder.build(ActorId.createRandom());
|
||||||
futures.add(callActorNTimes(actor));
|
|
||||||
|
// Start a thread per actor.
|
||||||
|
Thread thread = new Thread(() -> callActorForever(actor));
|
||||||
|
thread.start();
|
||||||
|
threads.add(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
futures.forEach(CompletableFuture::join);
|
// Waits for threads to finish.
|
||||||
POOL.shutdown();
|
for (Thread thread : threads) {
|
||||||
POOL.awaitTermination(1, TimeUnit.MINUTES);
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println("Done.");
|
System.out.println("Done.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final CompletableFuture<Void> callActorNTimes(ActorProxy actor) {
|
/**
|
||||||
return CompletableFuture.runAsync(() -> {
|
* Makes multiple method calls into actor until interrupted.
|
||||||
actor.invokeActorMethod("registerReminder").block();
|
* @param actor Actor to be invoked.
|
||||||
for (int i = 0; i < NUM_MESSAGES_PER_ACTOR; i++) {
|
*/
|
||||||
actor.invokeActorMethod("incrementAndGet", 1).block();
|
private static final void callActorForever(ActorProxy actor) {
|
||||||
String result = actor.invokeActorMethod(METHOD_NAME,
|
// First, register reminder.
|
||||||
String.format("Actor %s said message #%d", actor.getActorId().toString(), i), String.class).block();
|
actor.invokeActorMethod("registerReminder").block();
|
||||||
System.out.println(String.format("Actor %s got a reply: %s", actor.getActorId().toString(), result));
|
|
||||||
try {
|
|
||||||
Thread.sleep((long) (1000 * Math.random()));
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(
|
// Now, we run until thread is interrupted.
|
||||||
"Messages sent: " + actor.invokeActorMethod("incrementAndGet", 0, int.class).block());
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
}, POOL);
|
// Invoke actor method to increment counter by 1, then build message.
|
||||||
|
int messageNumber = actor.invokeActorMethod("incrementAndGet", 1, int.class).block();
|
||||||
|
String message = String.format("Actor %s said message #%d", actor.getActorId().toString(), messageNumber);
|
||||||
|
|
||||||
|
// Invoke the 'say' method in actor.
|
||||||
|
String result = actor.invokeActorMethod("say", message, String.class).block();
|
||||||
|
System.out.println(String.format("Actor %s got a reply: %s", actor.getActorId().toString(), result));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Waits for up to 1 second.
|
||||||
|
Thread.sleep((long) Math.rint(1000));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// We have been interrupted, so we set the interrupted flag to exit gracefully.
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,9 @@ public class DemoActorImpl extends AbstractActor implements DemoActor, Remindabl
|
||||||
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the constructor of an actor implementation.
|
* This is the constructor of an actor implementation, while also registering a timer.
|
||||||
* @param runtimeContext The runtime context object which contains objects such as the state provider.
|
* @param runtimeContext The runtime context object which contains objects such as the state provider.
|
||||||
* @param id The id of this actor.
|
* @param id The id of this actor.
|
||||||
*/
|
*/
|
||||||
public DemoActorImpl(ActorRuntimeContext runtimeContext, ActorId id) {
|
public DemoActorImpl(ActorRuntimeContext runtimeContext, ActorId id) {
|
||||||
super(runtimeContext, id);
|
super(runtimeContext, id);
|
||||||
|
@ -46,6 +46,9 @@ public class DemoActorImpl extends AbstractActor implements DemoActor, Remindabl
|
||||||
Duration.ofSeconds(1)).block();
|
Duration.ofSeconds(1)).block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a reminder.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void registerReminder() {
|
public void registerReminder() {
|
||||||
super.registerReminder(
|
super.registerReminder(
|
||||||
|
@ -55,6 +58,11 @@ public class DemoActorImpl extends AbstractActor implements DemoActor, Remindabl
|
||||||
Duration.ofSeconds(2)).block();
|
Duration.ofSeconds(2)).block();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a message and appends the timestamp.
|
||||||
|
* @param something Something to be said.
|
||||||
|
* @return What was said appended with timestamp.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String say(String something) {
|
public String say(String something) {
|
||||||
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||||
|
@ -71,6 +79,23 @@ public class DemoActorImpl extends AbstractActor implements DemoActor, Remindabl
|
||||||
return utcNowAsString;
|
return utcNowAsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments a persistent counter, saves and returns its updated value.
|
||||||
|
* Example of method implemented with Reactor's Mono class.
|
||||||
|
* This method could be rewritten with blocking calls in Mono, using block() method:
|
||||||
|
*
|
||||||
|
* <p>public int incrementAndGet(int delta) {
|
||||||
|
* int counter = 0;
|
||||||
|
* if (super.getActorStateManager().contains("counter").block()) {
|
||||||
|
* counter = super.getActorStateManager().get("counter", int.class).block();
|
||||||
|
* }
|
||||||
|
* counter = counter + 1;
|
||||||
|
* super.getActorStateManager().set("counter", counter).block();
|
||||||
|
* return counter;
|
||||||
|
* }</p>
|
||||||
|
* @param delta Amount to be added to counter.
|
||||||
|
* @return Mono response for the incremented value.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<Integer> incrementAndGet(int delta) {
|
public Mono<Integer> incrementAndGet(int delta) {
|
||||||
return super.getActorStateManager().contains("counter")
|
return super.getActorStateManager().contains("counter")
|
||||||
|
@ -79,6 +104,10 @@ public class DemoActorImpl extends AbstractActor implements DemoActor, Remindabl
|
||||||
.flatMap(c -> super.getActorStateManager().set("counter", c).thenReturn(c));
|
.flatMap(c -> super.getActorStateManager().set("counter", c).thenReturn(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method invoked by timer.
|
||||||
|
* @param message Message to be printed.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void clock(String message) {
|
public void clock(String message) {
|
||||||
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||||
|
@ -90,20 +119,34 @@ public class DemoActorImpl extends AbstractActor implements DemoActor, Remindabl
|
||||||
+ (message == null ? "" : message + " @ " + utcNowAsString));
|
+ (message == null ? "" : message + " @ " + utcNowAsString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method used to determine reminder's state type.
|
||||||
|
* @return Class for reminder's state.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Class<Integer> getStateType() {
|
public Class<Integer> getStateType() {
|
||||||
return Integer.class;
|
return Integer.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method used be invoked for a reminder.
|
||||||
|
* @param reminderName The name of reminder provided during registration.
|
||||||
|
* @param state The user state provided during registration.
|
||||||
|
* @param dueTime The invocation due time provided during registration.
|
||||||
|
* @param period The invocation period provided during registration.
|
||||||
|
* @return Mono result.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> receiveReminder(String reminderName, Integer state, Duration dueTime, Duration period) {
|
public Mono<Void> receiveReminder(String reminderName, Integer state, Duration dueTime, Duration period) {
|
||||||
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
return Mono.fromRunnable(() -> {
|
||||||
String utcNowAsString = DATE_FORMAT.format(utcNow.getTime());
|
Calendar utcNow = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
||||||
|
String utcNowAsString = DATE_FORMAT.format(utcNow.getTime());
|
||||||
|
|
||||||
// Handles the request by printing message.
|
String message = String.format("Server reminded actor %s of: %s for %d @ %s",
|
||||||
System.out.println(String.format(
|
this.getId(), reminderName, state, utcNowAsString);
|
||||||
"Server reminded actor %s of: %s for %d @ %s",
|
|
||||||
this.getId(), reminderName, state, utcNowAsString));
|
// Handles the request by printing message.
|
||||||
return Mono.empty();
|
System.out.println(message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
* dapr run --app-id demoactorservice --app-port 3000 --port 3005 \
|
* dapr run --app-id demoactorservice --app-port 3000 --port 3005 \
|
||||||
* -- mvn exec:java -pl=examples -Dexec.mainClass=io.dapr.examples.actors.http.DemoActorService -Dexec.args="-p 3000"
|
* -- mvn exec:java -pl=examples -Dexec.mainClass=io.dapr.examples.actors.http.DemoActorService -Dexec.args="-p 3000"
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
|
||||||
public class DemoActorService {
|
public class DemoActorService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,13 +41,9 @@ public class DemoActorService {
|
||||||
int port = Integer.parseInt(cmd.getOptionValue("port"));
|
int port = Integer.parseInt(cmd.getOptionValue("port"));
|
||||||
|
|
||||||
// Register the Actor class.
|
// Register the Actor class.
|
||||||
ActorRuntime.getInstance().registerActor(
|
ActorRuntime.getInstance().registerActor(DemoActorImpl.class);
|
||||||
DemoActorImpl.class, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
|
||||||
|
|
||||||
// Start Dapr's callback endpoint.
|
// Start Dapr's callback endpoint.
|
||||||
DaprApplication.start(port);
|
DaprApplication.start(port);
|
||||||
|
|
||||||
// Start application's endpoint.
|
|
||||||
SpringApplication.run(DemoActorService.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Microsoft Corporation.
|
|
||||||
* Licensed under the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.dapr.examples.actors.http;
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
public class HelloController {
|
|
||||||
@RequestMapping("/")
|
|
||||||
public String index() {
|
|
||||||
return "Greetings from your Spring Boot Application!";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -44,24 +44,65 @@ public class DemoActorService {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
///...
|
///...
|
||||||
// Register the Actor class.
|
// Register the Actor class.
|
||||||
ActorRuntime.getInstance().registerActor(
|
ActorRuntime.getInstance().registerActor(DemoActorImpl.class);
|
||||||
DemoActorImpl.class, new DefaultObjectSerializer(), new DefaultObjectSerializer());
|
|
||||||
|
|
||||||
// Start Dapr's callback endpoint.
|
// Start Dapr's callback endpoint.
|
||||||
DaprApplication.start(port);
|
DaprApplication.start(port);
|
||||||
|
|
||||||
// Start application's endpoint.
|
|
||||||
SpringApplication.run(DemoActorService.class);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
This application uses `ActorRuntime.getInstance().registerActor()` in order to register `DemoActorImpl` as an actor in the Dapr Actor runtime. Notice that this call passes in two serializer implementations: one is for Dapr's sent and received object and the other is for objects to be persisted.
|
This application uses `ActorRuntime.getInstance().registerActor()` in order to register `DemoActorImpl` as an actor in the Dapr Actor runtime. Internally, it is using `DefaultObjectSerializer` for two properties: `objectSerializer` is for Dapr's sent and received objects, and `stateSerializer` is for objects to be persisted.
|
||||||
|
|
||||||
|
|
||||||
`DaprApplication.start()` method will run the Spring Boot [DaprApplication](../../../springboot/DaprApplication.java), which registers the Dapr Spring Boot controller [DaprController](../../springboot/DaprController.java). This controller contains all Actor methods implemented as endpoints. The Dapr's sidecar will call into the controller. At the end of the main method, this class uses `SpringApplication.run()` to boostrap itself a an Spring application.
|
`DaprApplication.start()` method will run the Spring Boot [DaprApplication](../../../springboot/DaprApplication.java), which registers the Dapr Spring Boot controller [DaprController](../../springboot/DaprController.java). This controller contains all Actor methods implemented as endpoints. The Dapr's sidecar will call into the controller.
|
||||||
|
|
||||||
Execute the follow script in order to run the DemoActorService:
|
See [DemoActorImpl](DemoActorImpl.java) for details on the implementation of an actor:
|
||||||
|
```java
|
||||||
|
@ActorType(name = "DemoActor")
|
||||||
|
public class DemoActorImpl extends AbstractActor implements DemoActor, Remindable<Integer> {
|
||||||
|
//...
|
||||||
|
|
||||||
|
public DemoActorImpl(ActorRuntimeContext runtimeContext, ActorId id) {
|
||||||
|
super(runtimeContext, id);
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerReminder() {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String say(String something) {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Integer> incrementAndGet(int delta) {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clock(String message) {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<Integer> getStateType() {
|
||||||
|
return Integer.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> receiveReminder(String reminderName, Integer state, Duration dueTime, Duration period) {
|
||||||
|
//...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
An actor inherits from `AbstractActor` and implements the constructor to pass through `ActorRuntimeContext` and `ActorId`. By default, the actor's name will be the same as the class' name. Optionally, it can be annotated with `ActorType` and override the actor's name. The actor's methods can be synchronously or use [Project Reactor's Mono](https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html) return type. Finally, state management is done via methods in `super.getActorStateManager()`.
|
||||||
|
|
||||||
|
|
||||||
|
Now, execute the following script in order to run DemoActorService:
|
||||||
```sh
|
```sh
|
||||||
cd to [repo-root]
|
cd to [repo-root]
|
||||||
dapr run --app-id demoactorservice --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.actors.http.DemoActorService -D exec.args="-p 3000"
|
dapr run --app-id demoactorservice --app-port 3000 --port 3005 -- mvn exec:java -pl=examples -D exec.mainClass=io.dapr.examples.actors.http.DemoActorService -D exec.args="-p 3000"
|
||||||
|
@ -77,39 +118,47 @@ The `DemoActorClient.java` file contains the `DemoActorClient` class. See the co
|
||||||
public class DemoActorClient {
|
public class DemoActorClient {
|
||||||
|
|
||||||
private static final int NUM_ACTORS = 3;
|
private static final int NUM_ACTORS = 3;
|
||||||
private static final int NUM_MESSAGES_PER_ACTOR = 10;
|
|
||||||
|
|
||||||
private static final ExecutorService POOL = Executors.newFixedThreadPool(NUM_ACTORS);
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
///...
|
///...
|
||||||
for (int i = 0; i < NUM_ACTORS; i++) {
|
for (int i = 0; i < NUM_ACTORS; i++) {
|
||||||
ActorProxy actor = builder.build(ActorId.createRandom());
|
ActorProxy actor = builder.build(ActorId.createRandom());
|
||||||
futures.add(callActorNTimes(actor));
|
|
||||||
|
// Start a thread per actor.
|
||||||
|
Thread thread = new Thread(() -> callActorForever(actor));
|
||||||
|
thread.start();
|
||||||
|
threads.add(thread);
|
||||||
}
|
}
|
||||||
///...
|
///...
|
||||||
|
|
||||||
private static final CompletableFuture<Void> callActorNTimes(ActorProxy actor) {
|
|
||||||
return CompletableFuture.runAsync(() -> {
|
|
||||||
actor.invokeActorMethod("registerReminder").block();
|
|
||||||
for (int i = 0; i < NUM_MESSAGES_PER_ACTOR; i++) {
|
|
||||||
//Invoking the "incrementAndGet" method:
|
|
||||||
actor.invokeActorMethod("incrementAndGet", 1).block();
|
|
||||||
//Invoking "say" method
|
|
||||||
String result = actor.invokeActorMethod("say",
|
|
||||||
String.format("Actor %s said message #%d", actor.getActorId().toString(), i), String.class).block();
|
|
||||||
System.out.println(String.format("Actor %s got a reply: %s", actor.getActorId().toString(), result));
|
|
||||||
///...
|
|
||||||
}
|
|
||||||
System.out.println(
|
|
||||||
"Messages sent: " + actor.invokeActorMethod("incrementAndGet", 0, int.class).block());
|
|
||||||
}, POOL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final void callActorForever(ActorProxy actor) {
|
||||||
|
// First, register reminder.
|
||||||
|
actor.invokeActorMethod("registerReminder").block();
|
||||||
|
|
||||||
|
// Now, we run until thread is interrupted.
|
||||||
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
|
// Invoke actor method to increment counter by 1, then build message.
|
||||||
|
int messageNumber = actor.invokeActorMethod("incrementAndGet", 1, int.class).block();
|
||||||
|
String message = String.format("Actor %s said message #%d", actor.getActorId().toString(), messageNumber);
|
||||||
|
|
||||||
|
// Invoke the 'say' method in actor.
|
||||||
|
String result = actor.invokeActorMethod("say", message, String.class).block();
|
||||||
|
System.out.println(String.format("Actor %s got a reply: %s", actor.getActorId().toString(), result));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Waits for up to 1 second.
|
||||||
|
Thread.sleep((long) Math.rint(1000));
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// We have been interrupted, so we set the interrupted flag to exit gracefully.
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
First, The client defines how many actors it is going to create, as well as how many invocation calls it will perform per actor. Then the main method declares a `ActorProxyBuilder` for the `DemoActor` class for creating `ActorProxy` instances, which are the actor representation provided by the SDK. The code executes the `callActorNTimes` private method once per actor. This method executes functionality for the DemoActor implementation using `actor.invokeActorMethod()` in the follow order: `registerReminder()` which sets the due time and period for the reminder, `incrementAndGet()` which increments a counter, persists it and sends it back as response, and finally `say` method wich will print a message containing the received string along with the formatted server time. See [DemoActorImpl](DemoActorImpl.java) for details on the implementation of these methods.
|
First, the client defines how many actors it is going to create. Then the main method declares a `ActorProxyBuilder` for the `DemoActor` class to create `ActorProxy` instances, which are the actor representation provided by the SDK. The code executes the `callActorForever` private method once per actor. This method triggers the DemoActor's implementation by using `actor.invokeActorMethod()`. Initially, it will invoke `registerReminder()`, which sets the due time and period for the reminder. Then, `incrementAndGet()` increments a counter, persists it and sends it back as response. Finally `say` method which will print a message containing the received string along with the formatted server time.
|
||||||
|
|
||||||
Use the follow command to execute the DemoActorClient:
|
Use the follow command to execute the DemoActorClient:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue