diff --git a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ReliableProxySpec.scala b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ReliableProxySpec.scala index 63cf83bf3a..d2fe5cdf9f 100644 --- a/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ReliableProxySpec.scala +++ b/akka-contrib/src/multi-jvm/scala/akka/contrib/pattern/ReliableProxySpec.scala @@ -12,23 +12,19 @@ import org.scalatest.BeforeAndAfterEach import akka.remote.transport.ThrottlerTransportAdapter.Direction import akka.actor._ import akka.testkit.ImplicitSender + import scala.concurrent.duration._ import akka.actor.FSM import akka.actor.ActorRef import akka.testkit.TestKitExtension import akka.actor.ActorIdentity import akka.actor.Identify -import com.typesafe.config.ConfigFactory +import com.typesafe.config.ConfigValueFactory object ReliableProxySpec extends MultiNodeConfig { val local = role("local") val remote = role("remote") - commonConfig(ConfigFactory.parseString(""" - # Remove this when issue #22224 has been fixed - akka.actor.enable-additional-serialization-bindings = off - """)) - testTransport(on = true) } diff --git a/akka-remote/src/main/java/akka/remote/WireFormats.java b/akka-remote/src/main/java/akka/remote/WireFormats.java index 978ac19067..4aa63bebde 100644 --- a/akka-remote/src/main/java/akka/remote/WireFormats.java +++ b/akka-remote/src/main/java/akka/remote/WireFormats.java @@ -4685,25 +4685,104 @@ public final class WireFormats { */ akka.protobuf.ByteString getArgs(int index); - // repeated string classes = 5; + // repeated string manifests = 5; /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ java.util.List - getClassesList(); + getManifestsList(); /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ - int getClassesCount(); + int getManifestsCount(); /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ - java.lang.String getClasses(int index); + java.lang.String getManifests(int index); /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ akka.protobuf.ByteString - getClassesBytes(int index); + getManifestsBytes(int index); + + // repeated int32 serializerIds = 6; + /** + * repeated int32 serializerIds = 6; + * + *
+     * newer wire protocol: serializer id for each arg
+     * 
+ */ + java.util.List getSerializerIdsList(); + /** + * repeated int32 serializerIds = 6; + * + *
+     * newer wire protocol: serializer id for each arg
+     * 
+ */ + int getSerializerIdsCount(); + /** + * repeated int32 serializerIds = 6; + * + *
+     * newer wire protocol: serializer id for each arg
+     * 
+ */ + int getSerializerIds(int index); + + // repeated bool hasManifest = 7; + /** + * repeated bool hasManifest = 7; + * + *
+     * additionally a flag per position to indicate if it was
+     * serialized with manifest or not
+     * 
+ */ + java.util.List getHasManifestList(); + /** + * repeated bool hasManifest = 7; + * + *
+     * additionally a flag per position to indicate if it was
+     * serialized with manifest or not
+     * 
+ */ + int getHasManifestCount(); + /** + * repeated bool hasManifest = 7; + * + *
+     * additionally a flag per position to indicate if it was
+     * serialized with manifest or not
+     * 
+ */ + boolean getHasManifest(int index); } /** * Protobuf type {@code PropsData} @@ -4789,10 +4868,52 @@ public final class WireFormats { } case 42: { if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) { - classes_ = new akka.protobuf.LazyStringArrayList(); + manifests_ = new akka.protobuf.LazyStringArrayList(); mutable_bitField0_ |= 0x00000008; } - classes_.add(input.readBytes()); + manifests_.add(input.readBytes()); + break; + } + case 48: { + if (!((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + serializerIds_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000010; + } + serializerIds_.add(input.readInt32()); + break; + } + case 50: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (!((mutable_bitField0_ & 0x00000010) == 0x00000010) && input.getBytesUntilLimit() > 0) { + serializerIds_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000010; + } + while (input.getBytesUntilLimit() > 0) { + serializerIds_.add(input.readInt32()); + } + input.popLimit(limit); + break; + } + case 56: { + if (!((mutable_bitField0_ & 0x00000020) == 0x00000020)) { + hasManifest_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000020; + } + hasManifest_.add(input.readBool()); + break; + } + case 58: { + int length = input.readRawVarint32(); + int limit = input.pushLimit(length); + if (!((mutable_bitField0_ & 0x00000020) == 0x00000020) && input.getBytesUntilLimit() > 0) { + hasManifest_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000020; + } + while (input.getBytesUntilLimit() > 0) { + hasManifest_.add(input.readBool()); + } + input.popLimit(limit); break; } } @@ -4807,7 +4928,13 @@ public final class WireFormats { args_ = java.util.Collections.unmodifiableList(args_); } if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) { - classes_ = new akka.protobuf.UnmodifiableLazyStringList(classes_); + manifests_ = new akka.protobuf.UnmodifiableLazyStringList(manifests_); + } + if (((mutable_bitField0_ & 0x00000010) == 0x00000010)) { + serializerIds_ = java.util.Collections.unmodifiableList(serializerIds_); + } + if (((mutable_bitField0_ & 0x00000020) == 0x00000020)) { + hasManifest_ = java.util.Collections.unmodifiableList(hasManifest_); } this.unknownFields = unknownFields.build(); makeExtensionsImmutable(); @@ -4929,41 +5056,140 @@ public final class WireFormats { return args_.get(index); } - // repeated string classes = 5; - public static final int CLASSES_FIELD_NUMBER = 5; - private akka.protobuf.LazyStringList classes_; + // repeated string manifests = 5; + public static final int MANIFESTS_FIELD_NUMBER = 5; + private akka.protobuf.LazyStringList manifests_; /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ public java.util.List - getClassesList() { - return classes_; + getManifestsList() { + return manifests_; } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ - public int getClassesCount() { - return classes_.size(); + public int getManifestsCount() { + return manifests_.size(); } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ - public java.lang.String getClasses(int index) { - return classes_.get(index); + public java.lang.String getManifests(int index) { + return manifests_.get(index); } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+     * serialized props parameters
+     * older wire protocol: contains class name for each arg
+     * newer wire protocol: contains string manifest for each arg
+     * 
*/ public akka.protobuf.ByteString - getClassesBytes(int index) { - return classes_.getByteString(index); + getManifestsBytes(int index) { + return manifests_.getByteString(index); + } + + // repeated int32 serializerIds = 6; + public static final int SERIALIZERIDS_FIELD_NUMBER = 6; + private java.util.List serializerIds_; + /** + * repeated int32 serializerIds = 6; + * + *
+     * newer wire protocol: serializer id for each arg
+     * 
+ */ + public java.util.List + getSerializerIdsList() { + return serializerIds_; + } + /** + * repeated int32 serializerIds = 6; + * + *
+     * newer wire protocol: serializer id for each arg
+     * 
+ */ + public int getSerializerIdsCount() { + return serializerIds_.size(); + } + /** + * repeated int32 serializerIds = 6; + * + *
+     * newer wire protocol: serializer id for each arg
+     * 
+ */ + public int getSerializerIds(int index) { + return serializerIds_.get(index); + } + + // repeated bool hasManifest = 7; + public static final int HASMANIFEST_FIELD_NUMBER = 7; + private java.util.List hasManifest_; + /** + * repeated bool hasManifest = 7; + * + *
+     * additionally a flag per position to indicate if it was
+     * serialized with manifest or not
+     * 
+ */ + public java.util.List + getHasManifestList() { + return hasManifest_; + } + /** + * repeated bool hasManifest = 7; + * + *
+     * additionally a flag per position to indicate if it was
+     * serialized with manifest or not
+     * 
+ */ + public int getHasManifestCount() { + return hasManifest_.size(); + } + /** + * repeated bool hasManifest = 7; + * + *
+     * additionally a flag per position to indicate if it was
+     * serialized with manifest or not
+     * 
+ */ + public boolean getHasManifest(int index) { + return hasManifest_.get(index); } private void initFields() { deploy_ = akka.remote.WireFormats.DeployData.getDefaultInstance(); clazz_ = ""; args_ = java.util.Collections.emptyList(); - classes_ = akka.protobuf.LazyStringArrayList.EMPTY; + manifests_ = akka.protobuf.LazyStringArrayList.EMPTY; + serializerIds_ = java.util.Collections.emptyList(); + hasManifest_ = java.util.Collections.emptyList(); } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -4998,8 +5224,14 @@ public final class WireFormats { for (int i = 0; i < args_.size(); i++) { output.writeBytes(4, args_.get(i)); } - for (int i = 0; i < classes_.size(); i++) { - output.writeBytes(5, classes_.getByteString(i)); + for (int i = 0; i < manifests_.size(); i++) { + output.writeBytes(5, manifests_.getByteString(i)); + } + for (int i = 0; i < serializerIds_.size(); i++) { + output.writeInt32(6, serializerIds_.get(i)); + } + for (int i = 0; i < hasManifest_.size(); i++) { + output.writeBool(7, hasManifest_.get(i)); } getUnknownFields().writeTo(output); } @@ -5029,12 +5261,27 @@ public final class WireFormats { } { int dataSize = 0; - for (int i = 0; i < classes_.size(); i++) { + for (int i = 0; i < manifests_.size(); i++) { dataSize += akka.protobuf.CodedOutputStream - .computeBytesSizeNoTag(classes_.getByteString(i)); + .computeBytesSizeNoTag(manifests_.getByteString(i)); } size += dataSize; - size += 1 * getClassesList().size(); + size += 1 * getManifestsList().size(); + } + { + int dataSize = 0; + for (int i = 0; i < serializerIds_.size(); i++) { + dataSize += akka.protobuf.CodedOutputStream + .computeInt32SizeNoTag(serializerIds_.get(i)); + } + size += dataSize; + size += 1 * getSerializerIdsList().size(); + } + { + int dataSize = 0; + dataSize = 1 * getHasManifestList().size(); + size += dataSize; + size += 1 * getHasManifestList().size(); } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; @@ -5168,8 +5415,12 @@ public final class WireFormats { bitField0_ = (bitField0_ & ~0x00000002); args_ = java.util.Collections.emptyList(); bitField0_ = (bitField0_ & ~0x00000004); - classes_ = akka.protobuf.LazyStringArrayList.EMPTY; + manifests_ = akka.protobuf.LazyStringArrayList.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); + serializerIds_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + hasManifest_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); return this; } @@ -5216,11 +5467,21 @@ public final class WireFormats { } result.args_ = args_; if (((bitField0_ & 0x00000008) == 0x00000008)) { - classes_ = new akka.protobuf.UnmodifiableLazyStringList( - classes_); + manifests_ = new akka.protobuf.UnmodifiableLazyStringList( + manifests_); bitField0_ = (bitField0_ & ~0x00000008); } - result.classes_ = classes_; + result.manifests_ = manifests_; + if (((bitField0_ & 0x00000010) == 0x00000010)) { + serializerIds_ = java.util.Collections.unmodifiableList(serializerIds_); + bitField0_ = (bitField0_ & ~0x00000010); + } + result.serializerIds_ = serializerIds_; + if (((bitField0_ & 0x00000020) == 0x00000020)) { + hasManifest_ = java.util.Collections.unmodifiableList(hasManifest_); + bitField0_ = (bitField0_ & ~0x00000020); + } + result.hasManifest_ = hasManifest_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -5255,13 +5516,33 @@ public final class WireFormats { } onChanged(); } - if (!other.classes_.isEmpty()) { - if (classes_.isEmpty()) { - classes_ = other.classes_; + if (!other.manifests_.isEmpty()) { + if (manifests_.isEmpty()) { + manifests_ = other.manifests_; bitField0_ = (bitField0_ & ~0x00000008); } else { - ensureClassesIsMutable(); - classes_.addAll(other.classes_); + ensureManifestsIsMutable(); + manifests_.addAll(other.manifests_); + } + onChanged(); + } + if (!other.serializerIds_.isEmpty()) { + if (serializerIds_.isEmpty()) { + serializerIds_ = other.serializerIds_; + bitField0_ = (bitField0_ & ~0x00000010); + } else { + ensureSerializerIdsIsMutable(); + serializerIds_.addAll(other.serializerIds_); + } + onChanged(); + } + if (!other.hasManifest_.isEmpty()) { + if (hasManifest_.isEmpty()) { + hasManifest_ = other.hasManifest_; + bitField0_ = (bitField0_ & ~0x00000020); + } else { + ensureHasManifestIsMutable(); + hasManifest_.addAll(other.hasManifest_); } onChanged(); } @@ -5567,95 +5848,344 @@ public final class WireFormats { return this; } - // repeated string classes = 5; - private akka.protobuf.LazyStringList classes_ = akka.protobuf.LazyStringArrayList.EMPTY; - private void ensureClassesIsMutable() { + // repeated string manifests = 5; + private akka.protobuf.LazyStringList manifests_ = akka.protobuf.LazyStringArrayList.EMPTY; + private void ensureManifestsIsMutable() { if (!((bitField0_ & 0x00000008) == 0x00000008)) { - classes_ = new akka.protobuf.LazyStringArrayList(classes_); + manifests_ = new akka.protobuf.LazyStringArrayList(manifests_); bitField0_ |= 0x00000008; } } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ public java.util.List - getClassesList() { - return java.util.Collections.unmodifiableList(classes_); + getManifestsList() { + return java.util.Collections.unmodifiableList(manifests_); } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public int getClassesCount() { - return classes_.size(); + public int getManifestsCount() { + return manifests_.size(); } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public java.lang.String getClasses(int index) { - return classes_.get(index); + public java.lang.String getManifests(int index) { + return manifests_.get(index); } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ public akka.protobuf.ByteString - getClassesBytes(int index) { - return classes_.getByteString(index); + getManifestsBytes(int index) { + return manifests_.getByteString(index); } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public Builder setClasses( + public Builder setManifests( int index, java.lang.String value) { if (value == null) { throw new NullPointerException(); } - ensureClassesIsMutable(); - classes_.set(index, value); + ensureManifestsIsMutable(); + manifests_.set(index, value); onChanged(); return this; } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public Builder addClasses( + public Builder addManifests( java.lang.String value) { if (value == null) { throw new NullPointerException(); } - ensureClassesIsMutable(); - classes_.add(value); + ensureManifestsIsMutable(); + manifests_.add(value); onChanged(); return this; } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public Builder addAllClasses( + public Builder addAllManifests( java.lang.Iterable values) { - ensureClassesIsMutable(); - super.addAll(values, classes_); + ensureManifestsIsMutable(); + super.addAll(values, manifests_); onChanged(); return this; } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public Builder clearClasses() { - classes_ = akka.protobuf.LazyStringArrayList.EMPTY; + public Builder clearManifests() { + manifests_ = akka.protobuf.LazyStringArrayList.EMPTY; bitField0_ = (bitField0_ & ~0x00000008); onChanged(); return this; } /** - * repeated string classes = 5; + * repeated string manifests = 5; + * + *
+       * serialized props parameters
+       * older wire protocol: contains class name for each arg
+       * newer wire protocol: contains string manifest for each arg
+       * 
*/ - public Builder addClassesBytes( + public Builder addManifestsBytes( akka.protobuf.ByteString value) { if (value == null) { throw new NullPointerException(); } - ensureClassesIsMutable(); - classes_.add(value); + ensureManifestsIsMutable(); + manifests_.add(value); + onChanged(); + return this; + } + + // repeated int32 serializerIds = 6; + private java.util.List serializerIds_ = java.util.Collections.emptyList(); + private void ensureSerializerIdsIsMutable() { + if (!((bitField0_ & 0x00000010) == 0x00000010)) { + serializerIds_ = new java.util.ArrayList(serializerIds_); + bitField0_ |= 0x00000010; + } + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public java.util.List + getSerializerIdsList() { + return java.util.Collections.unmodifiableList(serializerIds_); + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public int getSerializerIdsCount() { + return serializerIds_.size(); + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public int getSerializerIds(int index) { + return serializerIds_.get(index); + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public Builder setSerializerIds( + int index, int value) { + ensureSerializerIdsIsMutable(); + serializerIds_.set(index, value); + onChanged(); + return this; + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public Builder addSerializerIds(int value) { + ensureSerializerIdsIsMutable(); + serializerIds_.add(value); + onChanged(); + return this; + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public Builder addAllSerializerIds( + java.lang.Iterable values) { + ensureSerializerIdsIsMutable(); + super.addAll(values, serializerIds_); + onChanged(); + return this; + } + /** + * repeated int32 serializerIds = 6; + * + *
+       * newer wire protocol: serializer id for each arg
+       * 
+ */ + public Builder clearSerializerIds() { + serializerIds_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000010); + onChanged(); + return this; + } + + // repeated bool hasManifest = 7; + private java.util.List hasManifest_ = java.util.Collections.emptyList(); + private void ensureHasManifestIsMutable() { + if (!((bitField0_ & 0x00000020) == 0x00000020)) { + hasManifest_ = new java.util.ArrayList(hasManifest_); + bitField0_ |= 0x00000020; + } + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public java.util.List + getHasManifestList() { + return java.util.Collections.unmodifiableList(hasManifest_); + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public int getHasManifestCount() { + return hasManifest_.size(); + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public boolean getHasManifest(int index) { + return hasManifest_.get(index); + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public Builder setHasManifest( + int index, boolean value) { + ensureHasManifestIsMutable(); + hasManifest_.set(index, value); + onChanged(); + return this; + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public Builder addHasManifest(boolean value) { + ensureHasManifestIsMutable(); + hasManifest_.add(value); + onChanged(); + return this; + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public Builder addAllHasManifest( + java.lang.Iterable values) { + ensureHasManifestIsMutable(); + super.addAll(values, hasManifest_); + onChanged(); + return this; + } + /** + * repeated bool hasManifest = 7; + * + *
+       * additionally a flag per position to indicate if it was
+       * serialized with manifest or not
+       * 
+ */ + public Builder clearHasManifest() { + hasManifest_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000020); onChanged(); return this; } @@ -9558,24 +10088,25 @@ public final class WireFormats { "\005\022\027\n\017messageManifest\030\003 \001(\014\"~\n\023DaemonMsgC" + "reateData\022\031\n\005props\030\001 \002(\0132\n.PropsData\022\033\n\006" + "deploy\030\002 \002(\0132\013.DeployData\022\014\n\004path\030\003 \002(\t\022" + - "!\n\nsupervisor\030\004 \002(\0132\r.ActorRefData\"V\n\tPr" + - "opsData\022\033\n\006deploy\030\002 \002(\0132\013.DeployData\022\r\n\005" + - "clazz\030\003 \002(\t\022\014\n\004args\030\004 \003(\014\022\017\n\007classes\030\005 \003" + - "(\t\"c\n\nDeployData\022\014\n\004path\030\001 \002(\t\022\016\n\006config" + - "\030\002 \001(\014\022\024\n\014routerConfig\030\003 \001(\014\022\r\n\005scope\030\004 " + - "\001(\014\022\022\n\ndispatcher\030\005 \001(\t\"P\n\023AkkaProtocolM" + - "essage\022\017\n\007payload\030\001 \001(\014\022(\n\013instruction\030\002", - " \001(\0132\023.AkkaControlMessage\"b\n\022AkkaControl" + - "Message\022!\n\013commandType\030\001 \002(\0162\014.CommandTy" + - "pe\022)\n\rhandshakeInfo\030\002 \001(\0132\022.AkkaHandshak" + - "eInfo\"N\n\021AkkaHandshakeInfo\022\034\n\006origin\030\001 \002" + - "(\0132\014.AddressData\022\013\n\003uid\030\002 \002(\006\022\016\n\006cookie\030" + - "\003 \001(\t\"O\n\013AddressData\022\016\n\006system\030\001 \002(\t\022\020\n\010" + - "hostname\030\002 \002(\t\022\014\n\004port\030\003 \002(\r\022\020\n\010protocol" + - "\030\004 \001(\t*{\n\013CommandType\022\r\n\tASSOCIATE\020\001\022\020\n\014" + - "DISASSOCIATE\020\002\022\r\n\tHEARTBEAT\020\003\022\036\n\032DISASSO" + - "CIATE_SHUTTING_DOWN\020\004\022\034\n\030DISASSOCIATE_QU", - "ARANTINED\020\005B\017\n\013akka.remoteH\001" + "!\n\nsupervisor\030\004 \002(\0132\r.ActorRefData\"\204\001\n\tP" + + "ropsData\022\033\n\006deploy\030\002 \002(\0132\013.DeployData\022\r\n" + + "\005clazz\030\003 \002(\t\022\014\n\004args\030\004 \003(\014\022\021\n\tmanifests\030" + + "\005 \003(\t\022\025\n\rserializerIds\030\006 \003(\005\022\023\n\013hasManif" + + "est\030\007 \003(\010\"c\n\nDeployData\022\014\n\004path\030\001 \002(\t\022\016\n" + + "\006config\030\002 \001(\014\022\024\n\014routerConfig\030\003 \001(\014\022\r\n\005s" + + "cope\030\004 \001(\014\022\022\n\ndispatcher\030\005 \001(\t\"P\n\023AkkaPr", + "otocolMessage\022\017\n\007payload\030\001 \001(\014\022(\n\013instru" + + "ction\030\002 \001(\0132\023.AkkaControlMessage\"b\n\022Akka" + + "ControlMessage\022!\n\013commandType\030\001 \002(\0162\014.Co" + + "mmandType\022)\n\rhandshakeInfo\030\002 \001(\0132\022.AkkaH" + + "andshakeInfo\"N\n\021AkkaHandshakeInfo\022\034\n\006ori" + + "gin\030\001 \002(\0132\014.AddressData\022\013\n\003uid\030\002 \002(\006\022\016\n\006" + + "cookie\030\003 \001(\t\"O\n\013AddressData\022\016\n\006system\030\001 " + + "\002(\t\022\020\n\010hostname\030\002 \002(\t\022\014\n\004port\030\003 \002(\r\022\020\n\010p" + + "rotocol\030\004 \001(\t*{\n\013CommandType\022\r\n\tASSOCIAT" + + "E\020\001\022\020\n\014DISASSOCIATE\020\002\022\r\n\tHEARTBEAT\020\003\022\036\n\032", + "DISASSOCIATE_SHUTTING_DOWN\020\004\022\034\n\030DISASSOC" + + "IATE_QUARANTINED\020\005B\017\n\013akka.remoteH\001" }; akka.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new akka.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -9623,7 +10154,7 @@ public final class WireFormats { internal_static_PropsData_fieldAccessorTable = new akka.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_PropsData_descriptor, - new java.lang.String[] { "Deploy", "Clazz", "Args", "Classes", }); + new java.lang.String[] { "Deploy", "Clazz", "Args", "Manifests", "SerializerIds", "HasManifest", }); internal_static_DeployData_descriptor = getDescriptor().getMessageTypes().get(7); internal_static_DeployData_fieldAccessorTable = new diff --git a/akka-remote/src/main/protobuf/WireFormats.proto b/akka-remote/src/main/protobuf/WireFormats.proto index 29b8d60d3c..49e9df558d 100644 --- a/akka-remote/src/main/protobuf/WireFormats.proto +++ b/akka-remote/src/main/protobuf/WireFormats.proto @@ -64,7 +64,15 @@ message PropsData { required DeployData deploy = 2; required string clazz = 3; repeated bytes args = 4; - repeated string classes = 5; + // serialized props parameters + // older wire protocol: contains class name for each arg + // newer wire protocol: contains string manifest for each arg + repeated string manifests = 5; + // newer wire protocol: serializer id for each arg + repeated int32 serializerIds = 6; + // additionally a flag per position to indicate if it was + // serialized with manifest or not + repeated bool hasManifest = 7; } /** diff --git a/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala b/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala index 11806c1fb3..fa156fc7e1 100644 --- a/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala +++ b/akka-remote/src/main/scala/akka/remote/serialization/DaemonMsgCreateSerializer.scala @@ -4,13 +4,14 @@ package akka.remote.serialization -import akka.serialization.{ BaseSerializer, SerializationExtension } +import akka.serialization.{ BaseSerializer, SerializationExtension, SerializerWithStringManifest } import akka.protobuf.ByteString import com.typesafe.config.{ Config, ConfigFactory } import akka.actor.{ Deploy, ExtendedActorSystem, NoScopeGiven, Props, Scope } import akka.remote.DaemonMsgCreate -import akka.remote.WireFormats.{ DaemonMsgCreateData, DeployData, PropsData } +import akka.remote.WireFormats.{ DaemonMsgCreateData, DeployData, PropsData, SerializedMessage } import akka.routing.{ NoRouter, RouterConfig } + import scala.reflect.ClassTag import util.{ Failure, Success } import java.io.Serializable @@ -24,24 +25,16 @@ import java.io.Serializable * * INTERNAL API */ -private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends BaseSerializer { +private[akka] final class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) extends BaseSerializer { import ProtobufSerializer.serializeActorRef import ProtobufSerializer.deserializeActorRef import Deploy.NoDispatcherGiven - @deprecated("Use constructor with ExtendedActorSystem", "2.4") - def this() = this(null) - private val scala212OrLater = !scala.util.Properties.versionNumberString.startsWith("2.11") - // TODO remove this when deprecated this() is removed - override val identifier: Int = - if (system eq null) 3 - else identifierFromConfig + private lazy val serialization = SerializationExtension(system) - def includeManifest: Boolean = false - - lazy val serialization = SerializationExtension(system) + override val includeManifest: Boolean = false def toBinary(obj: AnyRef): Array[Byte] = obj match { case DaemonMsgCreate(props, deploy, path, supervisor) ⇒ @@ -49,11 +42,11 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e def deployProto(d: Deploy): DeployData = { val builder = DeployData.newBuilder.setPath(d.path) if (d.config != ConfigFactory.empty) - builder.setConfig(serialize(d.config)) + builder.setConfig(oldSerialize(d.config)) if (d.routerConfig != NoRouter) - builder.setRouterConfig(serialize(d.routerConfig)) + builder.setRouterConfig(oldSerialize(d.routerConfig)) if (d.scope != NoScopeGiven) - builder.setScope(serialize(d.scope)) + builder.setScope(oldSerialize(d.scope)) if (d.dispatcher != NoDispatcherGiven) builder.setDispatcher(d.dispatcher) builder.build @@ -63,22 +56,12 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e val builder = PropsData.newBuilder .setClazz(props.clazz.getName) .setDeploy(deployProto(props.deploy)) - props.args map serialize foreach builder.addArgs - props.args.map { a ⇒ - val argClassName = - if (a == null) "null" - else { - val className = a.getClass.getName - if (scala212OrLater && a.getClass.isInstanceOf[Serializable] && a.getClass.isSynthetic && - className.contains("$Lambda$")) { - // The serialization of the parameters is based on passing class name instead of - // serializerId and manifest as we usually do. With Scala 2.12 the functions are generated as - // lambdas and we can't use that load class from that name when deserializing. - classOf[Serializable].getName - } else - className - } - builder.addClasses(argClassName) + props.args.foreach { arg ⇒ + val (serializerId, hasManifest, manifest, bytes) = serialize(arg) + builder.addArgs(ByteString.copyFrom(bytes)) + builder.addManifests(manifest) + builder.addSerializerIds(serializerId) + builder.addHasManifest(hasManifest) } builder.build } @@ -100,13 +83,13 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e def deploy(protoDeploy: DeployData): Deploy = { val config = - if (protoDeploy.hasConfig) deserialize(protoDeploy.getConfig, classOf[Config]) + if (protoDeploy.hasConfig) oldDeserialize(protoDeploy.getConfig, classOf[Config]) else ConfigFactory.empty val routerConfig = - if (protoDeploy.hasRouterConfig) deserialize(protoDeploy.getRouterConfig, classOf[RouterConfig]) + if (protoDeploy.hasRouterConfig) oldDeserialize(protoDeploy.getRouterConfig, classOf[RouterConfig]) else NoRouter val scope = - if (protoDeploy.hasScope) deserialize(protoDeploy.getScope, classOf[Scope]) + if (protoDeploy.hasScope) oldDeserialize(protoDeploy.getScope, classOf[Scope]) else NoScopeGiven val dispatcher = if (protoDeploy.hasDispatcher) protoDeploy.getDispatcher @@ -116,10 +99,29 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e def props = { import scala.collection.JavaConverters._ - val clazz = system.dynamicAccess.getClassFor[AnyRef](proto.getProps.getClazz).get - val args: Vector[AnyRef] = (proto.getProps.getArgsList.asScala zip proto.getProps.getClassesList.asScala) - .map(deserialize)(collection.breakOut) - Props(deploy(proto.getProps.getDeploy), clazz, args) + val protoProps = proto.getProps + val actorClass = system.dynamicAccess.getClassFor[AnyRef](protoProps.getClazz).get + val args: Vector[AnyRef] = + // message from a newer node always contains serializer ids and possibly a string manifest for each position + if (protoProps.getSerializerIdsCount > 0) { + for { + idx ← (0 until protoProps.getSerializerIdsCount).toVector + } yield { + val manifest = + if (protoProps.getHasManifest(idx)) protoProps.getManifests(idx) + else "" + serialization.deserializeByteBuffer( + protoProps.getArgs(idx).asReadOnlyByteBuffer(), + protoProps.getSerializerIds(idx), + manifest) + } + } else { + // message from an older node, which only provides data and class name + // and never any serializer ids + (proto.getProps.getArgsList.asScala zip proto.getProps.getManifestsList.asScala) + .map(oldDeserialize)(collection.breakOut) + } + Props(deploy(proto.getProps.getDeploy), actorClass, args) } DaemonMsgCreate( @@ -129,13 +131,51 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e supervisor = deserializeActorRef(system, proto.getSupervisor)) } - protected def serialize(any: Any): ByteString = ByteString.copyFrom(serialization.serialize(any.asInstanceOf[AnyRef]).get) + private def oldSerialize(any: Any): ByteString = ByteString.copyFrom(serialization.serialize(any.asInstanceOf[AnyRef]).get) - protected def deserialize(p: (ByteString, String)): AnyRef = - if (p._1.isEmpty && p._2 == "null") null - else deserialize(p._1, system.dynamicAccess.getClassFor[AnyRef](p._2).get) + private def serialize(any: Any): (Int, Boolean, String, Array[Byte]) = { + val m = any.asInstanceOf[AnyRef] + val serializer = serialization.findSerializerFor(m) - protected def deserialize[T: ClassTag](data: ByteString, clazz: Class[T]): T = { + // this trixery is to retain backwards wire compatibility while at the same time + // allowing for usage of serializers with string manifests + var hasManifest = false + val manifest = serializer match { + case ser: SerializerWithStringManifest ⇒ + hasManifest = true + ser.manifest(m) + case ser ⇒ + hasManifest = ser.includeManifest + + // we do include class name regardless to retain wire compatibility + // with older nodes who expect manifest to be the class name + if (m eq null) { + "null" + } else { + val className = m.getClass.getName + if (scala212OrLater && m.isInstanceOf[Serializable] && m.getClass.isSynthetic && className.contains("$Lambda$")) { + // When the additional-protobuf serializers are not enabled + // the serialization of the parameters is based on passing class name instead of + // serializerId and manifest as we usually do. With Scala 2.12 the functions are generated as + // lambdas and we can't use that load class from that name when deserializing + classOf[Serializable].getName + } else { + className + } + } + } + + (serializer.identifier, hasManifest, manifest, serializer.toBinary(m)) + } + + private def oldDeserialize(p: (ByteString, String)): AnyRef = + oldDeserialize(p._1, p._2) + + private def oldDeserialize(data: ByteString, className: String): AnyRef = + if (data.isEmpty && className == "null") null + else oldDeserialize(data, system.dynamicAccess.getClassFor[AnyRef](className).get) + + private def oldDeserialize[T: ClassTag](data: ByteString, clazz: Class[T]): T = { val bytes = data.toByteArray serialization.deserialize(bytes, clazz) match { case Success(x: T) ⇒ x @@ -152,4 +192,5 @@ private[akka] class DaemonMsgCreateSerializer(val system: ExtendedActorSystem) e } } } + } diff --git a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala index 967fa90765..33168fc15d 100644 --- a/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala +++ b/akka-remote/src/test/scala/akka/remote/serialization/DaemonMsgCreateSerializerSpec.scala @@ -8,25 +8,26 @@ import language.postfixOps import akka.serialization.SerializationExtension import com.typesafe.config.ConfigFactory import akka.testkit.AkkaSpec -import akka.actor.{ Actor, Address, Props, Deploy, OneForOneStrategy, SupervisorStrategy } +import akka.actor.{ Actor, ActorRef, Address, Deploy, ExtendedActorSystem, OneForOneStrategy, Props, SupervisorStrategy } import akka.remote.{ DaemonMsgCreate, RemoteScope } -import akka.routing.{ RoundRobinPool, FromConfig } +import akka.routing.{ FromConfig, RoundRobinPool } +import akka.util.ByteString + import scala.concurrent.duration._ object DaemonMsgCreateSerializerSpec { - class MyActor extends Actor { - def receive = Actor.emptyBehavior - } - class MyActorWithParam(ignore: String) extends Actor { - def receive = Actor.emptyBehavior - } - - class MyActorWithFunParam(fun: Function1[Int, Int]) extends Actor { + trait EmptyActor extends Actor { def receive = Actor.emptyBehavior } + class MyActor extends EmptyActor + class MyActorWithParam(ignore: String) extends EmptyActor + class MyActorWithFunParam(fun: Function1[Int, Int]) extends EmptyActor + class ActorWithDummyParameter(javaSerialized: DummyParameter, protoSerialized: ActorRef) extends EmptyActor } +case class DummyParameter(val inner: String) extends Serializable + class DaemonMsgCreateSerializerSpec extends AkkaSpec { import DaemonMsgCreateSerializerSpec._ @@ -79,6 +80,37 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec { } } + "deserialize the old wire format with just class and field for props parameters (if possible)" in { + val serializer = new DaemonMsgCreateSerializer(system.asInstanceOf[ExtendedActorSystem]) + + // the oldSnapshot was created with the version of DemonMsgCreateSerializer in Akka 2.4.17. See issue #22224. + // It was created with: + /* + import org.apache.commons.codec.binary.Hex.encodeHex + val bytes = serializer.toBinary( + DaemonMsgCreate(Props(classOf[MyActorWithParam], "a string"), Deploy.local, "/user/test", system.actorFor("/user"))) + println(String.valueOf(encodeHex(bytes))) + */ + + val oldBytesHex = + "0a6a12020a001a48616b6b612e72656d6f74652e73657269616c697a6174696f" + + "6e2e4461656d6f6e4d736743726561746553657269616c697a6572537065632" + + "44d794163746f7257697468506172616d22086120737472696e672a106a6176" + + "612e6c616e672e537472696e67122f0a00222baced000573720016616b6b612" + + "e6163746f722e4c6f63616c53636f706524000000000000000102000078701a" + + "0a2f757365722f74657374222b0a29616b6b613a2f2f4461656d6f6e4d73674" + + "3726561746553657269616c697a6572537065632f75736572" + + import org.apache.commons.codec.binary.Hex.decodeHex + val oldBytes = decodeHex(oldBytesHex.toCharArray) + val result = serializer.fromBinary(oldBytes, classOf[DaemonMsgCreate]) + + result match { + case dmc: DaemonMsgCreate ⇒ + dmc.props.args should ===(Seq("a string": Any)) + } + } + "serialize and de-serialize DaemonMsgCreate with Deploy and RouterConfig" in { verifySerialization { // Duration.Inf doesn't equal Duration.Inf, so we use another for test @@ -105,6 +137,17 @@ class DaemonMsgCreateSerializerSpec extends AkkaSpec { } } + "allows for mixing serializers with and without manifests for props parameters" in { + verifySerialization { + DaemonMsgCreate( + // parameters should trigger JavaSerializer for the first one and additional protobuf for the second (?) + props = Props(classOf[ActorWithDummyParameter], new DummyParameter("dummy"), system.deadLetters), + deploy = Deploy(), + path = "foo", + supervisor = supervisor) + } + } + def verifySerialization(msg: DaemonMsgCreate): Unit = { assertDaemonMsgCreate(msg, ser.deserialize(ser.serialize(msg).get, classOf[DaemonMsgCreate]).get.asInstanceOf[DaemonMsgCreate]) } diff --git a/project/MiMa.scala b/project/MiMa.scala index 65b6487ed1..64b2c0cf30 100644 --- a/project/MiMa.scala +++ b/project/MiMa.scala @@ -462,7 +462,42 @@ object MiMa extends AutoPlugin { ProblemFilters.exclude[IncompatibleMethTypeProblem]("akka.persistence.AbstractPersistentActor.persistAll"), // #22208 remove extension key - ProblemFilters.exclude[MissingClassProblem]("akka.event.Logging$Extension$") + ProblemFilters.exclude[MissingClassProblem]("akka.event.Logging$Extension$"), + + // #22224 DaemonMsgCreateSerializer using manifests + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData.getClassesBytes"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData.getClassesList"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData.getClassesCount"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData.getClasses"), + ProblemFilters.exclude[MissingFieldProblem]("akka.remote.WireFormats#PropsData.CLASSES_FIELD_NUMBER"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getHasManifest"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getHasManifestCount"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getSerializerIdsList"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getSerializerIds"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getHasManifestList"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getSerializerIdsCount"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getClassesBytes"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getClassesList"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getClassesCount"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getClasses"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getManifestsBytes"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getManifests"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getManifestsList"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.remote.WireFormats#PropsDataOrBuilder.getManifestsCount"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.getClassesBytes"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.getClassesList"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.addClassesBytes"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.getClassesCount"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.clearClasses"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.addClasses"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.getClasses"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.addAllClasses"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.WireFormats#PropsData#Builder.setClasses"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.serialization.DaemonMsgCreateSerializer.serialize"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.serialization.DaemonMsgCreateSerializer.deserialize"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.serialization.DaemonMsgCreateSerializer.deserialize"), + ProblemFilters.exclude[FinalClassProblem]("akka.remote.serialization.DaemonMsgCreateSerializer"), + ProblemFilters.exclude[DirectMissingMethodProblem]("akka.remote.serialization.DaemonMsgCreateSerializer.serialization") // NOTE: filters that will be backported to 2.4 should go to the latest 2.4 version below )