AutobahnAndroid

Additional

Language
Java
Version
v19.3.1 (Mar 9, 2019)
Created
Sep 21, 2011
Updated
Aug 4, 2019
Owner
Crossbar.io (crossbario)
Contributors
johlo
william-ferguson-au
oberstet
goeddea
murph
zerodivisi0n
almozavr
chrismeyersfsu
filipmaelbrancke
OttoAllmendinger
magnux
ralscha
om26er
fhriley
darkl
noman720
0xflotus
17
Activity
Badge
Generate
Download
Source code
APK file

Advertising

Gradle:

dependencies {
    implementation 'io.crossbar.autobahn:autobahn-android:18.5.1'
}

For non-android systems use artifactID autobahn-java or just Download the latest JAR

Getting Started

The demo clients are easy to run, you only need make and docker installed to get things rolling.

$ make crossbar # Starts crossbar in a docker container
$ make python # Starts a python based WAMP components that provides calls for the Java demo client

and finally

$ make java # Starts the java (Netty) based demo client that performs WAMP actions

Show me some code

The code in demo-gallery contains some examples on how to use the autobahn library, it also contains convenience methods to use. Below is a basic set of code examples showing all 4 WAMP actions.

Subscribe to a topic

public void demonstrateSubscribe(Session session, SessionDetails details) {
    // Subscribe to topic to receive its events.
    CompletableFuture<Subscription> subFuture = session.subscribe("com.myapp.hello",
            this::onEvent);
    subFuture.whenComplete((subscription, throwable) -> {
        if (throwable == null) {
            // We have successfully subscribed.
            System.out.println("Subscribed to topic " + subscription.topic);
        } else {
            // Something went bad.
            throwable.printStackTrace();
        }
    });
}

private void onEvent(List<Object> args, Map<String, Object> kwargs, EventDetails details) {
    System.out.println(String.format("Got event: %s", args.get(0)));
}

Since we are only accessing args in onEvent(), we could simplify it like:

private void onEvent(List<Object> args) {
    System.out.println(String.format("Got event: %s", args.get(0)));
}

Publish to a topic

public void demonstratePublish(Session session, SessionDetails details) {
    // Publish to a topic that takes a single arguments
    List<Object> args = Arrays.asList("Hello World!", 900, "UNIQUE");
    CompletableFuture<Publication> pubFuture = session.publish("com.myapp.hello", args);
    pubFuture.thenAccept(publication -> System.out.println("Published successfully"));
    // Shows we can separate out exception handling
    pubFuture.exceptionally(throwable -> {
        throwable.printStackTrace();
        return null;
    });
}

A simpler call would look like:

public void demonstratePublish(Session session, SessionDetails details) {
    CompletableFuture<Publication> pubFuture = session.publish("com.myapp.hello", "Hi!");
    ...
}

Register a procedure

public void demonstrateRegister(Session session, SessionDetails details) {
    // Register a procedure.
    CompletableFuture<Registration> regFuture = session.register("com.myapp.add2", this::add2);
    regFuture.thenAccept(registration ->
            System.out.println("Successfully registered procedure: " + registration.procedure));
}

private CompletableFuture<InvocationResult> add2(
        List<Object> args, Map<String, Object> kwargs, InvocationDetails details) {
    int res = (int) args.get(0) + (int) args.get(1);
    List<Object> arr = new ArrayList<>();
    arr.add(res);
    return CompletableFuture.completedFuture(new InvocationResult(arr));
}

A very precise add2 may look like:

private List<Object> add2(List<Integer> args, InvocationDetails details) {
    int res = args.get(0) + args.get(1);
    return Arrays.asList(res, details.session.getID(), "Java");
}

Call a procedure

public void demonstrateCall(Session session, SessionDetails details) {
    // Call a remote procedure.
    CompletableFuture<CallResult> callFuture = session.call("com.myapp.add2", 10, 20);
    callFuture.thenAccept(callResult ->
            System.out.println(String.format("Call result: %s", callResult.results.get(0))));
}

Connecting the dots

public void main() {
    // Create a session object
    Session session = new Session();
    // Add all onJoin listeners
    session.addOnJoinListener(this::demonstrateSubscribe);
    session.addOnJoinListener(this::demonstratePublish);
    session.addOnJoinListener(this::demonstrateCall);
    session.addOnJoinListener(this::demonstrateRegister);

    // finally, provide everything to a Client and connect
    Client client = new Client(session, url, realm);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Authentication

Authentication is simple, we just need to create an object of the desired authenticator and pass that to the Client

Ticket Auth

public void main() {
    ...
    IAuthenticator authenticator = new TicketAuth(authid, ticket);
    Client client = new Client(session, url, realm, authenticator);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Challenge Response Auth

public void main() {
    ...
    IAuthenticator authenticator = new ChallengeResponseAuth(authid, secret);
    Client client = new Client(session, url, realm, authenticator);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Cryptosign Auth

public void main() {
    ...
    IAuthenticator authenticator = new CryptosignAuth(authid, privkey, pubkey);
    Client client = new Client(session, url, realm, authenticator);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

You can also provide a list of Authenticators

public void main() {
    ...
    List<IAuthenticator> authenticators = new ArrayList<>();
    authenticators.add(new TicketAuth(authid, ticket));
    authenticators.add(new CryptosignAuth(authid, privkey, pubkey));
    Client client = new Client(session, url, realm, authenticators);
    CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Autobahn also supports POJOs

Here is how to call a remote procedure that returns a list of Person POJOs

// Call a remote procedure that returns a Person with id 1
CompletableFuture<Person> callFuture = mSession.call("com.example.get_person", 1);
callFuture.whenCompleteAsync((person, throwable) -> {
    if (throwable != null) {
        // handle error
    } else {
        // success!
        // do something with person
    }
}, mExecutor);
// call a remote procedure that returns a List<Person>
CompletableFuture<List<Person>> callFuture = mSession.call(
        // remote procedure to call
        "com.example.get_persons_by_department",

        // positional call arguments
        new ArrayList<Object>() {List.of("department-7")},

        // call return type
        new TypeReference<List<Person>>() {}
);

callFuture.whenCompleteAsync((persons, throwable) -> {
    if (throwable != null) {
        // handle error
    } else {
        // success!
        for (Person person: persons) {
            // do something with person
        }
    }
}, mExecutor);

Also register a procedure that returns a Person

private Person get_person() {
    return new Person("john", "doe", "hr");
}

private void main() {
    CompletableFuture<Registration> regFuture = session.register(
            "io.crossbar.example.get_person", this::get_person);
    regFuture.whenComplete((registration, throwable) -> {
        System.out.println(String.format(
                "Registered procedure %s", registration.procedure));
    });
}

WebSocket on Android

Echo example

WebSocketConnection connection = new WebSocketConnection();
connection.connect("wss://echo.websocket.org", new WebSocketConnectionHandler() {
    @Override
    public void onConnect(ConnectionResponse response) {
        System.out.println("Connected to server");
    }

    @Override
    public void onOpen() {
        connection.sendMessage("Echo with Autobahn");
    }

    @Override
    public void onClose(int code, String reason) {
        System.out.println("Connection closed");
    }

    @Override
    public void onMessage(String payload) {
        System.out.println("Received message: " + payload);
        connection.sendMessage(payload);
    }
});