Всем хай!
Когда приходится общаться из Erlang/Elixir мира с Java и обратно — не так уж и много вариантов имеется. Всеми заброшенный jinterface и новая библиотека encon, базовый пример использования которой представлен под катом.
Добавление зависимостей
Добавляем Encon
зависимость к JVM
приложению:
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'
}
ЗАМЕТЬТЕ: если есть такая необходимость (например проект на Ant
), то зависимости в виде jar-файлов можно найти на GitHub, в разделе релизы.
Запуск Erlang-ноды
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);
ЗАМЕТЬТЕ: что бы пример выше заработал, необходимо либо запустить демон EPMD
или его Java-имплементацию.
Создание мейлбокса
Мейлбокс, он же процесс, в терминалогии Erlang:
import io.appulse.encon.mailbox.Mailbox;
Mailbox mailbox = node.mailbox()
.name("popa") // опционально
.build();
Подключение к нодам
ЗАМЕТЬТЕ: Вы можете инициировать соединение из Erlang/Elixir или Java автоматически отправив сообщение, используя формат тюпла {Имя, Нода}
или по PID'у (если он есть).
Можно начать общение между нодами с отправки ping-сообщения cо стороны Erlang через net_adm:ping/1
:
(erlang@localhost)1> net_adm:ping('java@localhost').
pong
(erlang@localhost)2>
Также возможно отправить сообщение на {Name, Node}
, где Node
это атом вида 'java@localhost'
, и Name
это PID или зарегестрированное имя мейлбокса, который существует на стороне Java.
(erlang@localhost)1> {my_process, 'java@localhost'} ! hello.
hello
(erlang@localhost)2>
Если мейлбокс существует на стороне Java, то он получит сообщение.
Отправляем сообщение из Java
Есть целое семейство send
-методов у Mailbox
, которые доставляют:
- send(ErlangPid, ErlangTerm) — отправляет сообщение на удалённый или локальный PID;
- send(String, ErlangTerm) — пересылает терм на локальный мейлбокс по его имени этой же ноды;
- send(String, String, ErlangTerm) — отправляет сообщение на удалённую/локальную ноду и мейлбокс по его имени.
Давайте попробуем, откроем Erlang-shell и зарегаем его с именем...'shell'
:
(erlang@localhost)1> erlang:register(shell, self()).
true
(erlang@localhost)2>
Теперь, мы можем отправить сообщулю из Java (связь с нодой будет установлена автоматически):
import static io.appulse.encon.terms.Erlang.atom;
mailbox.send("erlang@localhost", "shell", atom("hello"));
Возвращаемся в Erlang и читаем полученное сообщение:
(erlang@localhost) 1> flush().
Shell got hello
ok
(erlang@localhost) 2>
Получение сообщений в Java
Для получения входящего сообщения необходимо воспользоваться одним из Mailbox
-методов: receive()
или receive(timeout, timeUnit)
, которые могут бесконечно ждать нового сообщения или фиксированное количество времени.
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;
public class Main {
public static void main (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());
}
}
Стартанём Erlang ноду и отправим сообщение:
$> erl -sname erlang@localhost
...
(erlang@localhost)1> {my_process, 'java@localhost'} ! hello.
Заключение
Эти и многие другие примеры можно изучить на сайте проекта и/или на GitHub страничке.