From c0e0e8efae2b56cee0fe8adad443ddf63d8ed2c5 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Mon, 20 Aug 2012 14:52:53 +0200 Subject: [PATCH 1/7] Migration guide for 2.0 to 2.1, see #2406 * Based the items and code snippets on diff of rst doc sample code --- akka-docs/project/index.rst | 2 +- .../project/migration-guide-1.3.x-2.0.x.rst | 899 ------------------ .../project/migration-guide-2.0.x-2.1.x.rst | 245 +++++ akka-docs/project/migration-guides.rst | 9 - 4 files changed, 246 insertions(+), 909 deletions(-) delete mode 100644 akka-docs/project/migration-guide-1.3.x-2.0.x.rst create mode 100644 akka-docs/project/migration-guide-2.0.x-2.1.x.rst delete mode 100644 akka-docs/project/migration-guides.rst diff --git a/akka-docs/project/index.rst b/akka-docs/project/index.rst index b814fd07f1..8260032b35 100644 --- a/akka-docs/project/index.rst +++ b/akka-docs/project/index.rst @@ -4,7 +4,7 @@ Project Information .. toctree:: :maxdepth: 2 - migration-guides + migration-guide-2.0.x-2.1.x release-notes scaladoc other-doc diff --git a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst deleted file mode 100644 index 738119adb0..0000000000 --- a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst +++ /dev/null @@ -1,899 +0,0 @@ -.. _migration-2.0: - -################################ - Migration Guide 1.3.x to 2.0.x -################################ - -The 2.0 release contains several new features which require source-level -changes in client code. This API cleanup is planned to be the last one for a -significant amount of time. - -New Concepts -============ - -First you should take some time to understand the new concepts of :ref:`actor-systems`, -:ref:`supervision`, and :ref:`addressing`. - -Migration Kit -============= - -Nobody likes a big refactoring that takes several days to complete until -anything is able to run again. Therefore we provide a migration kit that -makes it possible to do the migration changes in smaller steps. - -The migration kit only covers the most common usage of Akka. It is not intended -as a final solution. The whole migration kit is marked as deprecated and will -be removed in Akka 2.1. - -The migration kit is provided in separate jar files. Add the following dependency:: - - "com.typesafe.akka" % "akka-actor-migration" % "2.0" - -The first step of the migration is to do some trivial replacements. -Search and replace the following (be careful with the non qualified names): - -==================================== ==================================== -Search Replace with -==================================== ==================================== -``akka.actor.Actor`` ``akka.actor.OldActor`` -``extends Actor`` ``extends OldActor`` -``akka.actor.Scheduler`` ``akka.actor.OldScheduler`` -``Scheduler`` ``OldScheduler`` -``akka.event.EventHandler`` ``akka.event.OldEventHandler`` -``EventHandler`` ``OldEventHandler`` -``akka.config.Config`` ``akka.config.OldConfig`` -``Config`` ``OldConfig`` -==================================== ==================================== - -For Scala users the migration kit also contains some implicit conversions to be -able to use some old methods. These conversions are useful from tests or other -code used outside actors. - -:: - - import akka.migration._ - -Thereafter you need to fix compilation errors that are not handled by the migration -kit, such as: - -* Definition of supervisors -* Definition of dispatchers -* ActorRegistry - -When everything compiles you continue by replacing/removing the ``OldXxx`` classes -one-by-one from the migration kit with appropriate migration. - -When using the migration kit there will be one global actor system, which loads -the configuration ``akka.conf`` from the same locations as in Akka 1.x. -This means that while you are using the migration kit you should not create your -own ``ActorSystem``, but instead use the ``akka.actor.GlobalActorSystem``. -In order to voluntarily exit the JVM you must ``shutdown`` the ``GlobalActorSystem`` -Last task of the migration would be to create your own ``ActorSystem``. - - -Unordered Collection of Migration Items -======================================= - -Actors ------- - -Creating and starting actors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Actors are created by passing in a ``Props`` instance into the actorOf factory method in -a ``ActorRefProvider``, which is the ``ActorSystem`` or ``ActorContext``. -Use the system to create top level actors. Use the context to -create actors from other actors. The difference is how the supervisor hierarchy is arranged. -When using the context the current actor will be supervisor of the created child actor. -When using the system it will be a top level actor, that is supervised by the system -(internal guardian actor). - -``ActorRef.start()`` has been removed. Actors are now started automatically when created. -Remove all invocations of ``ActorRef.start()``. - -v1.3:: - - val myActor = Actor.actorOf[MyActor] - myActor.start() - -v2.0:: - - // top level actor - val firstActor = system.actorOf(Props[FirstActor], name = "first") - - // child actor - class FirstActor extends Actor { - val myActor = context.actorOf(Props[MyActor], name = "myactor") - -Documentation: - - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -Stopping actors -^^^^^^^^^^^^^^^ - -``ActorRef.stop()`` has been moved. Use ``ActorSystem`` or ``ActorContext`` to stop actors. - -v1.3:: - - actorRef.stop() - self.stop() - actorRef ! PoisonPill - -v2.0:: - - context.stop(someChild) - context.stop(self) - system.stop(actorRef) - actorRef ! PoisonPill - -*Stop all actors* - -v1.3:: - - ActorRegistry.shutdownAll() - -v2.0:: - - system.shutdown() // from outside of this system - context.system.shutdown() // from inside any actor - -Documentation: - - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -Identifying Actors -^^^^^^^^^^^^^^^^^^ - -In v1.3 actors have ``uuid`` and ``id`` field. In v2.0 each actor has a unique logical ``path``. - -The ``ActorRegistry`` has been replaced by actor paths and lookup with -``actorFor`` in ``ActorRefProvider`` (``ActorSystem`` or ``ActorContext``). It -is no longer possible to obtain references to all actors being implemented by a -certain class (the reason being that this property is not known yet when an -:class:`ActorRef` is created because instantiation of the actor itself is -asynchronous). - -v1.3:: - - val actor = Actor.registry.actorFor(uuid) - val actors = Actor.registry.actorsFor(id) - -v2.0:: - - val actor = context.actorFor("/user/serviceA/aggregator") - -Documentation: - - * :ref:`addressing` - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -Reply to messages -^^^^^^^^^^^^^^^^^ - -``self.channel`` has been replaced with unified reply mechanism using ``sender`` (Scala) -or ``getSender()`` (Java). This works for both tell (!) and ask (?). Sending to -an actor reference never throws an exception, hence :meth:`tryTell` and -:meth:`tryReply` are removed. - -v1.3:: - - self.channel ! result - self.channel tryTell result - self.reply(result) - self.tryReply(result) - -v2.0:: - - sender ! result - -Documentation: - - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -``ActorRef.ask()`` -^^^^^^^^^^^^^^^^^^ - -The mechanism for collecting an actor’s reply in a :class:`Future` has been -reworked for better location transparency: it uses an actor under the hood. -This actor needs to be disposable by the garbage collector in case no reply is -ever received, and the decision is based upon a timeout. This timeout -determines when the actor will stop itself and hence closes the window for a -reply to be received; it is independent of the timeout applied when awaiting -completion of the :class:`Future`, however, the actor will complete the -:class:`Future` with an :class:`AskTimeoutException` when it stops itself. - -Since there is no good library default value for the ask-timeout, specification -of a timeout is required for all usages as shown below. - -Also, since the ``ask`` feature is coupling futures and actors, it is no longer -offered on the :class:`ActorRef` itself, but instead as a use pattern to be -imported. While Scala’s implicit conversions enable transparent replacement, -Java code will have to be changed by more than just adding an import statement. - -v1.3:: - - actorRef ? message // Scala - actorRef.ask(message, timeout); // Java - -v2.0 (Scala):: - - import akka.pattern.ask - - implicit val timeout: Timeout = ... - actorRef ? message // uses implicit timeout - actorRef ask message // uses implicit timeout - actorRef.ask(message)(timeout) // uses explicit timeout - ask(actorRef, message) // uses implicit timeout - ask(actorRef, message)(timeout) // uses explicit timeout - -v2.0 (Java):: - - import akka.pattern.Patterns; - - Patterns.ask(actorRef, message, timeout) - -Documentation: - - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -``ActorRef.?(msg, timeout)`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -This method has a dangerous overlap with ``ActorRef.?(msg)(implicit timeout)`` -due to the fact that Scala allows to pass a :class:`Tuple` in place of the -message without requiring extra parentheses:: - - actor ? (1, "hallo") // will send a tuple - actor ? (1, Timeout()) // will send 1 with an explicit timeout - -To remove this ambiguity, the latter variant is removed in version 2.0. If you -were using it before, it will now send tuples where that is not desired. In -order to correct all places in the code where this happens, simply import -``akka.migration.ask`` instead of ``akka.pattern.ask`` to obtain a variant -which will give deprecation warnings where the old method signature is used:: - - import akka.migration.ask - - actor ? (1, Timeout(2 seconds)) // will give deprecation warning - -``UntypedActor.getContext()`` (Java API only) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -``getContext()`` in the Java API for UntypedActor is renamed to -``getSelf()``. - -v1.3:: - - actorRef.tell("Hello", getContext()); - -v2.0:: - - actorRef.tell("Hello", getSelf()); - -Documentation: - - * :ref:`untyped-actors-java` - -Configuration -^^^^^^^^^^^^^ - -A new, more powerful, configuration utility has been implemented. The format of the -configuration file is very similar to the format in v1.3. In addition it also supports -configuration files in json and properties format. The syntax is described in the -`HOCON `_ specification. - -v1.3:: - - include "other.conf" - - akka { - event-handler-level = "DEBUG" - } - -v2.0:: - - include "other" - - akka { - loglevel = "DEBUG" - } - -In v1.3 the default name of the configuration file was ``akka.conf``. -In v2.0 the default name is ``application.conf``. It is still loaded from classpath -or can be specified with java System properties (``-D`` command line arguments). - -v1.3:: - - -Dakka.config= - -Dakka.output.config.source=on - -v2.0:: - - -Dconfig.file= - -Dakka.log-config-on-start=on - - -Several configuration properties have been changed, such as: - - * ``akka.event-handler-level`` => ``akka.loglevel`` - * dispatcher ``type`` values are changed - * ``akka.actor.throughput`` => ``akka.actor.default-dispatcher.throughput`` - * ``akka.remote.layer`` => ``akka.remote.transport`` - * the global ``time-unit`` property is removed, all durations are specified with duration unit in the property value, ``timeout = 5s`` - -Verify used configuration properties against the reference :ref:`configuration`. - -Documentation: - - * :ref:`configuration` - -Logging -^^^^^^^ - -EventHandler API has been replaced by LoggingAdapter, which publish log messages -to the event bus. You can still plugin your own actor as event listener with the -``akka.event-handlers`` configuration property. - -v1.3:: - - EventHandler.error(exception, this, message) - EventHandler.warning(this, message) - EventHandler.info(this, message) - EventHandler.debug(this, message) - EventHandler.debug(this, "Processing took %s ms".format(duration)) - -v2.0:: - - import akka.event.Logging - - val log = Logging(context.system, this) // will include system name in message source - val log = Logging(system.eventStream, getClass.getName) // will not include system name - log.error(exception, message) - log.warning(message) - log.info(message) - log.debug(message) - log.debug("Processing took {} ms", duration) - -Documentation: - - * :ref:`logging-scala` - * :ref:`logging-java` - * :ref:`event-bus-scala` - * :ref:`event-bus-java` - - -Scheduler -^^^^^^^^^ - -The functionality of the scheduler is identical, but the API is slightly adjusted. - -v1.3:: - - //Schedules to send the "foo"-message to the testActor after 50ms - Scheduler.scheduleOnce(testActor, "foo", 50L, TimeUnit.MILLISECONDS) - - // Schedules periodic send of "foo"-message to the testActor after 1s inital delay, - // and then with 200ms between successive sends - Scheduler.schedule(testActor, "foo", 1000L, 200L, TimeUnit.MILLISECONDS) - - // Schedules a function to be executed (send the current time) to the testActor after 50ms - Scheduler.scheduleOnce({testActor ! System.currentTimeMillis}, 50L, TimeUnit.MILLISECONDS) - -v2.0:: - - //Schedules to send the "foo"-message to the testActor after 50ms - system.scheduler.scheduleOnce(50 milliseconds, testActor, "foo") - - // Schedules periodic send of "foo"-message to the testActor after 1s inital delay, - // and then with 200ms between successive sends - system.scheduler.schedule(1 second, 200 milliseconds, testActor, "foo") - - // Schedules a function to be executed (send the current time) to the testActor after 50ms - system.scheduler.scheduleOnce(50 milliseconds) { - testActor ! System.currentTimeMillis - } - - -The internal implementation of the scheduler is changed from -``java.util.concurrent.ScheduledExecutorService`` to a variant of -``org.jboss.netty.util.HashedWheelTimer``. - -Documentation: - - * :ref:`scheduler-scala` - * :ref:`scheduler-java` - -Supervision -^^^^^^^^^^^ - -Akka v2.0 implements parental supervision. Actors can only be created by other actors — where the top-level -actor is provided by the library — and each created actor is supervised by its parent. -In contrast to the special supervision relationship between parent and child, each actor may monitor any -other actor for termination. - -v1.3:: - - self.link(actorRef) - self.unlink(actorRef) - -v2.0:: - - class WatchActor extends Actor { - val actorRef = ... - // Terminated message will be delivered when the actorRef actor - // is stopped - context.watch(actorRef) - - val supervisedChild = context.actorOf(Props[ChildActor]) - - def receive = { - case Terminated(`actorRef`) ⇒ ... - } - } - -Note that ``link`` in v1.3 established a supervision relation, which ``watch`` doesn't. -``watch`` is only a way to get notification, ``Terminated`` message, when the monitored -actor has been stopped. - -*Refererence to the supervisor* - -v1.3:: - - self.supervisor - -v2.0:: - - context.parent - -*Supervisor Strategy* - -v1.3:: - - val supervisor = Supervisor( - SupervisorConfig( - OneForOneStrategy(List(classOf[Exception]), 3, 1000), - Supervise( - actorOf[MyActor1], - Permanent) :: - Supervise( - actorOf[MyActor2], - Permanent) :: - Nil)) - -v2.0:: - - class MyActor extends Actor { - override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { - case _: ArithmeticException ⇒ Resume - case _: NullPointerException ⇒ Restart - case _: IllegalArgumentException ⇒ Stop - case _: Exception ⇒ Escalate - } - - def receive = { - case x => - } - } - -Documentation: - - * :ref:`supervision` - * :ref:`fault-tolerance-java` - * :ref:`fault-tolerance-scala` - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -Dispatchers -^^^^^^^^^^^ - -Dispatchers are defined in configuration instead of in code. - -v1.3:: - - // in code - val myDispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher(name) - .withNewThreadPoolWithLinkedBlockingQueueWithCapacity(100) - .setCorePoolSize(16) - .setMaxPoolSize(128) - .setKeepAliveTimeInMillis(60000) - .build - -v2.0:: - - // in config - my-dispatcher { - type = Dispatcher - core-pool-size-factor = 8.0 - max-pool-size-factor = 16.0 - mailbox-capacity = 100 - } - -The dispatcher is assigned to the actor in a different way. - -v1.3:: - - actorRef.dispatcher = MyGlobals.myDispatcher - self.dispatcher = MyGlobals.myDispatcher - -v2.0:: - - val myActor = system.actorOf(Props[MyActor].withDispatcher("my-dispatcher"), "myactor") - -Documentation: - - * :ref:`dispatchers-java` - * :ref:`dispatchers-scala` - -Spawn -^^^^^ - -``spawn`` has been removed and should be replaced by creating a :class:`Future`. Be careful to not -access any shared mutable state closed over by the body. - -Scala:: - - Future { doSomething() } // will be executed asynchronously - -Java:: - - Futures.future(new Callable() { - public String call() { - doSomething(); - } - }, executionContext); - -Documentation: - - * :ref:`futures-scala` - * :ref:`futures-java` - * :ref:`jmm` - -HotSwap -^^^^^^^ - -In v2.0 ``become`` and ``unbecome`` metods are located in ``ActorContext``, i.e. ``context.become`` and ``context.unbecome``. - -The special ``HotSwap`` and ``RevertHotswap`` messages in v1.3 has been removed. Similar can be -implemented with your own message and using ``context.become`` and ``context.unbecome`` -in the actor receiving the message. The rationale is that being able to replace -any actor’s behavior generically is not a good idea because actor implementors -would have no way to defend against that; hence the change to lay it into the -hands of the actor itself. - - * :ref:`actors-scala` - * :ref:`untyped-actors-java` - -Routing -^^^^^^^ - -Routing has been redesign with improved performance and additional features as a result. - -v1.3:: - - class MyLoadBalancer extends Actor with LoadBalancer { - val pinger = actorOf(new Actor { def receive = { case x => println("Pinger: " + x) } }).start() - val ponger = actorOf(new Actor { def receive = { case x => println("Ponger: " + x) } }).start() - - val seq = new CyclicIterator[ActorRef](List(pinger,ponger)) - } - val loadbalancer = actorOf[MyLoadBalancer].start() - -v2.0:: - - val pinger = system.actorOf(Props(new Actor { def receive = { case x ⇒ println("Pinger: " + x) } })) - val ponger = system.actorOf(Props(new Actor { def receive = { case x ⇒ println("Ponger: " + x) } })) - val loadbalancer = system.actorOf(Props().withRouter(RoundRobinRouter(Seq(pinger, ponger)))) - -Documentation: - - * :ref:`routing-scala` - * :ref:`routing-java` - -ActorPool -^^^^^^^^^ - -The ActorPool has been replaced by dynamically resizable routers. - -v1.3:: - - class TestPool extends Actor with DefaultActorPool - with BoundedCapacityStrategy - with ActiveFuturesPressureCapacitor - with SmallestMailboxSelector - with BasicNoBackoffFilter - { - def receive = _route - def lowerBound = 2 - def upperBound = 4 - def rampupRate = 0.1 - def partialFill = true - def selectionCount = 1 - def instance = actorOf[ExampleActor] - } - -v2.0:: - - // in configuration - akka.actor.deployment { - /router2 { - router = round-robin - resizer { - lower-bound = 2 - upper-bound = 15 - } - } - } - - // in code - val router2 = system.actorOf(Props[ExampleActor].withRouter(FromConfig()) - -Documentation: - - * :ref:`routing-scala` - * :ref:`routing-java` - -STM ---- - -In Akka v2.0 `ScalaSTM`_ is used rather than Multiverse. - -.. _ScalaSTM: http://nbronson.github.com/scala-stm/ - -Agent and Transactor have been ported to ScalaSTM. The API's for Agent and -Transactor are basically the same, other than integration with ScalaSTM. See: - - * :ref:`agents-scala` - * :ref:`agents-java` - * :ref:`transactors-scala` - * :ref:`transactors-java` - -Imports -^^^^^^^ - -Scala -~~~~~ - -To use ScalaSTM the import from Scala is:: - - import scala.concurrent.stm._ - -Java -~~~~ - -For Java there is a special helper object with Java-friendly methods:: - - import scala.concurrent.stm.japi.STM; - -These methods can also be statically imported:: - - import static scala.concurrent.stm.japi.STM.*; - -Other imports that are needed are in the stm package, particularly ``Ref``:: - - import scala.concurrent.stm.Ref; - -Transactions -^^^^^^^^^^^^ - -Scala -~~~~~ - -Both v1.3 and v2.0 provide an ``atomic`` block, however, the ScalaSTM ``atomic`` -is a function from ``InTxn`` to return type. - -v1.3:: - - atomic { - // do something in transaction - } - -v2.0:: - - atomic { implicit txn => - // do something in transaction - } - -Note that in ScalaSTM the ``InTxn`` in the atomic function is usually marked as -implicit as transactional references require an implicit ``InTxn`` on all -methods. That is, the transaction is statically required and it is a -compile-time warning to use a reference without a transaction. There is also a -``Ref.View`` for operations without requiring an ``InTxn`` statically. See below -for more information. - -Java -~~~~ - -In the ScalaSTM Java API helpers there are atomic methods which accept -``java.lang.Runnable`` and ``java.util.concurrent.Callable``. - -v1.3:: - - new Atomic() { - public Object atomically() { - // in transaction - return null; - } - }.execute(); - - SomeObject result = new Atomic() { - public SomeObject atomically() { - // in transaction - return ...; - } - }.execute(); - -v2.0:: - - import static scala.concurrent.stm.japi.STM.atomic; - import java.util.concurrent.Callable; - - atomic(new Runnable() { - public void run() { - // in transaction - } - }); - - SomeObject result = atomic(new Callable() { - public SomeObject call() { - // in transaction - return ...; - } - }); - -Ref -^^^ - -Scala -~~~~~ - -Other than the import, creating a Ref is basically identical between Akka STM in -v1.3 and ScalaSTM used in v2.0. - -v1.3:: - - val ref = Ref(0) - -v2.0:: - - val ref = Ref(0) - -The API for Ref is similar. For example: - -v1.3:: - - ref.get // get current value - ref() // same as get - - ref.set(1) // set to new value, return old value - ref() = 1 // same as set - ref.swap(2) // same as set - - ref alter { _ + 1 } // apply a function, return new value - -v2.0:: - - ref.get // get current value - ref() // same as get - - ref.set(1) // set to new value, return nothing - ref() = 1 // same as set - ref.swap(2) // set and return old value - - ref transform { _ + 1 } // apply function, return nothing - - ref transformIfDefined { case 1 => 2 } // apply partial function if defined - -Ref.View -^^^^^^^^ - -In v1.3 using a ``Ref`` method outside of a transaction would automatically -create a single-operation transaction. In v2.0 (in ScalaSTM) there is a -``Ref.View`` which provides methods without requiring a current -transaction. - -Scala -~~~~~ - -The ``Ref.View`` can be accessed with the ``single`` method:: - - ref.single() // returns current value - ref.single() = 1 // set new value - - // with atomic this would be: - - atomic { implicit t => ref() } - atomic { implicit t => ref() = 1 } - -Java -~~~~ - -As ``Ref.View`` in ScalaSTM does not require implicit transactions, this is more -easily used from Java. ``Ref`` could be used, but requires explicit threading of -transactions. There are helper methods in ``japi.STM`` for creating ``Ref.View`` -references. - -v1.3:: - - Ref ref = new Ref(0); - -v2.0:: - - Ref.View ref = STM.newRef(0); - -The ``set`` and ``get`` methods work the same way for both versions. - -v1.3:: - - ref.get(); // get current value - ref.set(1); // set new value - -v2.0:: - - ref.get(); // get current value - ref.set(1); // set new value - -There are also ``transform``, ``getAndTransform``, and ``transformAndGet`` -methods in ``japi.STM`` which accept ``japi.STM.Transformer`` objects. - -There are ``increment`` helper methods for ``Ref.View`` and -``Ref.View`` references. - -Transaction lifecycle callbacks -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Scala -~~~~~ - -It is also possible to hook into the transaction lifecycle in ScalaSTM. See the -ScalaSTM documentation for the full range of possibilities. - -v1.3:: - - atomic { - deferred { - // executes when transaction commits - } - compensating { - // executes when transaction aborts - } - } - -v2.0:: - - atomic { implicit txn => - txn.afterCommit { txnStatus => - // executes when transaction commits - } - txn.afterRollback { txnStatus => - // executes when transaction rolls back - } - } - -Java -~~~~ - -Rather than using the ``deferred`` and ``compensating`` methods in -``akka.stm.StmUtils``, use the ``afterCommit`` and ``afterRollback`` methods in -``scala.concurrent.stm.japi.STM``, which behave in the same way and accept -``Runnable``. - -Transactional Datastructures -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In ScalaSTM see ``TMap``, ``TSet``, and ``TArray`` for transactional -datastructures. - -There are helper methods for creating these from Java in ``japi.STM``: -``newTMap``, ``newTSet``, and ``newTArray``. These datastructures implement the -``scala.collection`` interfaces and can also be used from Java with Scala's -``JavaConversions``. There are helper methods that apply the conversions, -returning ``java.util`` ``Map``, ``Set``, and ``List``: ``newMap``, ``newSet``, -and ``newArrayAsList``. - - diff --git a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst new file mode 100644 index 0000000000..a76e1712b3 --- /dev/null +++ b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst @@ -0,0 +1,245 @@ +.. _migration-2.1: + +################################ + Migration Guide 2.0.x to 2.1.x +################################ + +The 2.1 release contains several structural changes that require some +simple, mechanical source-level changes in client code. Several things have +been moved to Scala standard library, such as ``Future``. + +Scala Version +============= + +Change your project build and dependencies to Scala version: + +.. parsed-literal:: + + |scalaVersion| + +Config Dependency +================= + +`Typesafe config `_ library is a normal +dependency of akka-actor and it is no longer embedded in ``akka-actor.jar``. +If your are using a build tool with dependency resolution, such as sbt or maven you +will not notice the difference, but if you have manually constructed classpaths +you need to add `config-0.5.0.jar `_. + +Pieces Moved to Scala Standard Library +====================================== + +Change the following import statements. + +==================================== ==================================== +Search Replace with +==================================== ==================================== +``akka.dispatch.Await`` ``scala.concurrent.Await`` +``akka.dispatch.Future`` ``scala.concurrent.Future`` +``akka.dispatch.Promise`` ``scala.concurrent.Promise`` +``akka.dispatch.Promise`` ``scala.concurrent.Promise`` +``akka.dispatch.ExecutionContext`` ``scala.concurrent.ExecutionContext`` +``akka.util.Duration`` ``scala.concurrent.util.Duration`` +``akka.util.duration`` ``scala.concurrent.util.duration`` +``akka.util.Deadline`` ``scala.concurrent.util.Deadline`` +``akka.util.NonFatal`` ``scala.util.control.NonFatal`` +``akka.japi.Util.manifest`` ``akka.japi.Util.classTag`` +==================================== ==================================== + +Scheduler Dispatcher +==================== + +The ``ExecutionContext`` to use for running scheduled tasks must be specified. + +Scala: + +:: + + import context.dispatcher // Use this Actors' Dispatcher as ExecutionContext + context.system.scheduler.scheduleOnce(10 seconds, self, Reconnect) + + import system.dispatcher // Use ActorSystem's default Dispatcher as ExecutionContext + system.scheduler.scheduleOnce(50 milliseconds) { + testActor ! System.currentTimeMillis + } + +Java: +:: + + // Use this Actors' Dispatcher as ExecutionContext + getContext().system().scheduler().scheduleOnce(Duration.parse("10 seconds", getSelf(), + new Reconnect(), getContext().getDispatcher()); + + // Use ActorSystem's default Dispatcher as ExecutionContext + system.scheduler().scheduleOnce(Duration.create(50, TimeUnit.MILLISECONDS), new Runnable() { + @Override + public void run() { + testActor.tell(System.currentTimeMillis()); + } + }, system.dispatcher()); + + +API Changes of Future - Scala +============================= + +v2.0:: + + def square(i: Int): Future[Int] = Promise successful i * i + +v2.1:: + + def square(i: Int): Future[Int] = Promise.successful(i * i).future + +v2.0:: + + val failedFilter = future1.filter(_ % 2 == 1).recover { + case m: MatchError => //When filter fails, it will have a MatchError + } + +v2.1:: + + val failedFilter = future1.filter(_ % 2 == 1).recover { + case m: NoSuchElementException => //When filter fails, it will have a java.util.NoSuchElementException + } + + + +API Changes of Future - Java +============================ + +v2.0:: + + ExecutorService yourExecutorServiceGoesHere = Executors.newSingleThreadExecutor(); + ExecutionContextExecutorService ec = + ExecutionContexts.fromExecutorService(yourExecutorServiceGoesHere); + + //Use ec with your Futures + Future f1 = Futures.successful("foo", ec); + + // Then you shut the ec down somewhere at the end of your program/application. + ec.shutdown(); + +v2.1:: + + ExecutorService yourExecutorServiceGoesHere = Executors.newSingleThreadExecutor(); + ExecutionContext ec = + ExecutionContexts.fromExecutorService(yourExecutorServiceGoesHere); + + //Use ec with your Futures + Future f1 = Futures.successful("foo"); + + // Then you shut the ExecutorService down somewhere at the end of your program/application. + yourExecutorServiceGoesHere.shutdown(); + +v2.0:: + + Future f1 = future(new Callable() { + public String call() { + return "Hello" + "World"; + } + }, system.dispatcher()); + +v2.1:: + + final ExecutionContext ec = system.dispatcher(); + + Future f1 = future(new Callable() { + public String call() { + return "Hello" + "World"; + } + }, ec); + +v2.0:: + + Future future1 = Futures.successful("value", system.dispatcher()).andThen(new OnComplete() { + public void onComplete(Throwable failure, String result) { + if (failure != null) + sendToIssueTracker(failure); + } + }).andThen(new OnComplete() { + public void onComplete(Throwable failure, String result) { + if (result != null) + sendToTheInternetz(result); + } + }); + +v2.1:: + + final ExecutionContext ec = system.dispatcher(); + Future future1 = Futures.successful("value").andThen(new OnComplete() { + public void onComplete(Throwable failure, String result) { + if (failure != null) + sendToIssueTracker(failure); + } + }, ec).andThen(new OnComplete() { + public void onComplete(Throwable failure, String result) { + if (result != null) + sendToTheInternetz(result); + } + }, ec); + +Empty Props +=========== + +v2.0 Scala:: + + val router2 = system.actorOf(Props().withRouter( + RoundRobinRouter(routees = routees))) + +v2.1 Scala:: + + val router2 = system.actorOf(Props[ExampleActor1].withRouter( + RoundRobinRouter(routees = routees))) + +v2.0 Java:: + + ActorRef router2 = system.actorOf(new Props(ExampleActor.class).withRouter(RoundRobinRouter.create(routees))); + +v2.1 Java:: + + ActorRef router2 = system.actorOf(new Props().withRouter(RoundRobinRouter.create(routees))); + +Failing Send +============ + +When failing to send to an actor with bounded or durable mailbox the message will +silently be delivered to deadletters instead of throwing an exception. + +Graceful Stop Exception +======================= + +If the target actor of ``akka.pattern.gracefulStop`` isn't terminated within the +timeout the ``Future`` is completed with failure ``akka.pattern.AskTimeoutException``. +In 2.0 it was ``akka.actor.ActorTimeoutException``. + +PoisonPill and ReceiveTimeout - Java +==================================== + +v2.0:: + + import static akka.actor.Actors.*; + + if (msg.equals("done")) { + myActor.tell(poisonPill()); + } else if (msg == Actors.receiveTimeout()) { + +v2.1:: + + import akka.actor.PoisonPill; + import akka.actor.ReceiveTimeout; + + if (msg.equals("done")) { + myActor.tell(PoisonPill.getInstance()); + } else if (msg == ReceiveTimeout.getInstance()) { + + +Testkit Probe Reply +=================== + +v2.0:: + + probe.sender ! "world" + +v2.1:: + + probe.reply("world") \ No newline at end of file diff --git a/akka-docs/project/migration-guides.rst b/akka-docs/project/migration-guides.rst deleted file mode 100644 index 090e316c22..0000000000 --- a/akka-docs/project/migration-guides.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _migration: - -Migration Guides -================ - -.. toctree:: - :maxdepth: 1 - - migration-guide-1.3.x-2.0.x From 00a28302a1eb2a603c79ae2daf7b040f17f77550 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 21 Aug 2012 10:14:50 +0200 Subject: [PATCH 2/7] Fix erroneous links page --- akka-docs/project/links.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/akka-docs/project/links.rst b/akka-docs/project/links.rst index e4f1017828..3002dc1216 100644 --- a/akka-docs/project/links.rst +++ b/akka-docs/project/links.rst @@ -1,35 +1,35 @@ .. _support: -`Commercial Support `__ -============================================ +Commercial Support +================== Commercial support is provided by `Typesafe `_. Akka is now part of the `Typesafe Stack `_. -`Mailing List `_ -========================================================== +Mailing List +============ `Akka User Google Group `_ `Akka Developer Google Group `_ -`Downloads `_ -======================================== +Downloads +========= ``_ -`Source Code `_ -============================================== +Source Code +=========== Akka uses Git and is hosted at `Github `_. * Akka: clone the Akka repository from ``_ -`Releases Repository `_ -====================================================== +Releases Repository +=================== The Akka Maven repository can be found at http://repo.akka.io/releases/. @@ -49,8 +49,8 @@ underlying repositories directly. * http://databinder.net/repo/ -`Snapshots Repository `_ -======================================================== +Snapshots Repository +==================== Nightly builds are available in http://repo.akka.io/snapshots/ and proxied through http://repo.typesafe.com/typesafe/snapshots/ as both ``SNAPSHOT`` and From fc66c7a81f0fcd0d49e9633f5582ab931cbe751e Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 21 Aug 2012 10:24:21 +0200 Subject: [PATCH 3/7] Add back migration-guide-1.3.x-2.0.x with link to 2.0 docs, see #2406 --- akka-docs/project/index.rst | 2 +- akka-docs/project/migration-guide-1.3.x-2.0.x.rst | 10 ++++++++++ akka-docs/project/migration-guide-2.0.x-2.1.x.rst | 3 +++ akka-docs/project/migration-guides.rst | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 akka-docs/project/migration-guide-1.3.x-2.0.x.rst create mode 100644 akka-docs/project/migration-guides.rst diff --git a/akka-docs/project/index.rst b/akka-docs/project/index.rst index 8260032b35..b814fd07f1 100644 --- a/akka-docs/project/index.rst +++ b/akka-docs/project/index.rst @@ -4,7 +4,7 @@ Project Information .. toctree:: :maxdepth: 2 - migration-guide-2.0.x-2.1.x + migration-guides release-notes scaladoc other-doc diff --git a/akka-docs/project/migration-guide-1.3.x-2.0.x.rst b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst new file mode 100644 index 0000000000..58a8a75435 --- /dev/null +++ b/akka-docs/project/migration-guide-1.3.x-2.0.x.rst @@ -0,0 +1,10 @@ +.. _migration-2.0: + +################################ + Migration Guide 1.3.x to 2.0.x +################################ + +Migration from 1.3.x to 2.0.x is described in the +`documentation of 2.0 `_. + + diff --git a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst index a76e1712b3..3a9355c998 100644 --- a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst +++ b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst @@ -8,6 +8,9 @@ The 2.1 release contains several structural changes that require some simple, mechanical source-level changes in client code. Several things have been moved to Scala standard library, such as ``Future``. +When migrating from 1.3.x to 2.1.x you should first follow the instructions for +migrating `1.3.x to 2.0.x `_. + Scala Version ============= diff --git a/akka-docs/project/migration-guides.rst b/akka-docs/project/migration-guides.rst new file mode 100644 index 0000000000..79e2f7b8cc --- /dev/null +++ b/akka-docs/project/migration-guides.rst @@ -0,0 +1,10 @@ +.. _migration: + +Migration Guides +================ + +.. toctree:: + :maxdepth: 1 + + migration-guide-1.3.x-2.0.x + migration-guide-2.0.x-2.1.x From 0f0ed9db6f01c259e34faceefc7b8b82885f9531 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 21 Aug 2012 10:37:40 +0200 Subject: [PATCH 4/7] Incorporate more review comments, see #2406 --- .../project/migration-guide-2.0.x-2.1.x.rst | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst index 3a9355c998..7157487bd2 100644 --- a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst +++ b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst @@ -40,7 +40,6 @@ Search Replace with ``akka.dispatch.Await`` ``scala.concurrent.Await`` ``akka.dispatch.Future`` ``scala.concurrent.Future`` ``akka.dispatch.Promise`` ``scala.concurrent.Promise`` -``akka.dispatch.Promise`` ``scala.concurrent.Promise`` ``akka.dispatch.ExecutionContext`` ``scala.concurrent.ExecutionContext`` ``akka.util.Duration`` ``scala.concurrent.util.Duration`` ``akka.util.duration`` ``scala.concurrent.util.duration`` @@ -91,7 +90,7 @@ v2.0:: v2.1:: - def square(i: Int): Future[Int] = Promise.successful(i * i).future + def square(i: Int): Future[Int] = Future successful i * i v2.0:: @@ -128,7 +127,7 @@ v2.1:: ExecutionContext ec = ExecutionContexts.fromExecutorService(yourExecutorServiceGoesHere); - //Use ec with your Futures + //No need to pass the ExecutionContext here Future f1 = Futures.successful("foo"); // Then you shut the ExecutorService down somewhere at the end of your program/application. @@ -154,10 +153,11 @@ v2.1:: v2.0:: - Future future1 = Futures.successful("value", system.dispatcher()).andThen(new OnComplete() { + Future future1 = Futures.successful("value", system.dispatcher()).andThen( + new OnComplete() { public void onComplete(Throwable failure, String result) { - if (failure != null) - sendToIssueTracker(failure); + if (failure != null) + sendToIssueTracker(failure); } }).andThen(new OnComplete() { public void onComplete(Throwable failure, String result) { @@ -196,7 +196,8 @@ v2.1 Scala:: v2.0 Java:: - ActorRef router2 = system.actorOf(new Props(ExampleActor.class).withRouter(RoundRobinRouter.create(routees))); + ActorRef router2 = system.actorOf(new Props(ExampleActor.class).withRouter( + RoundRobinRouter.create(routees))); v2.1 Java:: @@ -205,8 +206,8 @@ v2.1 Java:: Failing Send ============ -When failing to send to an actor with bounded or durable mailbox the message will -silently be delivered to deadletters instead of throwing an exception. +When failing to send to a remote actor or actor with bounded or durable mailbox the message will +silently be delivered to ``ActorSystem.deadletters`` instead of throwing an exception. Graceful Stop Exception ======================= @@ -215,7 +216,7 @@ If the target actor of ``akka.pattern.gracefulStop`` isn't terminated within the timeout the ``Future`` is completed with failure ``akka.pattern.AskTimeoutException``. In 2.0 it was ``akka.actor.ActorTimeoutException``. -PoisonPill and ReceiveTimeout - Java +getInstance for singeltons - Java ==================================== v2.0:: From a05e42db8568cd149dbea0d00e414e3f55ed63d5 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 21 Aug 2012 10:45:01 +0200 Subject: [PATCH 5/7] Move misplaced docs/io/BinaryCoding --- .../scala/code/{akka => }/docs/io/BinaryCoding.scala | 2 +- akka-docs/scala/io.rst | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename akka-docs/scala/code/{akka => }/docs/io/BinaryCoding.scala (98%) diff --git a/akka-docs/scala/code/akka/docs/io/BinaryCoding.scala b/akka-docs/scala/code/docs/io/BinaryCoding.scala similarity index 98% rename from akka-docs/scala/code/akka/docs/io/BinaryCoding.scala rename to akka-docs/scala/code/docs/io/BinaryCoding.scala index d9aeb334fc..5af45a5bf2 100644 --- a/akka-docs/scala/code/akka/docs/io/BinaryCoding.scala +++ b/akka-docs/scala/code/docs/io/BinaryCoding.scala @@ -1,7 +1,7 @@ /** * Copyright (C) 2012 Typesafe Inc. */ -package akka.docs.io +package docs.io //#imports import akka.actor._ diff --git a/akka-docs/scala/io.rst b/akka-docs/scala/io.rst index a0fede51a2..0b664f9c13 100644 --- a/akka-docs/scala/io.rst +++ b/akka-docs/scala/io.rst @@ -48,27 +48,27 @@ In this example, the data is to be stored in arrays of ``a``, ``b`` and ``data`` Decoding of such frames can be efficiently implemented in the following fashion: -.. includecode:: code/akka/docs/io/BinaryCoding.scala +.. includecode:: code/docs/io/BinaryCoding.scala :include: decoding This implementation naturally follows the example data format. In a true Scala application, one might, of course, want use specialized immutable Short/Long/Double containers instead of mutable Arrays. After extracting data from a ``ByteIterator``, the remaining content can also be turned back into a ``ByteString`` using the ``toSeq`` method -.. includecode:: code/akka/docs/io/BinaryCoding.scala +.. includecode:: code/docs/io/BinaryCoding.scala :include: rest-to-seq with no copying from bytes to rest involved. In general, conversions from ByteString to ByteIterator and vice versa are O(1) for non-chunked ByteStrings and (at worst) O(nChunks) for chunked ByteStrings. Encoding of data also is very natural, using ``ByteStringBuilder`` -.. includecode:: code/akka/docs/io/BinaryCoding.scala +.. includecode:: code/docs/io/BinaryCoding.scala :include: encoding The encoded data then can be sent over socket (see ``IOManager``): -.. includecode:: code/akka/docs/io/BinaryCoding.scala +.. includecode:: code/docs/io/BinaryCoding.scala :include: sending From 976c97ae2c8b65e82c97337931c1507e9a28b84e Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 21 Aug 2012 10:47:39 +0200 Subject: [PATCH 6/7] Remove prematurly added cluster-usage.rst --- akka-docs/cluster/cluster-usage.rst | 84 ----------------------------- akka-docs/cluster/index.rst | 1 - 2 files changed, 85 deletions(-) delete mode 100644 akka-docs/cluster/cluster-usage.rst diff --git a/akka-docs/cluster/cluster-usage.rst b/akka-docs/cluster/cluster-usage.rst deleted file mode 100644 index b258b8eb8e..0000000000 --- a/akka-docs/cluster/cluster-usage.rst +++ /dev/null @@ -1,84 +0,0 @@ - -.. _cluster_usage: - -######### - Cluster -######### - -.. note:: *This document describes how to use the features implemented so far of the -new clustering coming in Akka Coltrane and is not available in the latest stable release. -The API might change before it is released. - -For introduction to the Akka Cluster concepts please see - -Preparing your ActorSystem for Clustering -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The Akka cluster is a separate jar file. Make sure that you have the following dependency in your project:: - - "com.typesafe.akka" % "akka-cluster" % "2.1-SNAPSHOT" - -It can be difficult to find the correct versions and repositories at the moment. The following sbt 0.11.3 build -file illustrates what to use with Scala 2.10.0-M6 and Akka 2.1-SNAPSHOT - - import sbt._ - import sbt.Keys._ - - object ProjectBuild extends Build { - - lazy val root = Project( - id = "root", - base = file("."), - settings = Project.defaultSettings ++ Seq( - name := "Akka Cluster Example", - organization := "org.test", - version := "0.1-SNAPSHOT", - scalaVersion := "2.10.0-M6", - - resolvers += "Sonatype Releases Repo" at "https://oss.sonatype.org/content/repositories/releases/", - resolvers += "Sonatype Snapshot Repo" at "https://oss.sonatype.org/content/repositories/snapshots/", - resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases", - resolvers += "Typesafe Snapshots" at "http://repo.typesafe.com/typesafe/snapshots/", - - - libraryDependencies ++= Seq( - "com.typesafe.akka" % "akka-cluster" % "2.1-20120816-000904", - "com.typesafe.akka" % "akka-testkit" % "2.1-20120816-000904" % "test", - "junit" % "junit" % "4.5" % "test", - "org.scalatest" %% "scalatest" % "1.9-2.10.0-M6-B2" % "test") - ) - ) - } - -Pick a timestamped Akka version from ``_. - -To enable cluster capabilities in your Akka project you should, at a minimum, add the :ref:`remoting-scala` -settings and the ``cluster seed-nodes`` to your ``application.conf`` file: - -.. literalinclude:: ../../akka-samples/akka-sample-remote/src/main/resources/common.conf - :language: none - -The seed nodes are configured contact points for inital join of the cluster. -When a new node is started started it sends a message to all seed nodes and -then sends join command to the one that answers first. - -A Simple Cluster Example -^^^^^^^^^^^^^^^^^^^^^^^^ - - - - -Configuration -^^^^^^^^^^^^^ - -There are lots of more properties that are related to clustering in Akka. We refer to the following -reference file for more information: - - -.. literalinclude:: ../../akka-cluster/src/main/resources/reference.conf - :language: none - - - - - diff --git a/akka-docs/cluster/index.rst b/akka-docs/cluster/index.rst index dac3a558d9..35c4b2250a 100644 --- a/akka-docs/cluster/index.rst +++ b/akka-docs/cluster/index.rst @@ -5,4 +5,3 @@ Cluster :maxdepth: 2 cluster - cluster-usage From 786f3b747e71eaccc00d2254e21f0c784bb2e165 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Tue, 21 Aug 2012 10:59:49 +0200 Subject: [PATCH 7/7] Add note about log-remote-lifecycle-events change, see #2406 --- akka-docs/project/migration-guide-2.0.x-2.1.x.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst index 7157487bd2..772e5ea784 100644 --- a/akka-docs/project/migration-guide-2.0.x-2.1.x.rst +++ b/akka-docs/project/migration-guide-2.0.x-2.1.x.rst @@ -246,4 +246,14 @@ v2.0:: v2.1:: - probe.reply("world") \ No newline at end of file + probe.reply("world") + +log-remote-lifecycle-events +=========================== + +Default value of akka.remote.log-remote-lifecycle-events has changed to **on**. +If you don't want these in the log you need to add this to your configuration:: + + akka.remote.log-remote-lifecycle-events = off + +