diff --git a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala index df2170905e..6501d8d43d 100644 --- a/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala +++ b/akka-actor-tests/src/test/scala/akka/serialization/SerializeSpec.scala @@ -203,6 +203,10 @@ object VerifySerializabilitySpec { } } + class FooUntypedActor extends UntypedActor { + def onReceive(message: Any) {} + } + class NonSerializableActor(system: ActorSystem) extends Actor { def receive = { case s: String ⇒ sender ! s @@ -210,6 +214,7 @@ object VerifySerializabilitySpec { } } +@org.junit.runner.RunWith(classOf[org.scalatest.junit.JUnitRunner]) class VerifySerializabilitySpec extends AkkaSpec(VerifySerializabilitySpec.conf) { import VerifySerializabilitySpec._ implicit val timeout = Timeout(5 seconds) @@ -221,17 +226,28 @@ class VerifySerializabilitySpec extends AkkaSpec(VerifySerializabilitySpec.conf) "verify creators" in { val a = system.actorOf(Props[FooActor]) - intercept[NotSerializableException] { - Await.result(a ? new AnyRef, timeout.duration) - } system stop a + + val b = system.actorOf(Props(new FooActor)) + system stop b + + val c = system.actorOf(Props().withCreator(new UntypedActorFactory { + def create() = new FooUntypedActor + })) + system stop c + + intercept[java.io.NotSerializableException] { + val d = system.actorOf(Props(new NonSerializableActor(system))) + } + } "verify messages" in { val a = system.actorOf(Props[FooActor]) Await.result(a ? "pigdog", timeout.duration) must be("pigdog") - intercept[java.io.NotSerializableException] { - val b = system.actorOf(Props(new NonSerializableActor(system))) + + intercept[NotSerializableException] { + Await.result(a ? new AnyRef, timeout.duration) } system stop a } diff --git a/akka-actor/src/main/scala/akka/AkkaException.scala b/akka-actor/src/main/scala/akka/AkkaException.scala index 47f7465535..ce1c01dcc5 100644 --- a/akka-actor/src/main/scala/akka/AkkaException.scala +++ b/akka-actor/src/main/scala/akka/AkkaException.scala @@ -33,6 +33,7 @@ object AkkaException { *
  • toLongString which also includes the stack trace
  • * */ +@SerialVersionUID(1L) class AkkaException(message: String = "", cause: Throwable = null) extends RuntimeException(message, cause) with Serializable { val uuid = "%s_%s".format(AkkaException.hostname, newUuid) diff --git a/akka-actor/src/main/scala/akka/actor/ActorPath.scala b/akka-actor/src/main/scala/akka/actor/ActorPath.scala index 8997b119e8..751aa05768 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorPath.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorPath.scala @@ -38,6 +38,7 @@ object ActorPath { * is sorted by path elements FROM RIGHT TO LEFT, where RootActorPath > * ChildActorPath in case the number of elements is different. */ +@SerialVersionUID(1L) sealed trait ActorPath extends Comparable[ActorPath] with Serializable { /** * The Address under which this path can be reached; walks up the tree to @@ -108,6 +109,7 @@ sealed trait ActorPath extends Comparable[ActorPath] with Serializable { * Root of the hierarchy of ActorPaths. There is exactly root per ActorSystem * and node (for remote-enabled or clustered systems). */ +@SerialVersionUID(1L) final case class RootActorPath(address: Address, name: String = "/") extends ActorPath { def parent: ActorPath = this @@ -130,6 +132,7 @@ final case class RootActorPath(address: Address, name: String = "/") extends Act } } +@SerialVersionUID(1L) final class ChildActorPath(val parent: ActorPath, val name: String) extends ActorPath { if (name.indexOf('/') != -1) throw new IllegalArgumentException("/ is a path separator and is not legal in ActorPath names: [%s]" format name) @@ -157,7 +160,7 @@ final class ChildActorPath(val parent: ActorPath, val name: String) extends Acto // TODO research whether this should be cached somehow (might be fast enough, but creates GC pressure) /* - * idea: add one field which holds the total length (because that is known) + * idea: add one field which holds the total length (because that is known) * so that only one String needs to be allocated before traversal; this is * cheaper than any cache */ diff --git a/akka-actor/src/main/scala/akka/actor/ActorRef.scala b/akka-actor/src/main/scala/akka/actor/ActorRef.scala index 38e8ab679f..621e1902b4 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRef.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRef.scala @@ -333,6 +333,7 @@ private[akka] class LocalActorRef private[akka] ( /** * Memento pattern for serializing ActorRefs transparently */ +@SerialVersionUID(1L) case class SerializedActorRef private (path: String) { import akka.serialization.Serialization.currentSystem @@ -397,6 +398,7 @@ private[akka] object MinimalActorRef { case class DeadLetter(message: Any, sender: ActorRef, recipient: ActorRef) private[akka] object DeadLetterActorRef { + @SerialVersionUID(1L) class SerializedDeadLetterActorRef extends Serializable { //TODO implement as Protobuf for performance? @throws(classOf[java.io.ObjectStreamException]) private def readResolve(): AnyRef = Serialization.currentSystem.value.deadLetters diff --git a/akka-actor/src/main/scala/akka/actor/Deployer.scala b/akka-actor/src/main/scala/akka/actor/Deployer.scala index d561c74413..dbd2f92aa0 100644 --- a/akka-actor/src/main/scala/akka/actor/Deployer.scala +++ b/akka-actor/src/main/scala/akka/actor/Deployer.scala @@ -25,6 +25,7 @@ import akka.util.ReflectiveAccess * context.actorOf(someProps, "someName", Deploy(scope = RemoteScope("someOtherNodeName"))) * }}} */ +@SerialVersionUID(1L) final case class Deploy( path: String = "", config: Config = ConfigFactory.empty, @@ -62,6 +63,7 @@ trait Scope { def withFallback(other: Scope): Scope } +@SerialVersionUID(1L) case object LocalScope extends Scope { /** * Java API @@ -74,6 +76,7 @@ case object LocalScope extends Scope { /** * This is the default value and as such allows overrides. */ +@SerialVersionUID(1L) case object NoScopeGiven extends Scope { def withFallback(other: Scope): Scope = other } diff --git a/akka-actor/src/main/scala/akka/actor/Props.scala b/akka-actor/src/main/scala/akka/actor/Props.scala index 74cf45ebe1..ff25324402 100644 --- a/akka-actor/src/main/scala/akka/actor/Props.scala +++ b/akka-actor/src/main/scala/akka/actor/Props.scala @@ -103,6 +103,7 @@ object Props { * Props props = new Props(MyActor.class).withRouter(new RoundRobinRouter(..)); * }}} */ +@SerialVersionUID(1L) case class Props( creator: () ⇒ Actor = Props.defaultCreator, dispatcher: String = Dispatchers.DefaultDispatcherId, diff --git a/akka-actor/src/main/scala/akka/actor/TypedActor.scala b/akka-actor/src/main/scala/akka/actor/TypedActor.scala index 41eba86bbd..c98f6aa55e 100644 --- a/akka-actor/src/main/scala/akka/actor/TypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/TypedActor.scala @@ -429,6 +429,7 @@ object TypedProps { * TypedProps is a TypedActor configuration object, that is thread safe and fully sharable. * It's used in TypedActorFactory.typedActorOf to configure a TypedActor instance. */ +@SerialVersionUID(1L) case class TypedProps[T <: AnyRef] protected[TypedProps] ( interfaces: Seq[Class[_]], creator: () ⇒ T, diff --git a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala index daa7467196..a5ebeb851c 100644 --- a/akka-actor/src/main/scala/akka/actor/UntypedActor.scala +++ b/akka-actor/src/main/scala/akka/actor/UntypedActor.scala @@ -158,4 +158,4 @@ abstract class UntypedActor extends Actor { /** * Factory closure for an UntypedActor, to be used with 'Actors.actorOf(factory)'. */ -trait UntypedActorFactory extends Creator[Actor] +trait UntypedActorFactory extends Creator[Actor] with Serializable diff --git a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala index 0cf6c4a77b..e32631108c 100644 --- a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala +++ b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala @@ -168,7 +168,7 @@ object MessageDispatcher { implicit def defaultDispatcher(implicit system: ActorSystem): MessageDispatcher = system.dispatcher } -abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) extends AbstractMessageDispatcher with Serializable with Executor with ExecutionContext { +abstract class MessageDispatcher(val prerequisites: DispatcherPrerequisites) extends AbstractMessageDispatcher with Executor with ExecutionContext { import MessageDispatcher._ import AbstractMessageDispatcher.{ inhabitantsUpdater, shutdownScheduleUpdater } diff --git a/akka-actor/src/main/scala/akka/routing/Routing.scala b/akka-actor/src/main/scala/akka/routing/Routing.scala index f2e4e9827c..62a00d510e 100644 --- a/akka-actor/src/main/scala/akka/routing/Routing.scala +++ b/akka-actor/src/main/scala/akka/routing/Routing.scala @@ -299,6 +299,7 @@ case class Destination(sender: ActorRef, recipient: ActorRef) * from lower-precendence sources. The decision whether or not to create a * router is taken in the LocalActorRefProvider based on Props. */ +@SerialVersionUID(1L) case object NoRouter extends RouterConfig { def createRoute(props: Props, routeeProvider: RouteeProvider): Route = null override def withFallback(other: RouterConfig): RouterConfig = other @@ -315,6 +316,7 @@ case object FromConfig extends RouterConfig { /** * Java API: Router configuration which has no default, i.e. external configuration is required. */ +@SerialVersionUID(1L) case class FromConfig() extends RouterConfig { def createRoute(props: Props, routeeProvider: RouteeProvider): Route = throw new ConfigurationException("router " + routeeProvider.context.self + " needs external configuration from file (e.g. application.conf)") @@ -345,6 +347,7 @@ object RoundRobinRouter { * @param routees string representation of the actor paths of the routees that will be looked up * using `actorFor` in [[akka.actor.ActorRefProvider]] */ +@SerialVersionUID(1L) case class RoundRobinRouter(nrOfInstances: Int = 0, routees: Iterable[String] = Nil, override val resizer: Option[Resizer] = None) extends RouterConfig with RoundRobinLike { @@ -424,6 +427,7 @@ object RandomRouter { * @param routees string representation of the actor paths of the routees that will be looked up * using `actorFor` in [[akka.actor.ActorRefProvider]] */ +@SerialVersionUID(1L) case class RandomRouter(nrOfInstances: Int = 0, routees: Iterable[String] = Nil, override val resizer: Option[Resizer] = None) extends RouterConfig with RandomLike { @@ -509,6 +513,7 @@ object SmallestMailboxRouter { * @param routees string representation of the actor paths of the routees that will be looked up * using `actorFor` in [[akka.actor.ActorRefProvider]] */ +@SerialVersionUID(1L) case class SmallestMailboxRouter(nrOfInstances: Int = 0, routees: Iterable[String] = Nil, override val resizer: Option[Resizer] = None) extends RouterConfig with SmallestMailboxLike { @@ -653,6 +658,7 @@ object BroadcastRouter { * @param routees string representation of the actor paths of the routees that will be looked up * using `actorFor` in [[akka.actor.ActorRefProvider]] */ +@SerialVersionUID(1L) case class BroadcastRouter(nrOfInstances: Int = 0, routees: Iterable[String] = Nil, override val resizer: Option[Resizer] = None) extends RouterConfig with BroadcastLike { @@ -724,6 +730,7 @@ object ScatterGatherFirstCompletedRouter { * @param routees string representation of the actor paths of the routees that will be looked up * using `actorFor` in [[akka.actor.ActorRefProvider]] */ +@SerialVersionUID(1L) case class ScatterGatherFirstCompletedRouter(nrOfInstances: Int = 0, routees: Iterable[String] = Nil, within: Duration, override val resizer: Option[Resizer] = None) extends RouterConfig with ScatterGatherFirstCompletedLike { diff --git a/akka-actor/src/main/scala/akka/serialization/Format.scala b/akka-actor/src/main/scala/akka/serialization/Format.scala index 41a8eed658..57ae659cec 100644 --- a/akka-actor/src/main/scala/akka/serialization/Format.scala +++ b/akka-actor/src/main/scala/akka/serialization/Format.scala @@ -7,7 +7,7 @@ package akka.serialization import akka.actor.Actor /** - * trait Serializer extends scala.Serializable { + * trait Serializer { * @volatile * var classLoader: Option[ClassLoader] = None * def deepClone(obj: AnyRef): AnyRef = fromBinary(toBinary(obj), Some(obj.getClass)) @@ -74,7 +74,7 @@ trait Format[T <: Actor] extends FromBinary[T] with ToBinary[T] * } * */ -trait StatelessActorFormat[T <: Actor] extends Format[T] with scala.Serializable { +trait StatelessActorFormat[T <: Actor] extends Format[T] { def fromBinary(bytes: Array[Byte], act: T) = act def toBinary(ac: T) = Array.empty[Byte] @@ -94,7 +94,7 @@ trait StatelessActorFormat[T <: Actor] extends Format[T] with scala.Serializable * } * */ -trait SerializerBasedActorFormat[T <: Actor] extends Format[T] with scala.Serializable { +trait SerializerBasedActorFormat[T <: Actor] extends Format[T] { val serializer: Serializer def fromBinary(bytes: Array[Byte], act: T) = serializer.fromBinary(bytes, Some(act.getClass)).asInstanceOf[T] diff --git a/akka-actor/src/main/scala/akka/serialization/Serializer.scala b/akka-actor/src/main/scala/akka/serialization/Serializer.scala index ffe7f50de9..5a9ba97a98 100644 --- a/akka-actor/src/main/scala/akka/serialization/Serializer.scala +++ b/akka-actor/src/main/scala/akka/serialization/Serializer.scala @@ -10,7 +10,7 @@ import akka.util.ClassLoaderObjectInputStream /** * A Serializer represents a bimap between an object and an array of bytes representing that object */ -trait Serializer extends scala.Serializable { +trait Serializer { /** * Completely unique value to identify this implementation of Serializer, used to optimize network traffic * Values from 0 to 16 is reserved for Akka internal usage diff --git a/akka-actor/src/main/scala/akka/util/Duration.scala b/akka-actor/src/main/scala/akka/util/Duration.scala index 2b6aae1eb3..176960b067 100644 --- a/akka-actor/src/main/scala/akka/util/Duration.scala +++ b/akka-actor/src/main/scala/akka/util/Duration.scala @@ -8,6 +8,7 @@ import java.util.concurrent.TimeUnit import TimeUnit._ import java.lang.{ Double ⇒ JDouble } +@SerialVersionUID(1L) case class Deadline private (time: Duration) { def +(other: Duration): Deadline = copy(time = time + other) def -(other: Duration): Deadline = copy(time = time - other) @@ -232,6 +233,7 @@ object Duration { * val d3 = d2 + 1.millisecond * */ +@SerialVersionUID(1L) abstract class Duration extends Serializable with Ordered[Duration] { def length: Long def unit: TimeUnit @@ -276,6 +278,7 @@ object FiniteDuration { } } +@SerialVersionUID(1L) class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration { import Duration._ @@ -525,6 +528,7 @@ class DurationDouble(d: Double) { def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS)) } +@SerialVersionUID(1L) case class Timeout(duration: Duration) { def this(timeout: Long) = this(Duration(timeout, TimeUnit.MILLISECONDS)) def this(length: Long, unit: TimeUnit) = this(Duration(length, unit)) diff --git a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala index 872be5aa41..36ed73c769 100644 --- a/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala +++ b/akka-remote/src/main/scala/akka/remote/RemoteActorRefProvider.scala @@ -222,6 +222,7 @@ trait RemoteRef extends ActorRefScope { * Remote ActorRef that is used when referencing the Actor on a different node than its "home" node. * This reference is network-aware (remembers its origin) and immutable. */ +@SerialVersionUID(1L) private[akka] class RemoteActorRef private[akka] ( val provider: RemoteActorRefProvider, remote: RemoteTransport,