Skip to content

Repository files navigation

Autobahn|Java

Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android.

Docker Hub | TravisDocs


Autobahn|Java is a subproject of the Autobahn project and provides open-source client implementations for

running on Android and Netty/Java8/JVM.

The WebSocket layer is using a callback based user API, and is specifically written for Android. Eg it does not run any network stuff on the main (UI) thread.

The WAMP layer is using Java 8 CompletableFuture for WAMP actions (call, register, publish and subscribe) and the Observer pattern for WAMP session, subscription and registration lifecycle events.

The library is MIT licensed, maintained by the Crossbar.io Project, tested using the AutobahnTestsuite and published as a JAR to Maven and as a Docker toolchain image to Dockerhub.


Download

Grab via Maven:

<dependency>
<groupId>io.crossbar.autobahn</groupId>
<artifactId>autobahn-android</artifactId>
<version>(insert latest version)</version>
</dependency>

Gradle:

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

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

publicvoiddemonstrateSubscribe(Sessionsession, SessionDetailsdetails) {
// 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();
}
});
}
privatevoidonEvent(List<Object> args, Map<String, Object> kwargs, EventDetailsdetails) {
System.out.println(String.format("Got event: %s", args.get(0)));
}

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

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

Publish to a topic

publicvoiddemonstratePublish(Sessionsession, SessionDetailsdetails) {
// Publish to a topic that takes a single argumentsList<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 handlingpubFuture.exceptionally(throwable -> {
throwable.printStackTrace();
returnnull;
});
}

A simpler call would look like:

publicvoiddemonstratePublish(Sessionsession, SessionDetailsdetails) {
CompletableFuture<Publication> pubFuture = session.publish("com.myapp.hello", "Hi!");
...
}

Register a procedure

publicvoiddemonstrateRegister(Sessionsession, SessionDetailsdetails) {
// Register a procedure.CompletableFuture<Registration> regFuture = session.register("com.myapp.add2", this::add2);
regFuture.thenAccept(registration ->
System.out.println("Successfully registered procedure: " + registration.procedure));
}
privateCompletableFuture<InvocationResult> add2(
List<Object> args, Map<String, Object> kwargs, InvocationDetailsdetails) {
intres = (int) args.get(0) + (int) args.get(1);
List<Object> arr = newArrayList<>();
arr.add(res);
returnCompletableFuture.completedFuture(newInvocationResult(arr));
}

A very precise add2 may look like:

privateList<Object> add2(List<Integer> args, InvocationDetailsdetails) {
intres = args.get(0) + args.get(1);
returnArrays.asList(res, details.session.getID(), "Java");
}

Call a procedure

publicvoiddemonstrateCall(Sessionsession, SessionDetailsdetails) {
// 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

publicvoidmain() {
// Create a session objectSessionsession = newSession();
// Add all onJoin listenerssession.addOnJoinListener(this::demonstrateSubscribe);
session.addOnJoinListener(this::demonstratePublish);
session.addOnJoinListener(this::demonstrateCall);
session.addOnJoinListener(this::demonstrateRegister);
// finally, provide everything to a Client and connectClientclient = newClient(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

publicvoidmain() {
...
IAuthenticatorauthenticator = newTicketAuth(authid, ticket);
Clientclient = newClient(session, url, realm, authenticator);
CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Challenge Response Auth

publicvoidmain() {
...
IAuthenticatorauthenticator = newChallengeResponseAuth(authid, secret);
Clientclient = newClient(session, url, realm, authenticator);
CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

Cryptosign Auth

publicvoidmain() {
...
IAuthenticatorauthenticator = newCryptosignAuth(authid, privkey, pubkey);
Clientclient = newClient(session, url, realm, authenticator);
CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

You can also provide a list of Authenticators

publicvoidmain() {
...
List<IAuthenticator> authenticators = newArrayList<>();
authenticators.add(newTicketAuth(authid, ticket));
authenticators.add(newCryptosignAuth(authid, privkey, pubkey));
Clientclient = newClient(session, url, realm, authenticators);
CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}

WebSocket on Android

TBD


Get in touch

Get in touch on IRC #autobahn on chat.freenode.net or join the mailing list.


Version 1

Version 1 of this library is still in the repo here, but is no longer maintained.

Version 1 only supported non-secure WebSocket on Android and only supported WAMP v1.

Both of these issues are fixed in the (current) version of Autobahn|Java.


About

WebSocket & WAMP in Java for Android and Java 8

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages