Mar 14, 2014

Monitoring Akka Actor in Scala (basic introduction)

In this tutorial we will see how we can add a watch on a child Actor (i.e. get a notification when child Actor is killed). Refer following code.



It will give following output.

Will monitor actor here
Parent:Hello
Parent:
Parent:Hi
Child::PreStart
Child:Hello
[ERROR] [03/14/2014 00:29:18.190] [ActorWatchSystem-akka.actor.default-dispatcher-2] [akka://ActorWatchSystem/user/parent/child] Boom....
java.lang.Exception: Boom....
       at com.techcielo.scala.actor.Child$$anonfun$receive$2.applyOrElse(MonitorableActor.scala:57)
       at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
       at akka.actor.ActorCell.invoke(ActorCell.scala:386)
       at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
       at akka.dispatch.Mailbox.run(Mailbox.scala:212)
       at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:506)
       at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
       at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
       at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
       at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)

Child::PreRestart
Child::Poststop
Child::postRestart
Child::PreStart
Child:Hi
Got handle to child actor
Child::Poststop
Child Terminated
class akka.actor.DeadLetterActorRef
Shutting down system


Now let's see how this code works. In order to understand this we will go back and forth in our code.

-> From line 29 to 40 we are creating an Actor class called Parent. When this class is created it will create a Child Actor using context (line# 30) and will add a watch on this child (line# 31). Since we have added watch on child if this child is terminate notification/message will be sent to Parent and receive method will get a message Terminate(ActorRef) so line# 37 will be executed. This Parent Actor will be called by our main method and this Actor will first get the message. Once it gets method it will print the message and send it to Child Actor (line# 35). If message is anything other then text it will simply print text "Parent got a message" without any processing.

-> Line# 42 to 48 shows our Child Actor (which is created by Parent Actor on line# 30). This class will get message from parent. We have also over loaded life cycle methods preStart, postStop, preRestart and postRestart of this Actor class. When this Actor gets message from parent (and when message is received receive method of this class will be called) it will check if this message has some text or not. If this message is a blank message it will throw an Exception which in turn will force actor to restart and hence its preRestart and postRestart methods will be called.
If message is anything other than String it will simply print text "Child got a message" (line# 60)

-> In our main method (line# 10 to 28) we are creating our ActorSystem (line# 12) then creating an instance of Parent Actor (line# 13) with name parent. We will pass some text messages to this Actor (also by passing blank message we will force it Child Actor to restart on line#15).

-> On line# 18 we are getting access to Child Actor's reference directly and we are giving this class a PoisonPill on line# 20 which will kill this child class once it has processed all message it has received before getting PoisonPill.

-> Once all operations are completed we will shutdown the actor system. If your system is continuously processing data then you need not to shutdow the system.

So this was brief introduction to Akka using Scala for Java developers. Interested users can try developing application where they are continuously getting some data from some stream and wants to process this data in parallel by using Akka Actors.

Happy coding. :)

Mar 12, 2014

Introduction to SBT (Scala Build Tool)

SBT is abbreviation for Scala Build Tool. This tool is a great help if you are a newbie in Scala like me. Its simple yet very powerful as far as Scala projects are concerned. In this tutorial we will see
  • How to create a small project (first without any dependency and later with dependency on some external jar files)
  • How to compile our code with sbt tool
  • How to run this code with sbt
  • What will be folder structure of our say decently complex project and how to segregate our main code and our test cases code.

So first lets start with installation of this tool. This tool can be downloaded from here. Once you download the tool extract the zip file on your local machine and set environment variable SBT_HOME to location where the file is extracted. Also add %SBT_HOME%/bin in your path so that you can run sbt command from anywhere you want.

Now go to directory where you want to write and run your Scala code and create a file HelloWorld.scala in this folder as follows


Once this file is created, open DOS shell and go to this folder and execute following command. 

sbt run

This command will not require any build file. It will automatically compile as well as run the HelloWorld.scala as shown in image below.




So now we know about basic sbt command so now we can look at few more commands and bit complicated code that will require some third party jar that sbt will try to download from maven/ivy repository.

Mar 8, 2014

Quick start with Scala for Java Developers

Let’s say we have number 1 to 100 in a list we will see how to perform different operations on this List in Java and Scala.

Add numbers 1 to 100 in a list
Java Way of doing it
Scala way of doing it
public static void main(String[] args) {
       List<Integer> list = new ArrayList<>();
       for(int i=0;i<=100;i++){
              list.add(i);
       }
}
val numbers = (1 to 100).toList


Get the sum of numbers
Java Way of doing it
Scala way of doing it
int sum = 0;
for (Integer num : list) {
       sum+=num;
}
System.out.println(sum);
println(numbers.foldLeft(0)((x,y)=>(x+y)))

Get the sum of even numbers
Java Way of doing it
Scala way of doing it
int sum = 0;
for (Integer num : list) {
       if(num%2==0){
              sum+=num;
       }
}
System.out.println(sum);
println(numbers.filter(_%2==0)
             .foldLeft(0)((x,y)=>(x+y)))

Get the sum of odd numbers that are greater than 15
Java Way of doing it
Scala way of doing it
int sum = 0;
for (Integer num : list) {
       if(num%2==1 && num>15){
              sum+=num;
       }
}
System.out.println(sum);
println(numbers.filter(x=>(x%2==1 && x>15))
             .foldLeft(0)((x,y)=>(x+y)))


From above examples we can see that by passing function to a list we can reduce the line of code that we need to write. This also have an advantage when code is running in multithreaded environment. I will keep adding similar examples for comparing Java and Scala in this tutorial.

Mar 2, 2014

Quick start MongoDB MapReduce with Java

In this tutorial we will how to use MapRedulce feature of MongoDB with java. First we will see few commands of MongoDB and then we will connect this DB with Java Connector and perform basic MapReduce feature and then a slightly more complex MapReduce function. So first lets start with MongoDB.
Download latest version of MongoDB from http://www.mongodb.org/downloads. One which I have used for this tutorial is mongodb-win32-i386-2.4.6.zip.  Now extract this file on local machine.
Go to %MONGODB_HOME%/bin and execute command mongod –help this will show options for starting instance on MongoDB.



So we will start instance by executing following command. We will pass location where the data will be stored by using --dbpath as follows.



You can also see files created at this location.



Now in another window we will start mongodb console by executing command mongo as follows.



Now we will use following three commands that will show us what databases are present in MongoDB (show databases), how to select particular DB (use <db_name>) and how to check what tables exists in particular database (show tables).




Now we will download driver for connecting to MongoDB from http://central.maven.org/maven2/org/mongodb/mongo-java-driver/2.9.3/mongo-java-driver-2.9.3.jar and add this jar in your Eclipse project. Also we will create a utility class that will create a connection to MongoDB and will create a DBCollection (Object where data will be stored in mongo db). So following will be our utility class.
package com.techcielo.mongodb.util;

import java.net.UnknownHostException;

import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;

public class MongoDBUtil {
      
       public static DBCollection createCollection(String name,boolean forceRecreate){
              try {
                     MongoClient client = new MongoClient();
                     DB db = client.getDB("test");
                     if(db.collectionExists(name)){
                           if(forceRecreate){
                                  db.getCollection(name).drop();
                           }
                           else
                           {
                                  return db.getCollection(name);
                           }
                     }
                     DBObject mydata = BasicDBObjectBuilder.start().add("capped", true).add("size", 200000000l).get();
               DBCollection collection = db.createCollection(name, mydata);
               return collection;
              }
              catch (UnknownHostException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
              }
              return null;
       }
}

Here since we have only one instance which we want to connect so we are not passing server list also since it is on local machine (localhost) we are also not passing server name and we use default Constructor to create instance of MongoClient. Second thing we will call getDB method on MongoDB to connect to test database of MongoDB.
Once this is done now we will insert some data in this collection. So we will insert following data in this collection. We will fire following query in our open source database northwind to get the data that we will insert here.
SELECT od.OrderID, ProductID, UnitPrice, Quantity, CustomerId, EmployeeID, ShipCountry
FROM order_details od
JOIN orders o ON o.orderId = od.orderId
LIMIT 0 , 100
So here I will just create one class that will give me list of bean with appropriate data, leaving it to user how he/she wants to load the data e.g. by hitting DB or by flat file anything that he/she likes. We are interested in end result. So following will be our class.

package com.techcielo.mongodb.main;

import java.util.List;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.techcielo.mongodb.bean.OrderBean;
import com.techcielo.mongodb.util.DBUtil;
import com.techcielo.mongodb.util.MongoDBUtil;


public class Main {
       public static void main(String[] args) {
              insertData();
       }
       public static void insertData(){
              List<OrderBean> orderlist = DBUtil.getOrderData();           
              System.out.println(orderlist.size());
              DBCollection coll = MongoDBUtil.createCollection("orderdata",true);
              for(OrderBean order:orderlist){
                     BasicDBObject obj = new BasicDBObject();
                     obj.append("orderId",order.getOrderid());
                     obj.append("productId",order.getProductid());
                     obj.append("custId",order.getCustid());
                     obj.append("quantity",order.getQuantity());
                     obj.append("unitPrice",order.getUnitprice());
                     obj.append("shipCountry",order.getShipctry());
                     coll.insert(obj);
              }
              System.out.println("Total Count:"+coll.getCount());
       }
}
When this code is executed following will be output

Total Count:99

So now we have inserted the data now let’s check this data with MapReduce. So now let’s find total order value of each order id.

public static void getMapReduceData(){
              DBCollection coll = MongoDBUtil.createCollection("orderdata", false);
              String map = "function() {emit(this.orderId,{cost: this.quantity*this.unitPrice});}";
              String reduce = "function(key, values) { "
                                         + "var sum = 0; "
                                         + "values.forEach(function(doc) { "
                                         + "sum += doc.cost;}); "
                                         + "return sum;} ";        
             
              MapReduceCommand cmd = new MapReduceCommand(coll, map, reduce, null, MapReduceCommand.OutputType.INLINE, null);
             
              MapReduceOutput out = coll.mapReduce(cmd);
        for (DBObject o : out.results())
        {
              Long orderid = (Long) o.get("_id");
              Double cost = 0.0;
              Object obj = o.get("value");
              if (obj instanceof DBObject) {                 
                           DBObject new_name = (DBObject) obj;
                           cost = (Double) new_name.get("cost");
                     }
              else
              {
                     cost = (Double) o.get("value");
              }
            System.out.println(orderid+":"+cost);
        }
       }

And call this method from your main class after loading data from northwind database. So following will be output of this method

10248:440.0
10249:1863.4
10250:1813.0
10251:670.8
10252:3730.0
10253:1444.8000000000002
10254:625.2
10255:2490.5
10256:517.8
10257:1119.9
10258:2018.6
10259:100.8
10260:1746.2
10261:448.0
10262:624.8
10263:2464.8
10264:724.5
10265:1176.0
10266:364.79999999999995
10267:4031.0
10268:1101.2
10269:676.0
10270:1376.0
10271:48.0
10272:1456.0
10273:2142.4
10274:538.6
10275:307.2
10276:420.0
10277:1200.8
10278:1488.8
10279:468.0
10280:613.2
10281:86.5
10282:155.39999999999998
10283:1414.8000000000002
10284:1452.0