Note that this is a FORK of a project by NaikSoftware! This version was originally made to avoid using RetroLambda.
(It now has many other important differences.)
This library provides support for STOMP protocol over Websockets.
Right now, the library works as a client for any backend that supports STOMP, such as Node.js (e.g. using StompJS) or Spring Boot (with WebSocket support).
Add library as gradle dependency (Versioning info here):
repositories {
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
compile 'com.github.forresthopkinsa:StompProtocolAndroid:17.11.0'
}
You can use this library two ways:
However, this fork is NOT compatible with Retrolambda. If you have RL as a dependency, then you should be using the upstream version of this project!
Finally, please take bugs and questions to the Issues page! I'll try to answer within one business day.
WebSocketConfig.java
@Configuration
@EnableWebSocket
@EnableWebSocketMessageBroker
class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
// We're using Spring's built-in message broker, with prefix "/topic"
config.enableSimpleBroker("/topic");
// This is the prefix for client requests
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/example-endpoint");
}
}
SocketController.java
@RestController
class SocketController {
@MessageMapping('/hello')
@SendTo('/topic/greetings')
public String greeting(String name) {
return "Hello, " + name + "!";
}
}
Check out the upstream example server
Basic usage
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
// ...
StompClient client = Stomp.over(Stomp.ConnectionProvider.OKHTTP, "http://localhost/example-endpoint");
client.connect();
client.topic("/topic/greetings").subscribe(message -> {
Log.i(TAG, "Received message: " + message.getPayload());
});
client.send("/app/hello", "world").subscribe(
() -> Log.d(TAG, "Sent data!"),
error -> Log.e(TAG, "Encountered error while sending data!", error)
);
// ...
// close socket connection when finished or exiting
client.disconnect();
See the upstream example
Method Stomp.over
uses an enum to know what connection provider to use.
Currently supported connection providers:
Stomp.ConnectionProvider.JWS
('org.java-websocket:Java-WebSocket:1.3.2')Stomp.ConnectionProvider.OKHTTP
('com.squareup.okhttp3:okhttp:3.8.1')You can add own connection provider. Just implement interface ConnectionProvider
.
If you implement new provider, please create pull request :)
Subscribe lifecycle connection
client.lifecycle().subscribe(lifecycleEvent -> {
switch (lifecycleEvent.getType()) {
case OPENED:
Log.d(TAG, "Stomp connection opened");
break;
case CLOSED:
Log.d(TAG, "Stomp connection closed");
break;
case ERROR:
Log.e(TAG, "Stomp connection error", lifecycleEvent.getException());
break;
}
});
Custom client
You can use a custom OkHttpClient (for example, if you want to allow untrusted HTTPS) using the four-argument overload of Stomp.over, like so:
client = Stomp.over(Stomp.ConnectionProvider.OKHTTP, address, null, getUnsafeOkHttpClient());
Yes, it's safe to pass null
for either (or both) of the last two arguments. That's exactly what the shorter overloads do.
Note: This method is only supported using OkHttp, not JWS.
Heartbeating
STOMP Heartbeat implementation is in progress. Right now, you can send a heartbeat request header upon initial websocket connect:
// ask server to send us heartbeat every ten seconds
client.setHeartbeat(10000);
client.connect();
Support
Right now, the library only supports sending and receiving messages. ACK messages and transactions are not implemented yet.
Summary
Improvements: Most of the Rx logic has been rewritten, and a good portion of the other code has also been modified to allow for more stability. Additionally, a lot of blocking code has been replaced with reactive code, resulting in better performance.
Drawbacks: In order to allow for major changes, this branch sacrifices backward compatibility. Code written for the upstream will likely have to be modified to work with this version. You can find more details below.
Build changes
The upstream master is based on Retrolambda. This version is based on Native Java 8 compilation, although it should also work with Jack. It will not work with Retrolambda.
Code changes
These are the possible changes you need to make to your code for this branch, if you were using the upstream before:
client.send("/app/hello", "world").subscribe(
aVoid -> Log.d(TAG, "Sent data!"),
error -> Log.e(TAG, "Encountered error while sending data!", error)
);
!! -v:
client.send("/app/hello", "world").subscribe(new Subscriber<Void>() {
@Override
public void onNext(Void aVoid) {
Log.d(TAG, "Sent data!");
}
@Override
public void onError(Throwable error) {
Log.e(TAG, "Encountered error while sending data!", error);
}
@Override
public void onCompleted() {} // useless
});
client.send("/app/hello", "world").subscribe(
() -> Log.d(TAG, "Sent data!"),
error -> Log.e(TAG, "Encountered error while sending data!", error)
);
Or if you just can't get enough of anonymous classes:
client.send("/app/hello", "world").subscribe(new Subscriber<Object /*This can be anything*/ >() {
@Override
public void onCompleted() {
Log.d(TAG, "Sent data!");
}
@Override
public void onError(Throwable error) {
Log.e(TAG, "Encountered error while sending data!", error);
}
@Override
public void onNext(Object o) {} // useless
});
reconnect
parameter from connect(...)
methods
void connect(boolean reconnect) {...}
void connect(List<StompHeader> _headers, boolean reconnect) {...}
connect
(these existed before, too):
void connect() {...}
void connect(List<StompHeader> _headers) {...}
reconnect()
disconnect()
TimeoutException
Topic subscription now supports wildcard parsing
StompClient client = Stomp.over(...);
client.setParser(StompClient.Parser.RABBITMQ);
client.connect();
client.topic("/topic/*").subscribe(message -> { Log.i(TAG, "Received message: " + message.getPayload()); });
StompClient.setHeartbeat(ms interval)
to send a heartbeat header to the server\u0000
.client.setLegacyWhitespace(true)
.