A library for Erlang/Java Interoperability via Erlang's rpc module
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
src
.gitignore
.travis.yml
LICENSE
Makefile
README.md
concrete.mk
custom.mk
pom.xml
rebar.config
rebar.config.script

README.md

gen_java

A library for Erlang/Java Interoperability via Erlang's rpc module

This project generates two artifacts:

  • a .jar file that includes all you need to build your own java project that can respond to erlang's rpc:call/4 function
  • an erlang dependency that provides a gen_java server that you can implement via parse transform.

Java Face

Here's what you need to know on the java side of things

If you want to expose a java method to erlang, it needs to be public, static and have argument and return types from the OTP JInterface library.

For reference, the JInterface package reference can be found here

Maven

You should be able to pull from Maven Central pretty soon with this:

<dependency>
    <groupId>com.devivo</groupId>
    <artifactId>gen_java</artifactId>
    <version>0.1.0</version>
</dependency>

Erlang

Configure gen_java in your sys.config

{gen_java, [
    {modules, [
        {my_module, [
            {jar, "/path/to/jar/file.jar"},
            %% Default thread count is 10.
            %% this is how big the java thread pool is
            {thread_count, 10}
        ]}
    ]}
]}

Create your my_module

-module(my_module).

-compile({parse_transform, gen_java_parse_transform}).

Start your gen_java server

On your own

Start gen_java with my_module:start_link() or my_module:start(). Those functions are free with the parse transform, so don't worry about it.

Or from a supervisor

{my_module,
    {my_module, start_link, []},
    permanent, 5000, worker, [my_module]},

Optional: Init Hollaback

Don't call it a callback, 'cause it's not a behaviour. You can add an init/1 hollaback to your module to do some initialization of your JVM node. The only trick is that you have to use rpc:call/4 since the gen_server isn't started yet.

-spec init(atom()) -> ok.
init(Nodename) ->
    rpc:call(Nodename, 'com.yourcompany.package', 'init', [<<SomeState>>]).

Call Java Methods!

my_module:call('com.whatever.package.Class', 'methodName', ['arg', <<"other arg">>]) will return the value you want!

Worried about waiting forever? There's a call/4 that allows you to specify a timeout.

Optional: Add a convenience wrapper function

-spec method_name(atom(), binary()) -> my_return_type() | gen_java:badrpc().
method_name(Atom, Binary) ->
    call('com.whatever.package.Class', 'methodName', [Atom, Binary]).

my_module:call/3 will have the same dialyzer return type as rpc:call/4

For fun, We provide gen_java:badrpc() for you to use in addition to your expected return type. This will let you just append | gen_java:badrpc() to your spec and then fuggedaboudit.

easy peasy

Provided Java Functions:

%% @doc java.lang.System.getProperties()
-spec system_properties() -> [{atom(), binary()}].
java:system_properties/0

%% @doc java.lang.System.getenv()
-spec system_env() -> [{binary(), binary()}].
java:system_env/0

%% @doc command line $JAVA_OPTS. (e.g. -Xmx512m)
-spec input_arguments() -> binary().
java:input_arguments/0