integrating erlang and java

29
© ThoughtWorks 2008 Integrating Erlang and Java Dennis Byrne - ThoughtWorks [email protected] http://notdennisbyrne.blogspot.com /

Upload: dennis-byrne

Post on 20-Aug-2015

4.153 views

Category:

Technology


2 download

TRANSCRIPT

© ThoughtWorks 2008

Integrating Erlang and Java

Dennis Byrne - [email protected]

http://notdennisbyrne.blogspot.com/

© ThoughtWorks 2008

Overview

• Java vs. Erlang• Jinterface Intro• Erlang Data Types • Nodes• Message Passing• Process Registration • Linking• Trapping Exits

© ThoughtWorks 2008

Java vs. Erlang

• Strongly typed• Object Oriented• Pass by Reference• Shared Memory• Mutable State• Nouns

• Dynamically Typed• Functional Programming• Pass by Value• Non shared memory• Immutable State• Verbs

Both compiled to byte code

© ThoughtWorks 2008

Introduction

• Created in Java 1.1• Little more than 10,000 LoC• Primarily authored by Gordon Beaton• OTP_DIR\lib\jinterface-X.X\priv\OtpErlang.jar• Jinterface Nodes run in separate user space• Different than JRuby, Jython, Groovy, etc.• Speaks the wire protocol

© ThoughtWorks 2008

Modeling Erlang Types

• OtpErlangObject• OtpErlangPid• OtpErlangRef• OtpErlangList• OtpErlangPort• OtpErlangBinary

• OtpErlangBoolean• OtpErlangByte• OtpErlangTuple• OtpErlangString• OtpErlangFloat• OtpErlangAtom

© ThoughtWorks 2008

Modeling Nodes

• One JVM, more than one node• Jinterface nodes are “hidden nodes”• Hidden Node

– $ erl –hidden– Non-transitive connections– Not returned by erlang:nodes/0

© ThoughtWorks 2008

Modeling a Node, Long Names

$ erl –name name> ‘[email protected]’ = node().

OtpNode node = new OtpNode("[email protected]");

assert "[email protected]".equals(node.node());

© ThoughtWorks 2008

Modeling a Node, Short Name

$erl -sname name

> ‘name@byrned’ = node().

OtpNode node = new OtpNode(“name”);assert “name@byrned”.equals(node.node());

© ThoughtWorks 2008

Cookies, Command Line

$ erl –name name –setcookie cookie> cookie = erlang:get_cookie().

OtpNode node = new OtpNode(“name”, “cookie”);assert "cookie".equals(node.cookie());

© ThoughtWorks 2008

Cookies, Programmatically

$ erl –name name> erlang:set_cookie(node(), cookie)

> cookie = erlang:get_cookie().

OtpNode node = new OtpNode(“name”);node.setCookie("cookie");

assert “cookie”.equals(node.cookie());

© ThoughtWorks 2008

net_adm:ping/0

$ erl> pong = net_adm:ping(b@byrned).> pang = net_adm:ping(c@byrned).

OtpNode a = new OtpNode("a@byrned", "z");OtpNode b = new OtpNode("b@byrned", "z");OtpNode c = new OtpNode("c@byrned", "notz");assert a.ping("b", 20);assert !a.ping("c", 20) & !a.ping("d", 20);

© ThoughtWorks 2008

Local Status Changes

OtpNode node = new OtpNode(“node”);

node.registerStatusHandler( new OtpNodeStatus() { public void localStatus(String node,

boolean up, Object info) {// local initialization // or clean up logic

}});

© ThoughtWorks 2008

Remote Status Changes, monitor_node/2

OtpNode node = new OtpNode(“node”);

node.registerStatusHandler(

new OtpNodeStatus() {

public void remoteStatus(String node, boolean up, Object info) {

// peer node is up or down?

}

});

© ThoughtWorks 2008

Handling Connection Attempts

OtpNode node = new OtpNode("a");

node.registerStatusHandler( new OtpNodeStatus() { public void connAttempt(String node,

boolean incoming, Object info) {// handle failed connections

}});

© ThoughtWorks 2008

Modeling Processes with OtpMbox$ erl –sname foo> Pid = self(), Msg = 999.> spawn( fun() -> Pid ! Msg end ).> Msg = receive Any -> Any end.

