Client library providing WAMP on Java 8 (Netty) and Android, plus (secure) WebSocket for Android.
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.
Grab via Maven:
<dependency>
<groupId>io.crossbar.autobahn</groupId>
<artifactId>autobahn-android</artifactId>
<version>20.7.1</version>
</dependency>
Gradle:
dependencies {
implementation 'io.crossbar.autobahn:autobahn-android:20.7.1'
}
For non-android systems use artifactID autobahn-java
or justDownload the latest JAR
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
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.
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)));
}
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!");
...
}
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");
}
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))));
}
Calling procedure with variable data type parameters
public void demonstrateCall(Session session, SessionDetails details) {
// Call a remote procedure.
byte[] var1 = new byte[20];
String var2 = "A sample text";
int var3 = 99;
List<Object> args = new ArrayList<>();
args.add(var1);
args.add(var2);
args.add(var3);
CompletableFuture<CallResult> callFuture = session.call("com.myapp.myproc", args);
callFuture.thenAccept(callResult ->
System.out.println(String.format("Call result: %s", callResult.results.get(0))));
}
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 is simple, we just need to create an object of the desired authenticator andpass that to the Client
public void main() {
...
IAuthenticator authenticator = new TicketAuth(authid, ticket);
Client client = new Client(session, url, realm, authenticator);
CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}
public void main() {
...
IAuthenticator authenticator = new ChallengeResponseAuth(authid, secret);
Client client = new Client(session, url, realm, authenticator);
CompletableFuture<ExitInfo> exitInfoCompletableFuture = client.connect();
}
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));
});
}
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);
}
});
Building Autobahn is pretty simple
For Android, we recommend to use Android Studio. Just import the project inAndroid Studio, it will tell you if there are any missing dependencies, install themand then just build the project from Build > Rebuild Project
and you will have theaar artifact in autobahn/build/outputs/aar/
To produce a build for non-android systems make sure you have docker and makeinstalled then just use run below command on the root directory of the project
make build_autobahn
and that will output the jar file in autobahn/build/libs/
.
Get in touch by joining our forum.
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.
Spring Boot大量使用自动配置和默认配置,极大地减少了代码,通常只需要加上几个注解,并按照默认规则设定一下必要的配置即可。例如,配置JDBC,默认情况下,只需要配置一个spring.datasource: spring: datasource: url: jdbc:hsqldb:file:testdb username: sa password: dirver-class-name: or
【实例简介】 这个源码的要求安卓studio3.0的版本,gradle-4.1,源码直接下载导入配置一下gradle基本上就可以运行了。需要的小伙伴可以下载 【实例截图】 【核心代码】 autobahn-java-master └── autobahn-java-master ├── autobahn │ ├── build.gradle │ ├── Doxyfile │ ├── RE
【实例简介】 这个源码的要求安卓studio3.0的版本,gradle-4.1,源码直接下载导入配置一下gradle基本上就可以运行了。需要的小伙伴可以下载 【实例截图】 【核心代码】 autobahn-java-master └── autobahn-java-master ├── autobahn │ ├── build.gradle │ ├── Doxyfile │ ├── RE
关于websocket 在安卓上的实现,可以说是一段坎坷路,搜索百度会出现一个叫Websocket的一款API,然而,其用在android上却需要一条坎坷人生路,后来找到了autobahn-Android以后,峰回路转。 Autobahn| Android是由项目实现创建了一个开源的网络库的Java / Android的 WebSocket协议和 Web应用程序消息协议(WAMP)
Autobahn|Android is an open-source networking library for Java/Android created by the Autobahn project that implementsthe WebSocket Protocol andthe Web Application Messaging Protocol (WAMP)for creatin
Socket通信之WebSocket 最近开发中需要通过ws协议通信,于是做了些功课,现在WebSocket用的比较多的就是Autobahn,由于使用方便所以选择了它。 首先需要引入autobahn-0.5.0.jar包,百度上就可以下载。 然后就是使用WebSocketConnection这个类,使用方法直接上代码吧 mConnect.connect(wsurl, new WebSocketHa
autobahn-0.5.0.jar 文件的地址: http://pan.baidu.com/s/1slQYcKP 使用websocket好简单方便,据一天来我们公司的大神说:websocket是封装好的成熟的框架,比socket更安全,用起来方便。在原有websocket的基础上加了一个心跳包的功能。 并且设置了一个链接超时的时间限制。代码还需要不停地优化。 package com.examp
我写了个websocket应用,服务器端是tomcat下的java servelet,用的库是javax.websocket.*,客户端是android app。android端的websocket是用autobahn库做的,我想在服务器端或客户端程序中加入websocket的ping、pong操作,不知怎么加,网上没有合适的例子代码,有几个都是直接定时发消息的,用onmessage事件。不是标准
我正在使用autobahn运行一个websocket服务器来补充我的Django应用程序。有时,我需要从Django向websocket服务器发送消息,该服务器使用websocket-client模块可以很好地工作。我想改用WAMP协议,因为RPC/PubSub API看起来很棒,但python客户机代码是作为扭曲的协议实现的,我不知道如何强制使用它,即像函数调用一样,而不是从某个外部事件循环中使
到目前为止,我已经有了将websocket服务器连接到websocket客户端的基本代码。我使用Autobahn作为服务器代码,使用Advanced REST Client作为客户端。在类中的一个单独的方法中,我在CouchDB中长时间轮询数据库,以查找发生的任何更改,即添加、删除、更新等。此方法在websocket连接打开5秒后得到调用。 如果数据未显示在客户端,或者有时需要很长时间才能到达,则
服务器在7080上提供一个RPC客户机,在8080上提供一个web客户机,在9080上提供一个WebSocket,使用TXJSONRPC、Twisted和Autobahn。Autobahn Web客户端对调试很有用,应该与服务器代码放在同一个目录中。 首先要注意的是,如果在Matlab中使用python有问题,您需要确保使用命令指向系统上的python的正确版本,并且可以使用进行更正 另一个尝试涉
我正在使用android autobahn websocket在android和python tornado套接字服务器之间建立连接。 下面是我在android中使用的高速公路websocket代码。 公开作废开始(){ 所有消息都是通过公共void onTextMessage(对象负载)方法接收的。 问题是,当我发送图像小于128 kb从python套接字服务器,我能够接收它。但是当我发送大小超
对于WebSockets来说是全新的。 谢谢
websocket客户端(使用Autobahn/Python和Twisted)需要连接到websocket服务器:客户端需要向服务器提供其客户端证书,客户端需要检查服务器的证书。例如,这些证书是在Kubernetes minikube安装过程中创建的。特别地: 服务器证书(据我所知为X509格式) 客户端证书~/。minikube/客户。按键 我已经检查过,我可以成功地使用这些证书密钥使用发出库伯