Classic Serialization
Pekko Classic pertains to the original Actor APIs, which have been improved by more type safe and guided Actor APIs. Pekko Classic is still fully supported and existing applications can continue to use the classic APIs. It is also possible to use the new Actor APIs together with classic actors in the same ActorSystem, see coexistence. For new projects we recommend using the new Actor API.
Serialization is the same for Classic and Typed actors. It is described in Serialization, aside from serialization of ActorRef
that is described here.
Dependency
To use Serialization, you must add the following dependency in your project:
- sbt
val PekkoVersion = "1.1.2" libraryDependencies += "org.apache.pekko" %% "pekko-actor" % PekkoVersion
- Maven
<properties> <scala.binary.version>2.13</scala.binary.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.apache.pekko</groupId> <artifactId>pekko-bom_${scala.binary.version}</artifactId> <version>1.1.2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.apache.pekko</groupId> <artifactId>pekko-actor_${scala.binary.version}</artifactId> </dependency> </dependencies>
- Gradle
def versions = [ ScalaBinary: "2.13" ] dependencies { implementation platform("org.apache.pekko:pekko-bom_${versions.ScalaBinary}:1.1.2") implementation "org.apache.pekko:pekko-actor_${versions.ScalaBinary}" }
Serializing ActorRefs
All ActorRefs are serializable when using Serialization with Jackson, but in case you are writing your own serializer, you might want to know how to serialize and deserialize them properly. In the general case, the local address to be used depends on the type of remote address which shall be the recipient of the serialized information. Use Serialization.serializedActorPath(actorRef)
like this:
- Scala
-
source
import org.apache.pekko import pekko.actor._ import pekko.actor.typed.scaladsl.Behaviors import pekko.cluster.Cluster import pekko.serialization._
- Java
-
source
import org.apache.pekko.actor.*; import org.apache.pekko.serialization.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets;
- Scala
-
source
// Serialize // (beneath toBinary) val serializedRef: String = Serialization.serializedActorPath(theActorRef) // Then serialize the identifier however you like // Deserialize // (beneath fromBinary) val deserializedRef = extendedSystem.provider.resolveActorRef(serializedRef) // Then use the ActorRef
- Java
-
source
// Serialize // (beneath toBinary) String serializedRef = Serialization.serializedActorPath(theActorRef); // Then just serialize the identifier however you like // Deserialize // (beneath fromBinary) final ActorRef deserializedRef = extendedSystem.provider().resolveActorRef(serializedRef); // Then just use the ActorRef
This assumes that serialization happens in the context of sending a message through the remote transport. There are other uses of serialization, though, e.g. storing actor references outside of an actor application (database, etc.). In this case, it is important to keep in mind that the address part of an actor’s path determines how that actor is communicated with. Storing a local actor path might be the right choice if the retrieval happens in the same logical context, but it is not enough when deserializing it on a different network host: for that it would need to include the system’s remote transport address.
- Scala
-
source
val selfAddress = Cluster(system).selfAddress val serializedRef: String = theActorRef.path.toSerializationFormatWithAddress(selfAddress)
- Java
-
source
Address selfAddress = Cluster.get(system).selfAddress(); String serializedRef = theActorRef.path().toSerializationFormatWithAddress(selfAddress);
ActorPath.toSerializationFormatWithAddress
differs from toString
if the address does not already have host
and port
components, i.e. it only inserts address information for local addresses.
toSerializationFormatWithAddress
also adds the unique id of the actor, which will change when the actor is stopped and then created again with the same name. Sending messages to a reference pointing the old actor will not be delivered to the new actor. If you don’t want this behavior, e.g. in case of long term storage of the reference, you can use toStringWithAddress
, which doesn’t include the unique id.
There is also a default remote address which is the one used by cluster support (and typical systems have just this one); you can get it like this:
- Scala
-
source
val selfAddress = Cluster(system).selfAddress val serializedRef: String = theActorRef.path.toSerializationFormatWithAddress(selfAddress)
- Java
-
source
Address selfAddress = Cluster.get(system).selfAddress(); String serializedRef = theActorRef.path().toSerializationFormatWithAddress(selfAddress);