A journey to find those pieces of software or technology that facilitate productive and maintainable software development

Showing posts with label HOWTO. Show all posts
Showing posts with label HOWTO. Show all posts

Monday, August 24, 2009

Concise HOWTO's: Message from Java to Erlang

First create an Erlang module called server that receives messages in the format {Sender,Data} and echoes the Data portion back to the Sender. Then create a Java class called EchoClient that prompts for a node to connect to and prompts in a loop for messages to send. You will need OtpErlang.jar in your build classpath and runtime classpath. I found it in /opt/local/lib/erlang/lib/jinterface-1.5.1/priv/ on Mac OS X. I had to install Erlang from source on Ubuntu since the APT package is missing Jinterface.

Listing of server.erl:

-module(server).
-compile(export_all).

start() -> register(server,spawn(fun loop/0)).
loop() ->
    receive
        {Sender,Data} ->
            Sender ! Data,
            loop();
        shutdown -> ok
    end.

Listing of EchoClient.java

import java.io.BufferedReader;
import java.io.InputStreamReader;

import com.ericsson.otp.erlang.*;

public class EchoClient {
    public static void main(String[] args) throws Exception {
        OtpNode node = new OtpNode("java");
        OtpMbox mbox = node.createMbox("admin_gui");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String defaultServerNodeName = "erl_node@" + node.host();
        System.out.format("Server Node to contact [%s]> ", defaultServerNodeName);
        String serverNodeName = in.readLine();
        if (serverNodeName == null || "".equals(serverNodeName)) {
            serverNodeName = defaultServerNodeName;
        }
        OtpErlangTuple serverPidTuple = new OtpErlangTuple(new OtpErlangObject[] {
                new OtpErlangAtom("server"), new OtpErlangAtom(serverNodeName)});
        while (true) {
            if (!node.ping(serverNodeName, 1000)) {
                System.out.println("Erlang node is not available: " + serverNodeName);
                System.exit(1);
            }
            System.out.print("Message (Hit Enter to send)> ");
            String message = in.readLine();
            if (message != null) {
                mbox.send("server", serverNodeName, new OtpErlangTuple(
                        new OtpErlangObject[] {
                                mbox.self(), new OtpErlangList(message)}));
                OtpErlangObject serverReply = mbox.receive(1000);
                if (serverReply == null) {
                    System.out.println("WARN: Timeout when receiving reply");
                } else {
                    System.out.format("%s replied : %s%n", serverPidTuple, serverReply);
                }
            }
        }
    }
}

Open an Erlang shell in the directory with server.erl by running erl -sname erl_node. From that shell compile and run the Erlang server module.

Listing of the Erlang shell interaction

$> erl -sname erl_node
Erlang R13B01 (erts-5.7.2) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.2  (abort with ^G)
(erl_node@alains_desktop)1> server:start().
true
(erl_node@alains_desktop)2> server ! {self(), hello}.
{<0.84.0>,hello}
(erl_node@alains_desktop)3> f(M), receive M -> {ok, M} after 100 -> {error,timeout} end.
{ok,hello}
(erl_node@alains_desktop)4>

Run the EchoClient Java program and either accept the default node or specify the name of another Erlang node you want to work with. Type messages in and see them echoed back to the EchoClient console.

Listing of the EchoClient Java program console interaction:

Server Node to contact [erl_node@alains_desktop]> [ENTER]
Message (Hit Enter to send)> Hello, Erlang![ENTER]
{server,erl_node@alains_desktop} replied : "Hello, Erlang!"
Message (Hit Enter to send)>

Concise HOWTOS: Install Erlang/OTP R13B01 from Source on Ubuntu 9.04

Generally it is better to use packages, so why have this HOWTO? Ubuntu 9.04's Erlang package is missing Jinterface, but it works when you build Erlang from source. Debian or Ubuntu will address this omission at some point. Until then we can build and install the latest Erlang release fairly easily.

The only real frustration in building from source is making sure all of the necessary build dependencies are installed first. Well, it also takes a significant chunk of time to build...

