Make an rpc call from Erlang/Elixir to Java via JInteface

587 views Asked by At

Is it possible to make an rpc:call from erlang to java, using JInterface?

If yes, what should the Module argument in the call function set to?

call(Node, Module, Function, Args) -> Res | {badrpc, Reason}

What I got working was this (simple message send, see code below):

> {javambox, server@javaapp} ! {self(), greet, <<"Hello man">>}.
> flush().
Shell got {bye,10000}

But not an rpc call. Here was my attempt:

> rpc:call(server@javaapp, javambox, greet, <<"Hello man">>, 1000).
{badrpc,timeout}

Full Java Code

MyInterface.java:

import com.ericsson.otp.erlang.*;

import java.lang.reflect.InvocationTargetException;

public class MyInterface {

    OtpErlangPid from = null;
    OtpMbox myOtpMbox = null;

    public static void main(String[] args) {
        MyInterface i = new MyInterface();
    }

    public MyInterface() {
        setupMBox();
    }
    private void setupMBox() {
        System.out.println("Setting up mbox");
        try {
            // server@java-app??
            OtpNode myOtpNode = new OtpNode("server");
            myOtpNode.setCookie("secret");

            myOtpMbox = myOtpNode.createMbox("javambox");
            System.out.println("System ready to accept messages.");
            System.out.println("Hostname is:");
            System.out.println(java.net.InetAddress.getLocalHost().getHostName() );
            System.out.println("List of known names:");
            System.out.println(String.join(" , ", myOtpNode.getNames()));
            System.out.println("Secret cookie is:");
            System.out.println(myOtpNode.cookie());

            while (true) {
                OtpErlangTuple tuple = (OtpErlangTuple) myOtpMbox.receive();
                System.out.println("GOT MESAGE!");

                from = (OtpErlangPid) tuple.elementAt(0);
                OtpErlangAtom dispatch = (OtpErlangAtom) tuple.elementAt(1);

                if (dispatch.toString().equals("settext")) {

                    final OtpErlangBinary message = (OtpErlangBinary) tuple.elementAt(2);

                    System.out.println("Setting text to: " + new String(message.binaryValue()));
                } else if (dispatch.toString().equals("greet")) {
                    final OtpErlangBinary message = (OtpErlangBinary) tuple.elementAt(2);
                    // Send reply
                    OtpErlangAtom myAtom = new OtpErlangAtom("bye");
                    OtpErlangObject[] reply = new OtpErlangObject[2];
                    reply[0] = myAtom;
                    reply[1] = new OtpErlangInt(10000);
                    OtpErlangTuple myTuple = new OtpErlangTuple(reply);
                    myOtpMbox.send(from, myTuple);
                    System.out.println("Greet got, bye!");

                } else{
                    System.out.println("Got unexpected message....");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Java Node Output

Setting up mbox
System ready to accept messages.
Hostname is:
javaapp
List of known names:
javambox
Secret cookie is:
secret
GOT MESAGE!
Greet got, bye!
1

There are 1 answers

2
Vlad Dumitrescu On

The Java side has no concept of modules, so you can use whatever name in the RPC. Check the sources to see how the call is encoded as a message, and don't forget to send an answer back. I find it easier to reason about simple messages, but maybe you don't want to care if the remote node is erlang or java. Hope this helps.