{"id":2113,"date":"2011-11-30T22:52:53","date_gmt":"2011-11-30T21:52:53","guid":{"rendered":"http:\/\/www.gamlor.info\/wordpress\/?p=2113"},"modified":"2021-03-11T09:14:43","modified_gmt":"2021-03-11T08:14:43","slug":"akka-mobile-first-code-snippet","status":"publish","type":"post","link":"https:\/\/www.gamlor.info\/wordpress\/2011\/11\/akka-mobile-first-code-snippet\/","title":{"rendered":"Akka-Mobile: First Code Snippets"},"content":{"rendered":"<p>So far I\u2019ve only talked about <a href=\"https:\/\/www.gamlor.info\/wordpress\/2011\/11\/akka-mobile-unreliable-connections-and-push-messages\/\">the idea \/ concept<\/a>of the Akka-Mobile. This time I show some small code examples =). Of course the current implementation is a uncompleted prototype. The implementation itself throws not implemented exceptions around every corner or has other unknown behavior. The API is nowhere near completion or final stage. Anyhow I just want show how it \u2018feels\u2019 like and throw in a few comments. Also keep in mind that Akka 2.0 is not that far away, and I will almost certainly move to it sooner or later.<\/p>\n<div id=\"attachment_2122\" style=\"width: 310px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/code-drop.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2122\" class=\"size-medium wp-image-2122\" title=\"First look at code\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/code-drop-300x90.png\" alt=\"First Look at Code\" width=\"300\" height=\"90\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/code-drop-300x90.png 300w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/code-drop-1024x309.png 1024w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/code-drop.png 1322w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-2122\" class=\"wp-caption-text\">First Look at Code<\/p><\/div>\n<h2>The Server<\/h2>\n<p>First let\u2019s start a server. This is easily done by calling NettyRemoteServer.start() which starts up the server and listens to the specified port. Don\u2019t confuse this with the regular Akka 1.2 remote actors. The mobile actors will use their own server-implementation. That\u2019s also quite intentional: We want to expose only certain \u2018service\u2019 actors to our mobile clients and keep the rest internal to our cluster \/ internal infrastructure.<\/p>\n<p>After that we can register regular actor to the given server instance. These actors then are reachable by the mobile clients under the given id. For example a ultra simple actor which just echoes the request:<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=TheServer.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">val chatServer = NettyRemoteServer.start(2552);\n\nchatServer.register(&quot;chat-service&quot;, Actor.actorOf[ChatServerActor])\n\n\nclass ChatServerActor extends Actor{\n  protected def receive = {\n    case msg =&gt;{\n       self.reply(&quot;Answer for: &quot;+msg)\n    }\n  }\n}<\/code><\/pre><\/noscript>\n<p>Well that\u2019s not very exiting. It\u2019s nearly identical to the regular Akka 1.2 remote actor.<\/p>\n<h2>On The Android Device<\/h2>\n<p>Now let\u2019s move on to the Android device. The first thing we need to do is to <a href=\"https:\/\/github.com\/pboos\/scala-on-android-example#readme\">get Scala running<\/a> =). Then we start with a normal \u2018main\u2019 activity. Optionally we can use the trait \u2018ActivityActor\u2019 which\u00a0turns our\u00a0activity into an actor. Any message send to the activity will be dispatched on the \u2018activity\u2019 thread, so that we can update the UI etc. Like this:<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=ActivityAsActor.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">class AkkaDroidActivity extends Activity with ActivityActor {\n\n  override def onCreate(savedInstanceState: Bundle) {\n    super.onCreate(savedInstanceState)\n    setContentView(R.layout.main)\n    \n    actorOf[DoSomeWork].start()\n  }\n\n  protected def receive = {\n    case WorkDone(happend) =&gt; {\n      val inputTextBox = findViewById(R.id.enterMsgBox).asInstanceOf[EditText]\n      inputTextBox.setText(&quot;happend&quot;)\n    }\n  }\n}\n\ncase class WorkDone(result:String)\n\nclass DoSomeWork extends Actor{\n\n  protected def receive = {\n    case &quot;Start&quot; =&gt;{\n      val result = workForAWhile()\n      self.reply(result)\n    }\n  } \n  \n  private def workForAWhile() :String ={\n    \/\/ work work \n    &quot;work-done&quot;\n  }\n}<\/code><\/pre><\/noscript>\n<h3>Remote Actors<\/h3>\n<p>For remote actors we need a client instance, usually one per application. When creating such an instance we need to pass in a Android context, which allows the remote implementation to get to Android resources. The other arguments are optional or loaded from the configuration.\u00a0 I\u2019ve put my remote instance in the global application object which is then registered in the Android manifest.<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=TheRemoteInterface.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">\/\/ Registred in the AndroidManifest as our application object\nclass MyApplication extends android.app.Application {\n\n  lazy val remote = MobileRemoteClient.createClient(\n    AndroidDevice(this))\n\n}<\/code><\/pre><\/noscript>\n<p>In the akka.conf we specify the host, port and preferably the Logcat logger:<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=akka.conf\"><\/script><noscript><pre><code class=\"language- \">akka {\n  event-handlers = [&quot;akka.mobile.android.LogcatLogger&quot;]\n  event-handler-level = &quot;DEBUG&quot; # Options: ERROR, WARNING, INFO, DEBUG\n\n  mobile{\n      client{\n          host = &quot;our.server.host&quot;\n          port = 2552\n      }\n  }\n}<\/code><\/pre><\/noscript>\n<p>After that we can get references to actors on the server by name and send messages to them. So we now can communicate with the actors on the server. Nice =)<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=ChatClientActor.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">class ChatClientActor extends Actor{\n\n  protected def receive = {\n    case SentToServer(msg) =&gt;{\n\t  val chatService = MyApplication.remote.actorFor(&quot;chat-service&quot;)\n      chatService ! msg\n    }\n    case MessageFromServer(msg) =&gt;{\n      \/\/ well, show the message or do what is needed\t\n    }\n\t\n  } \n}<\/code><\/pre><\/noscript>\n<h2>\u2018Push\u2019-Messages<\/h2>\n<p>So far so good, we\u2019ve connected from the Android device to the server, got a reference to it and started communicating with it.<\/p>\n<p>But what if the server wants to initiate the communication with a client? To do that we register an actor on our remote instace! The server will later be able to contact this client-actor by its name:<\/p>\n<p>The first thing we need is an \u2018address\u2019 for a client. Since\u00a0mobile devices\u00a0are on the move, they don&#8217;t permanent IP address. Akka mobile provides a \u2018clientId&#8217; as a replacement. You can get that id in multiple way. For example when a server-side actor is communicatong with a Android device the self-reference will contain this client id. With the trait ServiceActor you get a nice accessor:<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=GetClientID.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">class TalksToMobileDevices extends Actor with ServiceActor{\n  protected def receive = {\n    case msg =&gt;{\n       self.reply(&quot;Answer for: &quot;+msg)\n       val clientId = this.clientId;\n       if(clientId.isDefined){\n           \/\/ store it in database. So that you later can talk to this client\n       }\n    }\n  }\n}<\/code><\/pre><\/noscript>\n<p>As soon as we have a client id\u00a0\u00a0we can get an reference for an actor running on the device and start sending messages to it.<\/p>\n<script src=\"https:\/\/gist.github.com\/1387130.js?file=TalkToServiceOnPhone.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">val clientId = \/\/ clientId. Like from the database\nval serviceOnPhone = chatServer.actorOf(clientId, &quot;notifications&quot;)\nserviceOnPhone ! &quot;Hi Phone&quot;<\/code><\/pre><\/noscript>\n<div id=\"attachment_2123\" style=\"width: 510px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/c2md-support.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2123\" class=\"size-full wp-image-2123\" title=\"Pushing Messages to the Client\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/c2md-support.png\" alt=\"Pushing Messages to the Client\" width=\"500\" height=\"466\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/c2md-support.png 500w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/c2md-support-300x279.png 300w\" sizes=\"(max-width: 500px) 100vw, 500px\" \/><\/a><p id=\"caption-attachment-2123\" class=\"wp-caption-text\">Pushing Messages to the Client<\/p><\/div>\n<h2>But Wait, What if the Device is Offline?<\/h2>\n<p>Now the stuff I&#8217;ve showed so far only works as long as the Phone has a connection to the Server. What if the Phone is offline? Or the application isn&#8217;t running. Well here&#8217;s where the C2MD integration comes in. Akka mobile can deliver messages via C2MD. Here&#8217;s a short overview how it works.<\/p>\n<h3>Preparation on the Server<\/h3>\n<p>First we need to configure the Server to support C2MD: We need to add two things: The C2MD authentication key for talking to the C2MD servers and a database backend. The database backend is required to store the registration ids of all devices.<\/p>\n<p>So in the akka.conf configuration we add:<\/p>\n<script src=\"https:\/\/gist.github.com\/1428024.js?file=akka-conf-on-client.conf\"><\/script><noscript><pre><code class=\"language- \">akka {\n  event-handlers = [&quot;akka.mobile.android.LogcatLogger&quot;]\n  event-handler-level = &quot;DEBUG&quot; # Options: ERROR, WARNING, INFO, DEBUG\n\n  mobile{\n      client{\n          host = &quot;our.server.host&quot;\n          port = 2552\n      }\n      c2md{\n          email=&quot;the-c2md-email@thecompany&quot;\n          register-mode = &quot;AUTO&quot; # Possible values: MANUAL, AUTO, default is MANUAL\n      }\n  }\n}<\/code><\/pre><\/noscript>\n<p>And we start the server with a given database :<\/p>\n<script src=\"https:\/\/gist.github.com\/1428024.js?file=ServerWithDB.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">val chatServer = NettyRemoteServer.start(port=2552,\n    database = Some(new H2Database(&quot;jdbc:h2:~\/apiKeyStore&quot;)));<\/code><\/pre><\/noscript>\n<h3>Preparation on the Client<\/h3>\n<p>On the client we also\u00a0update the akka.conf. We add the email for which the C2MD service is registered:<\/p>\n<script src=\"https:\/\/gist.github.com\/1428024.js?file=akka-conf-on-server.conf\"><\/script><noscript><pre><code class=\"language- \">akka {\n    mobile{\n        c2md{\n            key=&quot;Your Application Key for C2MD&quot;\n        }\n\n    }\n}<\/code><\/pre><\/noscript>\n<p>Additionally we need a broad cast receiver which handles the C2MD intents. We inherit the &#8216;C2MDReceiver&#8217; -trait and implement the &#8216;remoteClient&#8217; method. In that method we return our instance of the akka-mobile remote client which our application is using. In this example I&#8217;ve\u00a0that instance\u00a0\u00a0in the application object and get it from there (via ugly cast, don&#8217;t hit me).<\/p>\n<script src=\"https:\/\/gist.github.com\/1428024.js?file=BroadcastReceiver.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">class DispatchToAkka extends C2MDReceiver {\n  def remoteClient(context: Context) = {\n    context.getApplicationContext.asInstanceOf[MyApplication].remote;\n  }\n}<\/code><\/pre><\/noscript>\n<p>In the Android Manifest you need to get the permissions for C2MD and register the broadcast receiver previously created:<\/p>\n<script src=\"https:\/\/gist.github.com\/1428024.js?file=AndroidManifest.xml\"><\/script><noscript><pre><code class=\"language-xml xml\">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;\n&lt;manifest xmlns:android=&quot;http:\/\/schemas.android.com\/apk\/res\/android&quot;\n          package=&quot;info.gamlor.akkamobile&quot;\n          android:versionCode=&quot;1&quot;\n          android:versionName=&quot;1.0&quot;\n          android:debuggable=&quot;true&quot;&gt;\n    &lt;uses-sdk android:minSdkVersion=&quot;10&quot;\/&gt;\n\t\n    &lt;permission android:name=&quot;info.gamlor.akkamobile.permission.C2D_MESSAGE&quot; android:protectionLevel=&quot;signature&quot;\/&gt;\n    &lt;uses-permission android:name=&quot;info.gamlor.akkamobile.permission.C2D_MESSAGE&quot;\/&gt;\n    &lt;uses-permission\n            android:name=&quot;android.permission.INTERNET&quot;\/&gt;\n    &lt;uses-permission android:name=&quot;com.google.android.c2dm.permission.RECEIVE&quot;\/&gt;\n\n    &lt;application android:name=&quot;.MyApplication&quot; android:label=&quot;@string\/app_name&quot; android:icon=&quot;@drawable\/icon&quot;\n                 android:debuggable=&quot;true&quot;&gt;\n        &lt;!-- Activities etc --&gt;\n\n        &lt;!-- Our Broadcast receiver for integration C2MD with akka-mobile --&gt;\n        &lt;receiver android:name=&quot;.DispatchToAkka&quot;\n                  android:permission=&quot;com.google.android.c2dm.permission.SEND&quot;&gt;\n            &lt;intent-filter&gt;\n                &lt;action android:name=&quot;com.google.android.c2dm.intent.REGISTRATION&quot;\/&gt;\n                &lt;category android:name=&quot;info.gamlor.akkamobile&quot;\/&gt;\n            &lt;\/intent-filter&gt;\n            &lt;intent-filter&gt;\n                &lt;action android:name=&quot;com.google.android.c2dm.intent.RECEIVE&quot;\/&gt;\n                &lt;category android:name=&quot;info.gamlor.akkamobile&quot;\/&gt;\n            &lt;\/intent-filter&gt;\n        &lt;\/receiver&gt;\n    &lt;\/application&gt;\n&lt;\/manifest&gt; \n<\/code><\/pre><\/noscript>\n<p>After that akka mobile is ready to use C2MD. It will register the application automatically and report\u00a0its registration-id\u00a0to out server as soon as the remote-instance is created. Or you can optionally disable the auto-registration and use &#8216;requestC2MDRegistration()&#8217; to start the C2MD registration at a certain point in time.<\/p>\n<h3>Sending a Message over C2MD<\/h3>\n<p>Now messages are still not sent with C2MD if no connection is available. The reason is that akka-mobile wants to prevent that we send hundreds of messages via C2MD by accident. We should be very careful and only sent important notifications over C2MD. There are two ways to achieve that.<\/p>\n<p>One is to use the marker-trait \u00a0&#8216;SentThroughC2MDIfNoConnectionIsAvailable&#8217; \u00a0in your message. If a\u00a0message implements this trait it will be delivered via C2MD if no connection is found.<\/p>\n<script src=\"https:\/\/gist.github.com\/1428024.js?file=ForceC2MD.scala\"><\/script><noscript><pre><code class=\"language-scala scala\">case class ImportantNotification(msg:String) extends SentThroughC2MDIfNoConnectionIsAvailable<\/code><\/pre><\/noscript>\n<p>The other possibility is by using a &#8216;error&#8217;-handler which falls back on C2MD if no connection can be established. However I explain error-handlers next time, since they are quite central to the whole communication stack.<\/p>\n<h2>Stuff Still To Implement for a Proper Prototype<\/h2>\n<p>So, that the first look at how akka-mobile will work. There still tons of things to do. Also very basic stuff:<\/p>\n<ul>\n<li>Improve stability, test-suite and build-process.<\/li>\n<li>Better integration with Android, especially the connection-manager. Maybe also with power management.<\/li>\n<li>&#8216;Session&#8217; actors on the server<\/li>\n<li>Better serialization story. Currently only Java Serialization is supported. Java serialization always makes me nervous.<\/li>\n<li>Error-Handler API has to improve, a lot. More about that next time.<\/li>\n<li>Do some basic performance analysis.<\/li>\n<li>Finally start on &#8216;cool&#8217; features&#8230;.<\/li>\n<\/ul>\n<p>Otherwise I&#8217;ve tons of other features I want to tackle, but those above are really needed to get to a more stable state.<\/p>\n<div id=\"attachment_2124\" style=\"width: 567px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/todo-akka-mobile.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2124\" class=\"size-full wp-image-2124\" title=\"todo-akka-mobile\" src=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/todo-akka-mobile.png\" alt=\"Lot's of Things to Do\" width=\"557\" height=\"400\" srcset=\"https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/todo-akka-mobile.png 557w, https:\/\/www.gamlor.info\/wordpress\/wp-content\/uploads\/2011\/11\/todo-akka-mobile-300x215.png 300w\" sizes=\"(max-width: 557px) 100vw, 557px\" \/><\/a><p id=\"caption-attachment-2124\" class=\"wp-caption-text\">Lot&#39;s of Things to Do<\/p><\/div>\n<h2>Conclusion and Next Time<\/h2>\n<p>So we&#8217;ve seen how we can setup the akka mobile remote actors. It allows us to have nice device to server communication between actors. It also allows us to fall back on C2MD messages when a client doesn&#8217;t have a connection to a server.<\/p>\n<p>Next time I&#8217;m going to talk about error-handlers. These are responsible for managing connection loses etc.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>So far I\u2019ve only talked about the idea \/ conceptof the Akka-Mobile. This time I show some small code examples =). Of course the current implementation is a uncompleted prototype.&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[243],"tags":[245,297,244,226],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/2113"}],"collection":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/comments?post=2113"}],"version-history":[{"count":13,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/2113\/revisions"}],"predecessor-version":[{"id":2130,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/posts\/2113\/revisions\/2130"}],"wp:attachment":[{"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/media?parent=2113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/categories?post=2113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gamlor.info\/wordpress\/wp-json\/wp\/v2\/tags?post=2113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}