diff --git a/README.md b/README.md index 9d8c9f9..9250855 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,11 @@ And let's populate this file with the following content: syntax = "proto3"; package domain; -option java_package = "io.eigr.spawn.java.demo.domain"; +// Due to the dynamic nature of spawn we are required to define the java package +// as being the same as the protobuf package name. +option java_package = "domain"; +// Generating the java classes in multiple files is mandatory for the process to work correctly. +option java_multiple_files = true; message State { repeated string languages = 1; @@ -97,6 +101,10 @@ service JoeActor { } ``` +> **_NOTE:_** Due to the dynamic nature of spawn we are required to define the java package +> as being the same as the protobuf package name. Also generating the java classes in multiple files +> is mandatory for the process to work correctly. + We must compile this file using the protoc utility. In the root of the project type the following command: ```shell @@ -120,42 +128,42 @@ import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import io.eigr.spawn.api.actors.ActionBindings; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class JoeActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("JoeActor"), - channel("test.channel"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - if (context.getState().isPresent()) { - //Do something with previous state - } - - return Value.at() - .response(Reply.newBuilder() - .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) - .build()) - .state(updateState(msg.getLanguage())) - .reply(); - } - - private State updateState(String language) { - return State.newBuilder() - .addLanguages(language) - .build(); - } + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("JoeActor"), + channel("test.channel"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + if (context.getState().isPresent()) { + //Do something with previous state + } + + return Value.at() + .response(Reply.newBuilder() + .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) + .build()) + .state(updateState(msg.getLanguage())) + .reply(); + } + + private State updateState(String language) { + return State.newBuilder() + .addLanguages(language) + .build(); + } } ``` @@ -167,7 +175,7 @@ public final class JoeActor implements StatefulActor { package io.eigr.spawn.java.demo; import io.eigr.spawn.api.actors.StatefulActor; -import io.eigr.spawn.java.demo.domain.Actor.State; +import domain.State; public final class JoeActor implements StatefulActor { // ... @@ -175,7 +183,7 @@ public final class JoeActor implements StatefulActor { ``` The `JoeActor` class implements `StatefulActor` interface. `StatefulActor` is a generic interface provided by the Spawn API, -which takes a type parameter for the state. In this case, the state type is `io.eigr.spawn.java.demo.domain.Actor.State` +which takes a type parameter for the state. In this case, the state type is `domain.State` defined in above protobuf file. ***Configure Actor Behavior*** @@ -360,40 +368,41 @@ import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import io.eigr.spawn.api.actors.ActionBindings; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.action; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.name; -public final class JoeActor implements StatefulActor { - - private String defaultMessage; - - @Override - public ActorBehavior configure(BehaviorCtx context) { - defaultMessage = context.getInjector().getInstance(String.class); - return new NamedActorBehavior( - name("JoeActor"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - private Value setLanguage(ActorContext context, Request msg) { - return Value.at() - .response(Reply.newBuilder() - .setResponse(defaultMessage) - .build()) - .state(updateState("java")) - .reply(); - } +public final class JoeActor implements StatefulActor { - private State updateState(String language) { - return State.newBuilder() - .addLanguages(language) - .build(); - } + private String defaultMessage; + + @Override + public ActorBehavior configure(BehaviorCtx context) { + defaultMessage = context.getInjector().getInstance(String.class); + return new NamedActorBehavior( + name("JoeActor"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + return Value.at() + .response(Reply.newBuilder() + .setResponse(defaultMessage) + .build()) + .state(updateState("java")) + .reply(); + } + + private State updateState(String language) { + return State.newBuilder() + .addLanguages(language) + .build(); + } } ``` @@ -462,36 +471,36 @@ For this the developer just needs to make extend of the correct base interface. ```java package io.eigr.spawn.java.demo.actors; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatelessActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; +import domain.Reply; +import domain.Request; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.action; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.name; public final class StatelessNamedActor implements StatelessActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("StatelessNamedActor"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - return Value.at() - .response(Reply.newBuilder() - .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) - .build()) - .reply(); - } + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("StatelessNamedActor"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + return Value.at() + .response(Reply.newBuilder() + .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) + .build()) + .reply(); + } } ``` @@ -538,35 +547,35 @@ import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; import io.eigr.spawn.api.actors.workflows.Broadcast; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import io.eigr.spawn.api.actors.ActionBindings; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class LoopActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("LoopActor"), - channel("test.channel"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - return Value.at() - .flow(Broadcast.to("test.channel", "setLanguage", msg)) - .response(Reply.newBuilder() - .setResponse("Hello From Erlang") - .build()) - .state(updateState("erlang")) - .reply(); - } - - // ... + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("LoopActor"), + channel("test.channel"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + return Value.at() + .flow(Broadcast.to("test.channel", "setLanguage", msg)) + .response(Reply.newBuilder() + .setResponse("Hello From Erlang") + .build()) + .state(updateState("erlang")) + .reply(); + } + + // ... } ``` @@ -584,38 +593,38 @@ import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import io.eigr.spawn.api.actors.ActionBindings; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class JoeActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("JoeActor"), - channel("test.channel"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - ActorRef sideEffectReceiverActor = ctx.getSpawnSystem() - .createActorRef(ActorIdentity.of("spawn-system", "MikeFriendActor", "MikeParentActor")); - - return Value.at() - .flow(SideEffect.to(sideEffectReceiverActor, "setLanguage", msg)) - .response(Reply.newBuilder() - .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) - .build()) - .state(updateState(msg.getLanguage())) - .noReply(); - } - - // .... + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("JoeActor"), + channel("test.channel"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + ActorRef sideEffectReceiverActor = ctx.getSpawnSystem() + .createActorRef(ActorIdentity.of("spawn-system", "MikeFriendActor", "MikeParentActor")); + + return Value.at() + .flow(SideEffect.to(sideEffectReceiverActor, "setLanguage", msg)) + .response(Reply.newBuilder() + .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) + .build()) + .state(updateState(msg.getLanguage())) + .noReply(); + } + + // .... } ``` @@ -634,37 +643,37 @@ See an example: ```Java package io.eigr.spawn.java.demo.actors; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatefulActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class RoutingActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("RoutingActor"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - ActorRef forwardedActor = ctx.getSpawnSystem() - .createActorRef(ActorIdentity.of("spawn-system", "MikeFriendActor", "MikeActor")); - - return Value.at() - .flow(Forward.to(forwardedActor, "setLanguage")) - .noReply(); - } + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("RoutingActor"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + ActorRef forwardedActor = ctx.getSpawnSystem() + .createActorRef(ActorIdentity.of("spawn-system", "MikeFriendActor", "MikeActor")); + + return Value.at() + .flow(Forward.to(forwardedActor, "setLanguage")) + .noReply(); + } } ``` @@ -686,37 +695,37 @@ import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import io.eigr.spawn.api.actors.ActionBindings; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class PipeActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("PipeActor"), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - ActorRef pipeReceiverActor = ctx.getSpawnSystem() - .createActorRef(ActorIdentity.of("spawn-system", "JoeActor")); - - return Value.at() - .response(Reply.newBuilder() - .setResponse("Hello From Java") - .build()) - .flow(Pipe.to(pipeReceiverActor, "someAction")) - .state(updateState("java")) - .noReply(); - } - - // ... + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("PipeActor"), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + ActorRef pipeReceiverActor = ctx.getSpawnSystem() + .createActorRef(ActorIdentity.of("spawn-system", "JoeActor")); + + return Value.at() + .response(Reply.newBuilder() + .setResponse("Hello From Java") + .build()) + .flow(Pipe.to(pipeReceiverActor, "someAction")) + .state(updateState("java")) + .noReply(); + } + + // ... } ``` @@ -749,35 +758,35 @@ import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import io.eigr.spawn.api.actors.ActionBindings; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class JoeActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new NamedActorBehavior( - name("JoeActor"), - snapshot(1000), - deactivated(60000), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - return Value.at() - .response(Reply.newBuilder() - .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) - .build()) - .state(updateState(msg.getLanguage()), true) - .reply(); - } - - // ... + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new NamedActorBehavior( + name("JoeActor"), + snapshot(1000), + deactivated(60000), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + return Value.at() + .response(Reply.newBuilder() + .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) + .build()) + .state(updateState(msg.getLanguage()), true) + .reply(); + } + + // ... } ``` @@ -836,7 +845,8 @@ import io.eigr.spawn.api.ActorIdentity; import io.eigr.spawn.api.ActorRef; import io.eigr.spawn.api.TransportOpts; import io.eigr.spawn.api.exceptions.SpawnException; -import io.eigr.spawn.java.demo.domain.Domain; +import domain.Reply; +import domain.Request; public class App { public static void main(String[] args) throws SpawnException { @@ -876,41 +886,41 @@ name at runtime: ```java package io.eigr.spawn.test.actors; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatefulActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.UnNamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.demo.domain.Actor.Reply; -import io.eigr.spawn.java.demo.domain.Actor.Request; -import io.eigr.spawn.java.demo.domain.Actor.State; +import domain.Reply; +import domain.Request; +import domain.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; public final class MikeActor implements StatefulActor { - @Override - public ActorBehavior configure(BehaviorCtx context) { - return new UnNamedActorBehavior( - name("MikeActor"), - snapshot(1000), - deactivated(60000), - action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) - ); - } - - private Value setLanguage(ActorContext context, Request msg) { - return Value.at() - .response(Reply.newBuilder() - .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) - .build()) - .state(updateState(msg.getLanguage()), true) - .reply(); - } - - // ... + @Override + public ActorBehavior configure(BehaviorCtx context) { + return new UnNamedActorBehavior( + name("MikeActor"), + snapshot(1000), + deactivated(60000), + action("SetLanguage", ActionBindings.of(Request.class, this::setLanguage)) + ); + } + + private Value setLanguage(ActorContext context, Request msg) { + return Value.at() + .response(Reply.newBuilder() + .setResponse(String.format("Hi %s. Hello From Java", msg.getLanguage())) + .build()) + .state(updateState(msg.getLanguage()), true) + .reply(); + } + + // ... } ``` diff --git a/src/main/java/io/eigr/spawn/internal/ActionBindings.java b/src/main/java/io/eigr/spawn/api/actors/ActionBindings.java similarity index 89% rename from src/main/java/io/eigr/spawn/internal/ActionBindings.java rename to src/main/java/io/eigr/spawn/api/actors/ActionBindings.java index b2da5c1..11923dd 100644 --- a/src/main/java/io/eigr/spawn/internal/ActionBindings.java +++ b/src/main/java/io/eigr/spawn/api/actors/ActionBindings.java @@ -1,8 +1,7 @@ -package io.eigr.spawn.internal; +package io.eigr.spawn.api.actors; import com.google.protobuf.Message; -import io.eigr.spawn.api.actors.ActorContext; -import io.eigr.spawn.api.actors.Value; +import io.eigr.spawn.internal.ActionEmptyFunction; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; diff --git a/src/main/java/io/eigr/spawn/api/actors/behaviors/ActorBehavior.java b/src/main/java/io/eigr/spawn/api/actors/behaviors/ActorBehavior.java index 7d995bd..1a429eb 100644 --- a/src/main/java/io/eigr/spawn/api/actors/behaviors/ActorBehavior.java +++ b/src/main/java/io/eigr/spawn/api/actors/behaviors/ActorBehavior.java @@ -2,6 +2,7 @@ import com.google.protobuf.GeneratedMessage; import com.google.protobuf.Message; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.exceptions.ActorInvocationException; diff --git a/src/main/java/io/eigr/spawn/internal/Entity.java b/src/main/java/io/eigr/spawn/internal/Entity.java index 67bb828..f6719cd 100644 --- a/src/main/java/io/eigr/spawn/internal/Entity.java +++ b/src/main/java/io/eigr/spawn/internal/Entity.java @@ -55,7 +55,7 @@ public Entity( String actorName, Class actorType, ActorOuterClass.Kind kind, - Class stateType, + Class stateType, String actorBeanName, boolean stateful, long deactivateTimeout, @@ -352,7 +352,7 @@ public ActorOuterClass.Kind getKind() { return kind; } - public Class getStateType() { + public Class getStateType() { return stateType; } diff --git a/src/main/java/io/eigr/spawn/internal/transport/server/ActorServiceHandler.java b/src/main/java/io/eigr/spawn/internal/transport/server/ActorServiceHandler.java index 1907a60..8281931 100644 --- a/src/main/java/io/eigr/spawn/internal/transport/server/ActorServiceHandler.java +++ b/src/main/java/io/eigr/spawn/internal/transport/server/ActorServiceHandler.java @@ -2,9 +2,7 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import com.google.protobuf.Any; -import com.google.protobuf.GeneratedMessage; -import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.*; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import io.eigr.functions.protocol.Protocol; @@ -209,13 +207,16 @@ private Entity.EntityMethod getEntityMethod(String commandName, Entity entity) t * @return the {@link ActorContext} instance * @throws InvalidProtocolBufferException if the state cannot be unpacked */ - private ActorContext createActorContext(Protocol.Context context, Entity entity) throws InvalidProtocolBufferException { - if (context.hasState()) { + private ActorContext createActorContext(Protocol.Context context, Entity entity) throws InvalidProtocolBufferException, ClassNotFoundException { + if (context.hasState() && entity.isStateful()) { Any anyCtxState = context.getState(); log.debug("[{}] trying to get the state of the Actor {}. Parse Any type {} from State type {}", system, entity.getActorName(), anyCtxState, entity.getStateType().getSimpleName()); - Object state = anyCtxState.unpack(entity.getStateType()); + String typeUrl = anyCtxState.getTypeUrl(); + String typeName = typeUrl.substring(typeUrl.lastIndexOf('/') + 1); + Class protoClass = Class.forName(typeName); + Object state = anyCtxState.unpack(protoClass); return new ActorContext(spawn, state); } else { return new ActorContext(spawn); diff --git a/src/test/java/io/eigr/spawn/AbstractContainerBaseTest.java b/src/test/java/io/eigr/spawn/test/AbstractContainerBaseTest.java similarity index 99% rename from src/test/java/io/eigr/spawn/AbstractContainerBaseTest.java rename to src/test/java/io/eigr/spawn/test/AbstractContainerBaseTest.java index 24a2ac7..38ada0d 100644 --- a/src/test/java/io/eigr/spawn/AbstractContainerBaseTest.java +++ b/src/test/java/io/eigr/spawn/test/AbstractContainerBaseTest.java @@ -1,4 +1,4 @@ -package io.eigr.spawn; +package io.eigr.spawn.test; import io.eigr.spawn.api.Spawn; import io.eigr.spawn.api.TransportOpts; diff --git a/src/test/java/io/eigr/spawn/test/ProtobufSerializationTest.java b/src/test/java/io/eigr/spawn/test/ProtobufSerializationTest.java new file mode 100644 index 0000000..9ba9304 --- /dev/null +++ b/src/test/java/io/eigr/spawn/test/ProtobufSerializationTest.java @@ -0,0 +1,28 @@ +package io.eigr.spawn.test; + +import com.google.protobuf.Any; +import com.google.protobuf.InvalidProtocolBufferException; +import domain.actors.State; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class ProtobufSerializationTest { + private static final Logger log = LoggerFactory.getLogger(ProtobufSerializationTest.class); + + @Test + public void testAnyUnpack() throws InvalidProtocolBufferException, ClassNotFoundException { + State stateActor = State.newBuilder().buildPartial(); + + Any anyCtxState = Any.pack(stateActor); + + String typeUrl = anyCtxState.getTypeUrl(); + String typeName = typeUrl.substring(typeUrl.lastIndexOf('/') + 1); + + Class protoClass = Class.forName(typeName); + stateActor = (State) anyCtxState.unpack(protoClass); + assertNotNull(stateActor); + } +} diff --git a/src/test/java/io/eigr/spawn/SpawnTest.java b/src/test/java/io/eigr/spawn/test/SpawnTest.java similarity index 76% rename from src/test/java/io/eigr/spawn/SpawnTest.java rename to src/test/java/io/eigr/spawn/test/SpawnTest.java index f7d0c7d..fdbe729 100644 --- a/src/test/java/io/eigr/spawn/SpawnTest.java +++ b/src/test/java/io/eigr/spawn/test/SpawnTest.java @@ -1,10 +1,11 @@ -package io.eigr.spawn; +package io.eigr.spawn.test; +import domain.actors.Reply; +import domain.actors.Request; import io.eigr.spawn.api.ActorIdentity; import io.eigr.spawn.api.ActorRef; import io.eigr.spawn.api.exceptions.ActorCreationException; import io.eigr.spawn.api.exceptions.ActorInvocationException; -import io.eigr.spawn.java.test.domain.Actor; import io.eigr.spawn.test.actors.JoeActor; import io.eigr.spawn.test.actors.StatelessNamedActor; import io.eigr.spawn.test.actors.UnNamedActor; @@ -25,15 +26,15 @@ void testNamedInvocation() throws ActorCreationException, ActorInvocationExcepti Assertions.assertEquals(type, JoeActor.class); Assertions.assertNotNull(joeActor); - Actor.Request msg = Actor.Request.newBuilder() + Request msg = Request.newBuilder() .setLanguage("Erlang") .build(); - Optional maybeReply = - joeActor.invoke("SetLanguage", msg, Actor.Reply.class); + Optional maybeReply = + joeActor.invoke("SetLanguage", msg, Reply.class); if (maybeReply.isPresent()) { - Actor.Reply reply = maybeReply.get(); + Reply reply = maybeReply.get(); Assertions.assertNotNull(reply); Assertions.assertEquals("Hi Erlang. Hello From Java", reply.getResponse()); } @@ -49,15 +50,15 @@ void testUnNamedInvocation() throws ActorCreationException, ActorInvocationExcep Assertions.assertEquals(type, UnNamedActor.class); Assertions.assertNotNull(unNamedJoeActor); - Actor.Request msg = Actor.Request.newBuilder() + Request msg = Request.newBuilder() .setLanguage("Erlang") .build(); - Optional maybeReply = - unNamedJoeActor.invoke("SetLanguage", msg, Actor.Reply.class); + Optional maybeReply = + unNamedJoeActor.invoke("SetLanguage", msg, Reply.class); if (maybeReply.isPresent()) { - Actor.Reply reply = maybeReply.get(); + Reply reply = maybeReply.get(); Assertions.assertNotNull(reply); Assertions.assertEquals("Hi Erlang. Hello From Java", reply.getResponse()); } @@ -73,15 +74,15 @@ void testStatelessInvocation() throws ActorCreationException, ActorInvocationExc Assertions.assertEquals(type, StatelessNamedActor.class); Assertions.assertNotNull(statelessNamedActor); - Actor.Request msg = Actor.Request.newBuilder() + Request msg = Request.newBuilder() .setLanguage("Elixir") .build(); - Optional maybeReply = - statelessNamedActor.invoke("SetLanguage", msg, Actor.Reply.class); + Optional maybeReply = + statelessNamedActor.invoke("SetLanguage", msg, Reply.class); if (maybeReply.isPresent()) { - Actor.Reply reply = maybeReply.get(); + Reply reply = maybeReply.get(); Assertions.assertNotNull(reply); Assertions.assertEquals("Hi Elixir. Hello From Java", reply.getResponse()); } diff --git a/src/test/java/io/eigr/spawn/WorkflowTest.java b/src/test/java/io/eigr/spawn/test/WorkflowTest.java similarity index 91% rename from src/test/java/io/eigr/spawn/WorkflowTest.java rename to src/test/java/io/eigr/spawn/test/WorkflowTest.java index 3bbd2e4..9e88258 100644 --- a/src/test/java/io/eigr/spawn/WorkflowTest.java +++ b/src/test/java/io/eigr/spawn/test/WorkflowTest.java @@ -1,5 +1,6 @@ -package io.eigr.spawn; +package io.eigr.spawn.test; +import domain.actors.Request; import io.eigr.functions.protocol.Protocol; import io.eigr.spawn.api.ActorIdentity; import io.eigr.spawn.api.ActorRef; @@ -8,7 +9,6 @@ import io.eigr.spawn.api.actors.workflows.Pipe; import io.eigr.spawn.api.actors.workflows.SideEffect; import io.eigr.spawn.api.exceptions.SpawnException; -import io.eigr.spawn.java.test.domain.Actor; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -25,7 +25,7 @@ public void before() throws SpawnException { @Test void testBroadcastBuilder() { - Broadcast broadcast = Broadcast.to("test.channel", "hi", Actor.Request.getDefaultInstance()); + Broadcast broadcast = Broadcast.to("test.channel", "hi", Request.getDefaultInstance()); final Protocol.Broadcast protocolBroadcast = broadcast.build(); Assertions.assertEquals("test.channel", protocolBroadcast.getChannelGroup()); Assertions.assertNotNull(protocolBroadcast.getValue()); @@ -49,7 +49,7 @@ void testPipeBuilder() throws Exception { @Test void testSideEffectBuilder() throws Exception { - SideEffect effect = SideEffect.to(joeActorRef, "hi", Actor.Request.getDefaultInstance()); + SideEffect effect = SideEffect.to(joeActorRef, "hi", Request.getDefaultInstance()); final Protocol.SideEffect protocolSideEffect = effect.build(); Protocol.InvocationRequest request = protocolSideEffect.getRequest(); Assertions.assertNotNull(request); diff --git a/src/test/java/io/eigr/spawn/test/actors/ActorWithConstructor.java b/src/test/java/io/eigr/spawn/test/actors/ActorWithConstructor.java index 319a586..442d8bd 100644 --- a/src/test/java/io/eigr/spawn/test/actors/ActorWithConstructor.java +++ b/src/test/java/io/eigr/spawn/test/actors/ActorWithConstructor.java @@ -1,15 +1,15 @@ package io.eigr.spawn.test.actors; +import domain.actors.Reply; +import domain.actors.Request; +import domain.actors.State; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatefulActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.test.domain.Actor.Reply; -import io.eigr.spawn.java.test.domain.Actor.Request; -import io.eigr.spawn.java.test.domain.Actor.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.action; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.name; diff --git a/src/test/java/io/eigr/spawn/test/actors/JoeActor.java b/src/test/java/io/eigr/spawn/test/actors/JoeActor.java index 4644505..58da19f 100644 --- a/src/test/java/io/eigr/spawn/test/actors/JoeActor.java +++ b/src/test/java/io/eigr/spawn/test/actors/JoeActor.java @@ -1,17 +1,18 @@ package io.eigr.spawn.test.actors; +import domain.actors.Reply; +import domain.actors.Request; +import domain.actors.State; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatefulActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.test.domain.Actor.Reply; -import io.eigr.spawn.java.test.domain.Actor.Request; -import io.eigr.spawn.java.test.domain.Actor.State; -import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.*; +import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.action; +import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.channel; public final class JoeActor implements StatefulActor { diff --git a/src/test/java/io/eigr/spawn/test/actors/StatelessNamedActor.java b/src/test/java/io/eigr/spawn/test/actors/StatelessNamedActor.java index 65fc2af..2117372 100644 --- a/src/test/java/io/eigr/spawn/test/actors/StatelessNamedActor.java +++ b/src/test/java/io/eigr/spawn/test/actors/StatelessNamedActor.java @@ -1,14 +1,14 @@ package io.eigr.spawn.test.actors; +import domain.actors.Reply; +import domain.actors.Request; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatelessActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.NamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.test.domain.Actor.Reply; -import io.eigr.spawn.java.test.domain.Actor.Request; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.action; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.name; diff --git a/src/test/java/io/eigr/spawn/test/actors/UnNamedActor.java b/src/test/java/io/eigr/spawn/test/actors/UnNamedActor.java index 66e2bd3..5d90f65 100644 --- a/src/test/java/io/eigr/spawn/test/actors/UnNamedActor.java +++ b/src/test/java/io/eigr/spawn/test/actors/UnNamedActor.java @@ -1,15 +1,15 @@ package io.eigr.spawn.test.actors; +import domain.actors.Reply; +import domain.actors.Request; +import domain.actors.State; +import io.eigr.spawn.api.actors.ActionBindings; import io.eigr.spawn.api.actors.ActorContext; import io.eigr.spawn.api.actors.StatefulActor; import io.eigr.spawn.api.actors.Value; import io.eigr.spawn.api.actors.behaviors.ActorBehavior; import io.eigr.spawn.api.actors.behaviors.BehaviorCtx; import io.eigr.spawn.api.actors.behaviors.UnNamedActorBehavior; -import io.eigr.spawn.internal.ActionBindings; -import io.eigr.spawn.java.test.domain.Actor.Reply; -import io.eigr.spawn.java.test.domain.Actor.Request; -import io.eigr.spawn.java.test.domain.Actor.State; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.action; import static io.eigr.spawn.api.actors.behaviors.ActorBehavior.name; diff --git a/src/test/proto/eigr/functions/java/sdk/test/actor.proto b/src/test/proto/eigr/functions/java/sdk/test/actor.proto index 81b1951..6a73217 100644 --- a/src/test/proto/eigr/functions/java/sdk/test/actor.proto +++ b/src/test/proto/eigr/functions/java/sdk/test/actor.proto @@ -1,6 +1,7 @@ syntax = "proto3"; -package domain; -option java_package = "io.eigr.spawn.java.test.domain"; +package domain.actors; +option java_package = "domain.actors"; +option java_multiple_files = true; message State { repeated string languages = 1;