OtpNode node = new OtpNode("foo");OtpMbox first = node.createMbox();OtpMbox second = node.createMbox();OtpErlangInt msg = new OtpErlangInt(999);second.send(first.self(), msg);assert msg.equals(first.receive());

© ThoughtWorks 2008

receive

$ erl

> receive Any -> Any after 1000 -> true end.

OtpMbox mailBox = node.createMbox();

mailBox.receive(1000);

© ThoughtWorks 2008

Pass By Value

OtpNode node = new OtpNode("value");OtpMbox from = node.createMbox();OtpMbox to = node.createMbox();OtpErlangLong sent = new OtpErlangLong(9);from.send(to.self(), sent);Object received = to.receive();

assert sent != received;

© ThoughtWorks 2008

User Defined Classes

OtpMbox to = node.createMbox();OtpMbox from = node.createMbox();Customer customer = new Customer();customer.name = "Dennis";

from.send(to.self(), new OtpErlangBinary(customer));

OtpErlangBinary bin = (OtpErlangBinary) to.receive();Customer object = (Customer)bin.getObject();assert "Dennis".equals(object.name);

© ThoughtWorks 2008

Remote Execution

OtpErlangObject[] call = new OtpErlangObject[] {new OtpErlangAtom("call"),new OtpErlangAtom("erlang"), /* mod */new OtpErlangAtom("node"), /* fun */new OtpErlangList(), /* arg */new OtpErlangAtom("user")

};OtpErlangTuple msg = new OtpErlangTuple( new OtpErlangObject[] {

mailBox.self(), new OtpErlangTuple(call)

});

© ThoughtWorks 2008

Remote Execution

mailBox.send("rex", "d@byrned", msg);

OtpErlangTuple response =

(OtpErlangTuple) mailBox.receive();

OtpErlangObject proc = response.elementAt(0);

assert "rex".equals(proc.toString());

OtpErlangObject from = response.elementAt(1);

assert "d@byrned".equals(from.toString());

© ThoughtWorks 2008

register/2$ erl> register(first, self()).> Msg = 999.> spawn(fun() -> first ! Msg end). Msg = receive Any -> Any end.

OtpMbox first = node.createMbox();OtpMbox second = node.createMbox();OtpErlangInt msg = new OtpErlangInt(999);first.registerName("first");second.send("first", msg);assert msg.equals(first.receive());

© ThoughtWorks 2008

whereis/2

$ erl

> Pid = self().

> register(w, Pid).

> spawn(fun() -> Pid = whereis(w) end).

OtpNode node = new OtpNode(“whereis”);OtpMbox first = node.createMbox(“w”);OtpMbox second = node.createMbox();

assert first.self() == second.whereis(“w”);

© ThoughtWorks 2008

registered/0> register(a, self()).

> F = fun() -> receive Any -> Any end end.

> register(b, spawn(F)).

> true = lists:member(a, registered()).

> true = lists:member(b, registered()).

OtpNode node = new OtpNode("node");

node.createMbox("a");

node.createMbox("b");

List names = Arrays.asList(node.getNames());

assert names.contains("a");

assert names.contains("b");

© ThoughtWorks 2008

Linking

> process_flag(trap_exit, true).

> F = fun() ->

receive after 200 -> exit(normal) end

end.

> Pid = spawn_link(F).

OtpMbox first = node.createMbox();

OtpMbox second = node.createMbox();

first.link(second.self());

second.close();

© ThoughtWorks 2008

Trapping Exits

{'EXIT', Pid, normal} = receive X -> X end.

try {

first.receive();

}catch(OtpErlangExit e) {

assert second.self().equals(e.pid());

assert "normal".equals(e.getMessage());

}

© ThoughtWorks 2008

Unlinking

> Pid = spawn_link(Fun).

> unlink(Pid).

> nil = receive X -> received

after 2000 -> nil end.

OtpMbox first = node.createMbox();

OtpMbox second = node.createMbox();

first.link(second.self());

second.unlink(first.self());

second.exit("normal");

assert null == first.receive(1);

© ThoughtWorks 2008

Concurrent Programming

• Fast Context Switching• Fast Message Passing• Fast Process Spawning

© ThoughtWorks 2008

Synchronization

• Sending and receiving messages• Mailbox creation • Linking and unlinking processes• Node creation

© ThoughtWorks 2008

Thanks

Dennis [email protected]

http://notdennisbyrne.blogspot.com/