将来自 JInterface Java 应用程序的二进制响应转换回 Elixir 中的字符串列表

Converting binary response from JInterface Java app back into list of strings in Elixir

我有一个小型 java 应用程序,我使用 JInterface 在我的 elixir 应用程序中将其作为 OTP 进程公开。我可以调用它并成功获得响应。

我的问题是我在 elixir 中得到的响应是二进制的,但我不知道如何将二进制转换为字符串列表,这就是响应。

我在 Java 中使用 JInterface 的 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。

在长生不老药方面,我可以收到二进制响应 IO.inspect 它。

有人知道如何使用 JInterface 正确反序列化不是单个字符串的结果吗?或者,如果我犯了一些错误,如何构建正确的响应类型以便我可以正确反序列化它?

任何帮助将不胜感激,因为我多年来一直在努力解决这个问题。 提前致谢。

我一直在研究 JInterface 和 Elixir,我想我已经解决了你的问题。

因此您正尝试将字符串列表从 Elixir/Erlang 节点发送到 Java 节点,但无法正确反序列化。

Elixir 有自己的类型(例如 atomstuples、..)并且 Java 有自己的类型(例如 ObjectStringList<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 列表解释为 OtpErlangString 列表,并将它们转换为 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();
            }
        }
    }
}