Я играл с JInterface и Elixir, и, думаю, я понял твою проблему.
Итак, вы пытаетесь отправить список строк из узла Elixir / Erlang в узел Java, но вы не можете заставить его десериализоваться должным образом.
Эликсир имеет свои собственные типы (например, atoms
, tuples
, ..), а Java имеет свои собственные типы (например, Object
, String
, List<String>
, .. ). Должно быть преобразование из одного типа в другой, если они должны общаться друг с другом. В конце концов это всего лишь набор из 1 и 0, которые все равно отправляются по проводам.
Если список Erlang отправляется на Java, то, что прибывает, всегда можно интерпретировать как OtpErlangObject
. Затем вы должны попытаться угадать, что это за тип, прежде чем мы сможем даже превратить его в значение Java.
// We know that everything is at least an OtpErlangObject value!
OtpErlangObject o = mbox.receive();
Но учитывая, что вы знаете, что это на самом деле список, мы можем превратить его в значение OtpErlangList
.
// We know o is an Erlang list!
OtpErlangList erlList = (OtpErlangList) o;
Элементы этого списка все еще неизвестны. Так что на данный момент это все еще список OtpErlangObject
с.
Но мы знаем, что это список строк, поэтому мы можем интерпретировать список OtpErlangObject
s как список OtpErlangString
s и преобразовать их в Java строки.
public static List<String> ErlangListToStringList(OtpErlangList estrs) {
OtpErlangObject[] erlObjs = estrs.elements();
List<String> strs = new LinkedList<String>();
for (OtpErlangObject erlO : erlObjs) {
strs.add(erlO.toString());
}
return strs;
}
Обратите внимание, что здесь я часто использовал термин список, потому что на самом деле это список Эрланга, в Java он все представлен в виде массива!
Весь мой код указан ниже. Чтобы выполнить это, вставьте его в Java IDE и запустите REPL со следующими параметрами:
iex --name bob@127.0.0.1 --cookie "secret"
Java part:
import com.ericsson.otp.erlang.*;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
public class Main {
public static OtpErlangList StringListToErlangList(List<String> strs) {
OtpErlangObject[] elems = new OtpErlangObject[strs.size()];
int idx = 0;
for (String str : strs) {
elems[idx] = new OtpErlangString(str);
idx++;
}
return new OtpErlangList(elems);
}
public static List<String> ErlangListToStringList(OtpErlangList estrs) {
OtpErlangObject[] erlObjs = estrs.elements();
List<String> strs = new LinkedList<String>();
for (OtpErlangObject erlO : erlObjs) {
strs.add(erlO.toString());
}
return strs;
}
public static void main(String[] args) throws IOException, InterruptedException {
// Do some initial setup.
OtpNode node = new OtpNode("alice", "secret");
OtpMbox mbox = node.createMbox();
mbox.registerName("alice");
// Check that the remote node is actually online.
if (node.ping("bob@127.0.0.1", 2000)) {
System.out.println("remote is up");
} else {
System.out.println("remote is not up");
}
// Create the list of strings that needs to be sent to the other node.
List<String> strs = new LinkedList<String>();
strs.add("foo");
strs.add("bar");
OtpErlangList erlangStrs = StringListToErlangList(strs);
// Create a tuple so the other node can reply to use.
OtpErlangObject[] msg = new OtpErlangObject[2];
msg[0] = mbox.self();
msg[1] = erlangStrs;
OtpErlangTuple tuple = new OtpErlangTuple(msg);
// Send the tuple to the other node.
mbox.send("echo", "bob@127.0.0.1", tuple);
// Await the reply.
while (true) {
try {
System.out.println("Waiting for response!");
OtpErlangObject o = mbox.receive();
if (o instanceof OtpErlangList) {
OtpErlangList erlList = (OtpErlangList) o;
List<String> receivedStrings = ErlangListToStringList(erlList);
for (String s : receivedStrings) {
System.out.println(s);
}
}
if (o instanceof OtpErlangTuple) {
OtpErlangTuple m = (OtpErlangTuple) o;
OtpErlangPid from = (OtpErlangPid) (m.elementAt(0));
OtpErlangList value = (OtpErlangList) m.elementAt(1);
List<String> receivedStrings = ErlangListToStringList(value);
for (String s : receivedStrings) {
System.out.println(s);
}
}
} catch (OtpErlangExit otpErlangExit) {
otpErlangExit.printStackTrace();
} catch (OtpErlangDecodeException e) {
e.printStackTrace();
}
}
}
}