From Erlang / Elixir to Java and back. Adventure for 20 minutes
- Tutorial
Hi all!
When you have to communicate from the Erlang / Elixir world with Java and back, there are not too many options. All abandoned jinterface and the new library encon , a basic example of the use of which is presented under the cat.
Add dependencies
Add a Encon
dependency to the JVM
application:
Maven :
<dependencies>
...
<dependency><groupId>io.appulse.encon</groupId><artifactId>encon</artifactId><version>1.6.4</version></dependency>
...
</dependencies>
Gradle :
dependencies {
compile'io.appulse.encon:encon:1.6.4'
}
NOTE: if there is such a need (for example, the project is on Ant
), then dependencies in the form of jar files can be found on GitHub, in the releases section .
Run Erlang node
import io.appulse.encon.Node;
import io.appulse.encon.Nodes;
import io.appulse.encon.config.NodeConfig;
// Создание конфига ноды.// Больше деталей - см. проект encon-config
NodeConfig config = NodeConfig.builder()
// true - для локальных нод,// false (по умолчанию) - доступных извне
.shortName(true)
.cookie("secret")
.build();
// Созадние, регистрация в EPMD и запуск сервера новой Erlang ноды
Node node = Nodes.singleNode("echo-node", config);
NOTE: in order for the example above to work, you must either start the daemon EPMD
or its Java implementation .
Create Mailbox
Mailbox, it is a process in Erlang terminology:
import io.appulse.encon.mailbox.Mailbox;
Mailbox mailbox = node.mailbox()
.name("popa") // опционально
.build();
Connection to nodes
NOTE: You can initiate a connection from Erlang / Elixir or Java by automatically sending a message using the plugin format {Имя, Нода}
or by PID (if there is one).
You can start communication between the nodes by sending a ping message from the side of Erlang through net_adm:ping/1
:
(erlang@localhost)1> net_adm:ping('java@localhost').
pong(erlang@localhost)2>
It is also possible to send a message to {Name, Node}
where Node
the view atom is 'java@localhost'
, and Name
this is the PID or registered name of the mailbox that exists on the Java side.
(erlang@localhost)1> {my_process, 'java@localhost'} ! hello.
hello(erlang@localhost)2>
If the mailbox exists on the Java side, then it will receive a message.
We send the message from Java
There is a whole family of send
methods Mailbox
that deliver:
- send ( ErlangPid , ErlangTerm ) - sends a message to a remote or local PID ;
- send ( String , ErlangTerm ) - sends the term to the local mailbox by its name of the same node;
- send ( String , String , ErlangTerm ) - sends a message to a remote / local node and mailbox by its name.
Let's try, open the Erlang-shell and register it with the name ... 'shell'
:
(erlang@localhost)1> erlang:register(shell, self()).
true(erlang@localhost)2>
Now, we can send a message from Java (the connection with the node will be established automatically):
importstatic io.appulse.encon.terms.Erlang.atom;
mailbox.send("erlang@localhost", "shell", atom("hello"));
We return to Erlang and read the received message:
(erlang@localhost) 1> flush().
Shell got hello
ok(erlang@localhost) 2>
Receiving messages in java
To receive an incoming message, you must use one of the Mailbox
methods: receive()
or receive(timeout, timeUnit)
, which can wait indefinitely for a new message or a fixed amount of time.
import io.appulse.encon.Node;
import io.appulse.encon.Nodes;
import io.appulse.encon.config.NodeConfig;
import io.appulse.encon.connection.regular.Message;
import io.appulse.encon.mailbox.Mailbox;
publicclassMain{
publicstaticvoidmain(String[] args){
NodeConfig config = NodeConfig.builder()
.shortName(true)
.build();
Node node = Nodes.singleNode("java@localhost", config);
Mailbox mailbox = node.mailbox()
.name("my_process")
.build();
Message message = mailbox.receive();
System.out.println("Incoming message: " + message.getBody().asText());
}
}
Start the Erlang node and send a message:
$> erl -sname erlang@localhost
...
(erlang@localhost)1> {my_process, 'java@localhost'} ! hello.
Conclusion
These and many other examples can be viewed on the project website and / or on the GitHub page .