<?xml version='1.0' encoding='utf-8' ?>
<rss version='2.0' xmlns:dc='http://purl.org/dc/elements/1.1/'>
  <channel>
    <title>Wolfmans Howlings: Using Erlang with JInterface</title>
    <link>http://blog.wolfman.com/articles/2009/4/12/using-erlang-with-jinterface</link>
    <description>A programmers Blog about Ruby, Rails and a few other issue</description>
    <language>en-us</language>
    <ttl>40</ttl>
    <item>
      <title>Using Erlang with JInterface</title>
      <description>
        &lt;h2&gt;Background&lt;/h2&gt;
        
        &lt;p&gt;I recently undertook a project to rewrite a voice conference server I
        wrote over 10 years ago. This server was written in C++ running on a
        Windows Server (originally NT and then win2k). The reason it was
        written for win2k was to use 
        &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/aa365198.aspx&quot;&gt;I/O Completion Ports&lt;/a&gt;
        which were not (and still are not) available on Linux. &lt;/p&gt;
        
        &lt;p&gt;Solaris has an equivalent AIO feature but not quite the same. I/O
        Completion Ports make very efficient use of multiple CPU's, and the
        conference server had to be very fast and handle a large number of
        concurrent connections.&lt;/p&gt;
        
        &lt;p&gt;The program uses a limited number of threads basically enough to keep
        all the CPUs busy, it uses the 
        &lt;a href=&quot;http://www.cs.wustl.edu/~schmidt/PDF/proactor.pdf&quot;&gt;Proactor Pattern&lt;/a&gt;
        to handle the large number of concurrent connections. Each client
        connected has its own state, and every Asynchronous I/O needs to
        switch to that context.  Needless to say there was a lot of shared
        memory and locks everywhere.  The program was very complex to write,
        trying to keep all those locks and memory synchronized yet avoid
        deadlocks. I guess I did a good job as the servers are still running
        to this day, with barely a reboot in 5 years.&lt;/p&gt;
        
        &lt;p&gt;However the code is tortuous, and making any changes risks introducing
        deadlocks, also I wanted to get off of the windows servers and onto
        Linux which all my other servers run.&lt;/p&gt;
        
        &lt;p&gt;I have written several scalable servers using 
        &lt;a href=&quot;http://java.sun.com/j2se/1.4.2/docs/guide/nio/index.html&quot;&gt;Java NIO&lt;/a&gt;,
        and even though they use the 
        &lt;a href=&quot;http://en.wikipedia.org/wiki/Reactor_pattern&quot;&gt;Reactor Pattern&lt;/a&gt;
        and I avoid creating hundreds of threads, instead I have several
        threads working through the ready sockets, it is still very hard to
        write, even with the great new concurrency libraries,&lt;/p&gt;
        
        &lt;p&gt;An article comparing the two patterns is
        &lt;a href=&quot;http://www.artima.com/articles/io_design_patterns.html&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
        
        &lt;p&gt;The trick is to write servers that you can simply add new servers to
        increase capacity, and to allow for redundancy so if one server goes
        down the service continues to run.&lt;/p&gt;
        
        &lt;p&gt;So having heard a lot about Erlang and how it auto-magically allowed
        you to run scalable and redundant servers I had to give it a go.&lt;/p&gt;
        
        &lt;p&gt;I bought 
        &lt;a href=&quot;http://pragprog.com/titles/jaerlang/programming-erlang&quot;&gt;Joe Armstrong's Book&lt;/a&gt;
        to learn Erlang, it is a good book to learn the basics, but is very
        short on details about OTP and how to actually use Erlang to write
        scalable servers. I guess the next book in the series will cover that ;)&lt;/p&gt;
        
        &lt;p&gt;I actually found it very hard to wrap my brain around Erlang
        initially. Having programmed in procedural and object oriented
        languages for so many years the switch to a functional, non object
        oriented language was tough.&lt;/p&gt;
        
        &lt;p&gt;Once I got over that initial hurdle (but am still struggling with it),
        I was able to quickly write the basic operations of the voice server
        in Erlang. I used a number of gen_servers, and tried to follow the OTP
        principles as closely as possible. I still have not figured out how to
        achieve the transparent scalability and redundancy that Erlang is
        touted for and that my old server has. However I do see the
        possibilities of making that transition.&lt;/p&gt;
        
        &lt;p&gt;What made the whole thing very easy is that every client connection
        can have its own process and state, totally independent of other
        connections. No locks are needed as there is no shared memory (except
        for the large ETS tables I use to store the list of users that are
        online etc). It turns out that not having to use either the Reactor or
        Proactor pattern makes things very simple, although as I am using the
        asynchronous mode of gen_tcp it is almost like a Proactor, as I get a
        callback (actually Erlang messages) everytime a packet comes in. As
        every client has its own process, and there could be about 100,000
        clients concurrently connected, that is more than enough process to
        keep all the processors busy, also distributing those process over
        several physical servers should not be a problem (if I can figure out
        a way to load balance, probably using a H/W load balancer). I won't go
        into details here of gen_servers and the Erlang language as there is
        plenty of documentation on the web covering those, one particularly
        good series I found is 
        &lt;a href=&quot;http://spawnlink.com/articles/an-introduction-to-gen_server-erlybank/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
        
        &lt;p&gt;I use a binary protocol between the clients and servers and Erlang is
        particularly good at handling binary protocols, with its Binary type
        and easy pattern matching to extract parts of the message. Packing and
        unpacking binary messages is a breeze once you get the binary matching
        syntax.&lt;/p&gt;
        
        &lt;h2&gt;Java and Erlang&lt;/h2&gt;
        
        &lt;p&gt;However (and finally getting to the point of this article) one thing I
        found Erlang is particularly bad at is database access. It does have
        ODBC built in, and there is a Postgresql driver too, however the code
        is basically using raw SQL, and gets very ugly very fast. Now I am
        used to using Java and Spring and SpringJdbc to do all my database
        work, and it is a pleasure to work with. I use a common pattern of
        Dao, Business logic and I/O separation, and it keeps things very clean.
        Plus I already had all the database access written in Java.&lt;/p&gt;
        
        &lt;p&gt;So being one to use the best tool for the given situation, I wanted to
        continue to use Java/Spring for all the database accesses, and use
        Erlang as the server frontend.&lt;/p&gt;
        
        &lt;p&gt;Turns out Erlang ships with a pretty robust Java to Erlang interface
        called &lt;a href=&quot;http://erlang.org/doc/apps/jinterface/index.html&quot;&gt;JInterface&lt;/a&gt;.&lt;/p&gt;
        
        &lt;p&gt;Basically this allows me to write an Erlang Node in Java, which Erlang
        can communicate with seamlessly using the normal Erlang message
        passing systems.&lt;/p&gt;
        
        &lt;p&gt;I have structured the database back end as 3 basic packages. The I/O
        package that contains all the knowledge of the server/server protocol
        for database requests and actually runs as an Erlang node. It calls
        methods in a POJO package which handles all business logic for those
        requests, and the business logic POJOs access the database entirely
        through calls to methods in the DAO package. The whole system is
        hooked together using 
        &lt;a href=&quot;http://www.devshed.com/c/a/Java/The-Spring-Framework-Understanding-IoC/&quot;&gt;Spring IoC&lt;/a&gt;, 
        and the DAO is written using 
        &lt;a href=&quot;http://static.springframework.org/spring/docs/2.0.x/reference/jdbc.html&quot;&gt;Spring JDBC&lt;/a&gt;.&lt;/p&gt;
        
        &lt;p&gt;I won't go into details here of how to write Spring based JDBC access
        as that is also well documented on the 
        &lt;a href=&quot;http://static.springframework.org/spring/docs/2.5.x/api/index.html&quot;&gt;Spring site&lt;/a&gt;
        I may write another article on Spring JDBC as it is very elegant and
        easy to use.&lt;/p&gt;
        
        &lt;p&gt;So the focus of this article is the JInterface based part of the Java
        system, which receives database requests from the Erlang based
        front-end server and does whatever it needs to do getting data from the
        database then replies to that request back to the calling Erlang
        process.&lt;/p&gt;
        
        &lt;p&gt;Here is a portion of the java code setting up and handling the erlang
        requests, only the JInterface portions are shown&lt;/p&gt;
        
        &lt;pre&gt;import com.ericsson.otp.erlang.*;
        
        public class ServerNodeImpl implements Server {
            private static final Logger jlog = Logger.getLogger(ServerNodeImpl.class);
            private String nodeName = &amp;quot;databasenode@localhost&amp;quot;;
            private String mboxName = &amp;quot;database&amp;quot;;
        
        ...
        
            private OtpMbox mbox;
        
            // create some convenient atoms
            private final OtpErlangAtom request= new OtpErlangAtom(&amp;quot;request&amp;quot;);
            private final OtpErlangAtom authenticate= new OtpErlangAtom(&amp;quot;authenticate&amp;quot;);
            private final OtpErlangAtom failed= new OtpErlangAtom(&amp;quot;failed&amp;quot;);
            private final OtpErlangAtom ok= new OtpErlangAtom(&amp;quot;ok&amp;quot;);
        
            // start the node up
            public boolean start() {
                try{
                    init();
                }catch(IOException e){
                    jlog.error(&amp;quot;start()&amp;quot;, e);
                    return false;
                }
        
                // this will block and the caller will block until the loop exits
                loop();
        
                return true;
            }
        
            // stop the node
            public boolean stop() {
                // to stop it, try sending myself a stop message
                OtpErlangObject[] msg = new OtpErlangObject[2];
                msg[0] = mbox.self();
                msg[1] = new OtpErlangAtom(&amp;quot;stop&amp;quot;);
                OtpErlangTuple tuple = new OtpErlangTuple(msg);  
                mbox.send(mbox.self(), tuple);
                return true;
            }
        
            private void init() throws IOException {
                jlog.info(&amp;quot;Node: &amp;quot; + nodeName + &amp;quot;, MBox: &amp;quot; + mboxName);
                OtpNode self = new OtpNode(getNodeName());
                mbox = self.createMbox(getMboxName());
            }
        
            /**
             * We get requests which are tuples.. {from,cmd,ref,...}
             * where cmd is currently an atom stop|request
             */
            private void loop() {
                jlog.info(&amp;quot;loop(): starting...&amp;quot;);
                boolean running= true;
                while(running){
                    try{
                        OtpErlangObject o = mbox.receive();
                        jlog.debug(&amp;quot;loop(): Received Request: &amp;quot; + o);
                        if(o instanceof OtpErlangTuple){
                            OtpErlangTuple msg = (OtpErlangTuple) o;
                            OtpErlangPid from = (OtpErlangPid) msg.elementAt(0);
                            OtpErlangObject cmd = msg.elementAt(1);
                            OtpErlangRef ref = (OtpErlangRef) msg.elementAt(2);
                            if(cmd instanceof OtpErlangAtom){
                                OtpErlangAtom atom= (OtpErlangAtom)cmd;
                                String c= atom.atomValue();
                                if(c.equals(&amp;quot;stop&amp;quot;)){
                                    jlog.info(&amp;quot;loop(): got stop message&amp;quot;);
                                    running= false;
                                }else if(c.equals(&amp;quot;request&amp;quot;)){
                                    try{
                                        byte [][] reply= handleRequest(from, msg);
                                        sendResponse(from, ref, reply);
                                    }catch(Exception e){
                                        jlog.error(&amp;quot;loop(): got exception from handleRequest()&amp;quot;, e);
                                    }
                                }else{
                                    jlog.error(&amp;quot;loop(): got unknown cmd: &amp;quot; + c);                          
                                }
                            }else{
                                jlog.error(&amp;quot;loop(): got unknown cmd type: &amp;quot; + cmd);
                            }
        
                        }else{
                            jlog.error(&amp;quot;loop(): Unknown message type: &amp;quot; + o);
                        }
                    }catch(Exception e){
                        jlog.error(&amp;quot;loop(): got exception&amp;quot;, e);
                        running= false;
                    }
                }
                jlog.info(&amp;quot;loop(): ...leaving&amp;quot;);
            }
        
            ...
        
            // sends a tuple back to requesting Pid {From, Ref, Data}
            private void sendResponse(OtpErlangPid from, OtpErlangRef ref, byte [] ba) {
                OtpErlangBinary data= new OtpErlangBinary(ba);      
                OtpErlangObject [] eoa= new OtpErlangObject[]{mbox.self(), ref, data};
                OtpErlangTuple tuple= new OtpErlangTuple(eoa);
                mbox.send(from, tuple);
            }
        
        
        &lt;/pre&gt;
        
        &lt;p&gt;That is it, a very simple Erlang node which sits and receives
        Erlang messages from another Erlang node and processes them then sends
        its responses back to the requesting Erlang node.&lt;/p&gt;
        
        &lt;p&gt;You only need the jinterface package from the Erlang distribution, and
        import it... &lt;code&gt;import com.ericsson.otp.erlang.*;&lt;/code&gt;&lt;/p&gt;
        
        &lt;p&gt;To start the node listening you simply do this...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;OtpNode self = new OtpNode(getNodeName());
        mbox = self.createMbox(getMboxName());
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;Now you have a node which can be sent to using...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;{database, databasenode@localhost} ! message.
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;The loop has the following...&lt;/p&gt;
        
        &lt;pre&gt;&lt;code&gt;OtpErlangObject o = mbox.receive();
        &lt;/code&gt;&lt;/pre&gt;
        
        &lt;p&gt;which receives a message, which you can then process. This is a little
        wordy but fairly simple...&lt;/p&gt;
        
        &lt;pre&gt;   
        // first check that the message is a tuple
        if(o instanceof OtpErlangTuple){
            // cast it into a tuple object
            OtpErlangTuple msg = (OtpErlangTuple) o;
        
            // extract the first element of the tuple
            OtpErlangPid from = (OtpErlangPid) (msg.elementAt(0));
        
            // extract the second element of the tuple
            OtpErlangObject cmd = msg.elementAt(1);
        
            // extract the ref of the request
            OtpErlangRef ref = (OtpErlangRef) msg.elementAt(2);
        
            // which should be an atom of stop | request
            if(cmd instanceof OtpErlangAtom){
                OtpErlangAtom atom= (OtpErlangAtom)cmd;
        
                // convert the atom to a string
                String c= atom.atomValue();
        
                // if it is stop then we exit the loop
                if(c.equals(&amp;quot;stop&amp;quot;)){
                    jlog.info(&amp;quot;loop(): got stop message&amp;quot;);
                    running= false;
        
                // if it is request we pass the rest of the message
                // onto the code to handle the request
                }else if(c.equals(&amp;quot;request&amp;quot;)){
                    try{
                        byte [][] reply= handleRequest(from, msg);
        
                        // send the rsponse back to the requesting node
                        sendResponse(from, ref, reply);
                    }catch(Exception e){
                        jlog.error(&amp;quot;loop(): got exception from handleRequest()&amp;quot;, e);
                    }
                }else{
                    jlog.error(&amp;quot;loop(): got unknown cmd: &amp;quot; + c);                          
                }
            }else{
                jlog.error(&amp;quot;loop(): got unknown cmd type: &amp;quot; + cmd);
            }
        
        
            // sends a tuple back to requesting Pid {From, Ref, Data}
            private void sendResponse(OtpErlangPid from, OtpErlangRef ref, byte [] ba) {
                // convert the binary reply into and Erlang Binary
                OtpErlangBinary data= new OtpErlangBinary(ba);
        
                // make an array of Erlang Objects
                OtpErlangObject [] eoa= new OtpErlangObject[]{mbox.self(), ref, data};
        
                // make an Erlang tuple out of the Object array above
                OtpErlangTuple tuple= new OtpErlangTuple(eoa);
        
                // send the message back to requesting process Pid
                mbox.send(from, tuple);
            }
        
        }
        
        &lt;/pre&gt;
        
        &lt;p&gt;The worst part is converting back and forth between Erlang objects and
        Java objects.&lt;/p&gt;
        
        &lt;p&gt;You could have several of these nodes running so you can balance the
        load across several servers if needed.&lt;/p&gt;
        
        &lt;p&gt;&lt;a href=&quot;http://technorati.com/tag/erlang+jinterface&quot; rel=&quot;tag&quot;&gt;&lt;/a&gt;&lt;/p&gt;
      </description>
      <author>Jim Morris</author>
      <pubDate>Sun, 12 Apr 2009 17:13:17 -0700</pubDate>
      <link>http://blog.wolfman.com/articles/2009/4/12/using-erlang-with-jinterface</link>
      <guid isPermaLink='false'>urn:uuid:967a55e0-c1af-49d5-a3b6-23b9b229d7f3</guid>
    </item>
    <item>
      <title>"Using Erlang with JInterface" by jaime.a.flores@gmail.com</title>
      <description>
        Hello,
        
        It would have been good to have the complete source code available.
      </description>
      <pubDate>Tue, 23 Jun 2009 09:21:54 -0700</pubDate>
      <link>http://blog.wolfman.com/posts/44#comment-254</link>
      <guid isPermaLink='false'>urn:uuid:346b3447-a010-4390-83b0-b2821be039f8</guid>
    </item>
    <item>
      <title>"Using Erlang with JInterface" by Jim Morris</title>
      <description>
        I agree, unfortunately I cannot release the actual database code for various reasons. Also the Java/Spring/Dao code is pretty standard stuff and good examples can be found in the Spring documentation.
        
        All the JInterface code should be here though, and this article was more about JInterface rather than Java/Spring
      </description>
      <pubDate>Tue, 23 Jun 2009 15:56:22 -0700</pubDate>
      <link>http://blog.wolfman.com/posts/44#comment-255</link>
      <guid isPermaLink='false'>urn:uuid:daf0fc17-0a81-4058-88fa-ccdcfdb51531</guid>
    </item>
    <item>
      <title>"Using Erlang with JInterface" by alanmckean@mac.com</title>
      <description>
        I am trying to get an example running and I dfon't understand how something works ... how can you instantiate OtperlangObject when it is an abstract class. This question only arises because I am using a Scala shell to develop an example. Here is the problem:
        When I evaluate this expression: 'new OtpErlangObject(2)' the shell give me an error that says I can't instantiate OtpErlangObject because it is an abstract class (which, according to the javadocs, it is). But when I run the same example by compiling a Java file, it works! To me, the Scala error makes sense and the Java doesn't. I shouldn't be able to compile the Java file if the class is abstract. What gives?
      </description>
      <pubDate>Fri, 03 Jul 2009 09:45:27 -0700</pubDate>
      <link>http://blog.wolfman.com/posts/44#comment-258</link>
      <guid isPermaLink='false'>urn:uuid:ef72e850-c6ea-4516-a076-d90ae697af8d</guid>
    </item>
    <item>
      <title>"Using Erlang with JInterface" by Jim Morris</title>
      <description>Did you mean 'new OtpErlangObject[2]' to create an array of 2 Erlang Objects? Because new OtpErlangObject(2) would be wrong. The Formet does not instantiate the object which is why it works, the latter would try to instantiate an Object which would be wrong as it is abstract. It is fine to have a variable of an abstract class so long as it is assigned to a concrete sub-class of that class.</description>
      <pubDate>Fri, 03 Jul 2009 14:19:44 -0700</pubDate>
      <link>http://blog.wolfman.com/posts/44#comment-259</link>
      <guid isPermaLink='false'>urn:uuid:2b6645bc-8d87-4885-8407-f790ee437262</guid>
    </item>
    <item>
      <title>"Using Erlang with JInterface" by goldy</title>
      <description>i am working on a project which is a bit torrent software... i have created the GUI using netbeans and the complete software is in erlang. Am really cofused on how to get the corrent data(file name, size, peers, seeds etc) from the database can display it in the GUI.... Can anyone help??</description>
      <pubDate>Tue, 10 Nov 2009 15:33:17 -0800</pubDate>
      <link>http://blog.wolfman.com/posts/44#comment-282</link>
      <guid isPermaLink='false'>urn:uuid:39bfe97b-3ccb-4be2-831c-75cb065085e0</guid>
    </item>
  </channel>
</rss>
