Elixir/Phoenix
Erlang/OTP
Java
September 2018 19

Из Erlang/Elixir в Java и обратно. Приключение на 20 минут

Tutorial

Всем хай!


Когда приходится общаться из 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 страничке.

+5
3.2k 22
Comments 6