sudo apt-get install build-essential libncurses-dev \
                     unixodbc-dev libssl-dev \
                     libwxgtk2.8-dev default-jdk
curl http://erlang.org/download/otp_src_R13B01.tar.gz
tar xzvf otp_src_R13B01.tar.gz
cd otp_src_R13B01/
./configure
make
sudo make install

The make step takes a long time. It made me really appreciate the pre-built packages I can get so easily and quickly with APT.

Sunday, August 23, 2009

Concise HOWTO's: Message from Erlang to Java

First create an EchoServer in Java that receives messages in the format {Sender,Data} and echoes the Data portion back to the Sender. You will need OtpErlang.jar in your build classpath and runtime classpath. I found it in /opt/local/lib/erlang/lib/jinterface-1.5.1/priv/ on Mac OS X. I had to install Erlang from source on Ubuntu since the APT package is missing Jinterface.

Listing for EchoServer.java:

 
import com.ericsson.otp.erlang.*;

public class EchoServer {
    public static void main(String[] args) throws Exception {
        OtpNode node = new OtpNode("java");
        OtpMbox mbox = node.createMbox("echo");
        OtpErlangAtom SHUTDOWN = new OtpErlangAtom("shutdown");
        while (true) {
            OtpErlangObject message = mbox.receive();
            System.out.format("%s received: %s%n", mbox.self(), message);
            if (SHUTDOWN.equals(message)) {
                System.out.format("%s shutting down...%n", mbox.self());
                break;
            } else if (message instanceof OtpErlangTuple) {
                OtpErlangTuple messageTuple = (OtpErlangTuple) message;
                if (messageTuple.arity() == 2 && messageTuple.elementAt(0) instanceof OtpErlangPid) {
                    OtpErlangPid sender = (OtpErlangPid) messageTuple.elementAt(0);
                    OtpErlangObject sendersMessage = messageTuple.elementAt(1);
                    mbox.send(sender, sendersMessage);
                }
            }
        }
    }
}

Once you have compiled and started the EchoServer you can communicate with it from the Erlang shell. First you need to start a new named node with erl -sname erl_node.

Listing of the Erlang shell interaction:

Erlang R13B01 (erts-5.7.2) [source] [64-bit] [smp:4:4] [rq:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.7.2  (abort with ^G)
(erl_node@alains_desktop)1> net_adm:ping(java@alains_desktop).                   
pong
(erl_node@alains_desktop)2> {echo,java@alains_desktop} ! {self(),"Hello, Java!"}.
{<0.39.0>,"Hello, Java!"}
(erl_node@alains_desktop)3> % use f(M) to "forget" M (make it unbound)
(erl_node@alains_desktop)3> f(M), receive M -> {ok,M} after 100 -> {error,timeout} end.
{ok,"Hello, Java!"}
(erl_node@alains_desktop)4> {echo,java@alains_desktop} ! {self(),{tuples,can,be,sent,too}}.
{<0.39.0>,{tuples,can,be,sent,too}}
(erl_node@alains_desktop)5> f(M), receive M -> {ok,M} after 100 -> {error,timeout} end.
{ok,{tuples,can,be,sent,too}}
(erl_node@alains_desktop)6> {echo,java@alains_desktop} ! shutdown.
(erl_node@alains_desktop)6>
(erl_node@alains_desktop)7> {echo,java@alains_desktop} ! shutdown.                         
shutdown
(erl_node@alains_desktop)8> {echo,java@alains_desktop} ! {self(),"Are you there?"}.        
{<0.39.0>,"Are you there?"}
(erl_node@alains_desktop)9> f(),receive M -> {ok,M} after 100 -> {error,timeout} end.
{error,timeout}
(erl_node@alains_desktop)10>

Listing of EchoServer Java process output:

#Pid received: {#Pid,"Hello, Java!"}
#Pid received: {#Pid,{tuples,can,be,sent,too}}
#Pid received: shutdown
#Pid shutting down...

SyntaxHighlighter