我有一个小型 java 应用程序,我使用 JInterface 将其本质上公开为我的 elixir 应用程序中的 OTP 进程。我可以调用它并成功得到响应。
我的问题是,我在 Elixir 中得到的响应是二进制的,但我不知道如何将二进制转换为字符串列表,这就是响应。
使用 JInterface 的 Java 中的 OTP 节点代码如下:
public void performAction(Object requestData, OtpMbox mbox, OtpErlangPid lastPid){
List<String> sentences = paragraphSplitter.splitParagraphIntoSentences((String) requestData, Locale.JAPAN);
mbox.send(lastPid, new OtpErlangBinary(getOtpStrings(sentences)));
System.out.println("OK");
}
private List<OtpErlangString> getOtpStrings(List<String> sentences) {
List<OtpErlangString> erlangStrings = new ArrayList<>();
for(int i = 0; i < sentences.size(); i++){
erlangStrings.add(new OtpErlangString(sentences.get(i)));
}
return erlangStrings;
}
有必要将响应包装在 OtpErlangBinary 中,并且我已将字符串协调为 OTPErlangString。我也尝试过不将字符串转换为 OTPErlangString。
在 Elixir 端,我可以接收二进制响应并对其进行 IO.inspect。
当结果不是单个字符串时,有人知道如何使用 JInterface 正确反序列化结果吗?或者,如果我犯了一些错误,如何构建正确的响应类型以便我可以正确地反序列化它?
任何帮助将非常感激,因为我多年来一直在努力解决这个问题。 提前致谢。
最佳答案
我一直在使用 JInterface 和 Elixir,我想我已经解决了你的问题。
因此,您尝试将字符串列表从 Elixir/Erlang 节点发送到 Java 节点,但无法使其正确反序列化。
Elixir 有自己的类型(例如 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
值(value)。
// We know o is an Erlang list!
OtpErlangList erlList = (OtpErlangList) o;
然而,该列表的元素仍然未知。所以此时它仍然是 OtpErlangObject
的列表s。
但是,我们知道它是一个字符串列表,因此我们可以解释 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;
}
请注意,我在这里经常使用术语“列表”,因为它实际上是一个 Erlang 列表,在 Java 中它全部表示为数组!
下面列出了我的整个代码。 运行它的方法是将其粘贴到 Java IDE 中,并使用以下参数启动 REPL:
iex --name bob@127.0.0.1 --cookie "secret"
Java部分:
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();
}
}
}
}
关于java - 将 JInterface Java 应用程序的二进制响应转换回 Elixir 中的字符串列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60010255/