Languages/Erlang2009.06.23 14:07
Erlang과 Java를 연동시키려면 Erlang의 runtime을 띄울 때 epmd가 구동되도록 해야 합니다. 별도로 실행 방법을 알 필요는 없고, erl을 띄울 때 node 이름과 host name을 지정해 주면 됩니다.

$> erl -name foo@foo.bar

그렇게 하면 epmd가 자동으로 듭니다. 그래야 나중에 Java가 붙을 때 Java 프로그램의 node 이름이 해당 epmd에 등록 되기 때문에, 반드시 이렇게 해 주어야 합니다.

Erlang과 Java 프로그램의 연동은 서로 메시지를 주고 받는 과정을 통해서 이루어집니다. 따라서 연동을 하려면 Java 프로그램과 연동할 Erlang 프로세스가 떠 있어야 합니다. 다음의 간단한 프로그램 예제를 봅시다. 이 파일을 ets_java_frontend.erl로 저장하고 컴파일 해 둡니다.

-module(ets_java_frontend).
-export([start/0, shutdown/0, show/0, rpc/1]).

start() ->
    LoopPid = spawn(fun loop/0),
    register(ets_server, LoopPid).

shutdown() ->
    Pid = whereis(ets_server),
    Pid ! quit.

show() ->
    Pid = whereis(ets_server),
    Pid ! show.

rpc(T) ->
    Pid = whereis(ets_server),
    Pid ! T.

loop() ->
    EtsHandle = ets:new(test, [set]),
    loop(EtsHandle).

loop(Handle) ->
    receive
        show ->
            List = ets:tab2list(Handle),
            io:format("~p~n", [List]),
            loop(Handle);
        quit ->
            {ok, terminated};
        {tuple, T} ->
            io:format("msg is received ~p~n", [T]),
            ets:insert(Handle, T),
            loop(Handle);
        true ->
            io:format("unprocessable msg is received~n"),
            loop(Handle)
    end.

이 Erlang 프로그램은 {tuple, T} 형태의 메시지를 받으면 T (투플입니다)를 ets에 저장하는 프로그램입니다. spawn해서 프로세스를 생성할 때 해당 프로세스의 Pid를 register() 호출을 통해 등록하고 있는데, Java쪽에서 이 Erlang 프로그램에 메시지를 보낼 때 register()할 때 전달한 프로세스 이름(위의 경우에는 ets_server)을 통해 해당 프로세스의 mbox에 메시지를 전달하므로, register()를 반드시 호출해 프로세스 이름을 등록해 두어야 합니다.

이렇게 하면 Java 프로그램 안에서 Erlang 프로세스에 메시지를 전달할 수 있는데요. 공짜로 되는 것은 아니고 (당연하겠죠?) Erlang 패키지에 포함되어 있는 JInterface라는 라이브러리를 통하여야 합니다. Windows라면 해당 라이브러리는 C:/Program Files/erl5.7.2/lib/jinterface-1.5.1/priv에 있고, Unix라면 아마 /usr/lib/erlang/ 아래 어딘가에 해당 jar가 있을 겁니다. ^^;

잡소리는 집어치우고 해당 프로그램 예제를 간단하게 훑어보면...

import java.io.IOException;
import com.ericsson.otp.erlang.*;

public class ETP {

    private String node;
    private OtpNode self;
    private OtpMbox mbox;

    /**
     * create ETP instance.
     * @param name name of the erlang server node.
     * @throws IOException
     */
    public ETP(String node) throws IOException {
       
        this.node = node;
       
        try {
            this.self = new OtpNode("java_erl_bjlee");
        } catch ( IOException e ) {
            System.err.println("cannot create ETP instance.");
            e.printStackTrace();
            throw e;
        }

        this.mbox = self.createMbox("etp_java_client");
    }

    private OtpErlangTuple createMessage(OtpErlangTuple tuple) {
       OtpErlangObject[] aTerm = new OtpErlangObject[2];
       aTerm[0] = new OtpErlangAtom("tuple");
       aTerm[1] = tuple;
       OtpErlangTuple msg = new OtpErlangTuple( aTerm );
       return msg;
   }

   private void send(OtpErlangTuple msg) {
       mbox.send("ets_server", this.node, msg);
   }
   
    public boolean put(String key, String value) {
        OtpErlangObject[] aTuple = new OtpErlangObject[2];
        aTuple[0] = new OtpErlangAtom(key);
        aTuple[1] = new OtpErlangAtom(value);
        OtpErlangTuple tuple = new OtpErlangTuple(aTuple);
       
        OtpErlangTuple msg = createMessage(tuple);
       
        send(msg);
       
        return true;
    }
}

this.node에는 통신할 Erlang 노드의 이름이 들어갑니다. 이 페이지 맨 위에서처럼 했다면 foo가 들어가야겠군요. 먼저 OtpNode를 생성하구요. (이름을 주어야 합니다. Java 프로그램은 별개의 Erlang 노드인 것처럼 동작하거든요.) 그 다음에 message 송수신에 사용될 mbox를 만듭니다.

그 다음에는 이제 메시지를 보내 Erlang 프로그램이 원하는 작업을 하도록 만들면 됩니다. put 메소드의 코드를 보시면 되겠습니다. mbox.send() 함수가 최종적으로 호출되는데, 이 때 첫 번째 인자로는 통신할 erlang 프로세스의 registered name이 들어가고, 두 번째 인자로는 해당 프로세스가 돌고 있는 Erlang node, 그리고 세 번째 인자로는 실제로 전송할 메시지가 들어갑니다.

이제 Main 클래스를 다음과 같이 작성하고 돌려보면...

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
       
        ETP etp;
       
        try {
            etp = new ETP("foo");
        } catch (IOException e) {
           
            e.printStackTrace();
            return;
        }
       
        etp.put("test1", "value1");
        etp.put("test2", "value2");
       
        System.out.println("finished");
    }
}

참. 돌리기 전에 erl 셸에서 ets_java_frontend:start()를 먼저 실행해주어야 합니다. ㅎㅎ 어쨌든 실행하고 위의 Java 프로그램을 돌려보면... erl 쪽 화면에 메시지들이 찍히면서 ets에 내가 전송한 투플들이 저장됩니다. 저장이 잘 되었는지는 erl 셸에서 ets_java_frontend:show()를 실행하여 확인할 수 있습니다.

신고
Posted by 이병준

소중한 의견, 감사합니다. ^^

  1. 땅꼬마

    감사합니다, 좋은 정보 얻어가네요 ^^

    2009.12.24 10:28 신고 [ ADDR : EDIT/ DEL : REPLY ]