Use the Scaledrone Java client to connect to the Scaledrone realtime messaging service
This project goes hand to hand with Scaledrone documentation. It's still a work in progress, pull requests and issues are very welcome.
The library is hosted on the Jcenter repository, so you need to ensure that the repo is referenced also; IDEs will typically include this by default:
repositories {
jcenter()
}
<dependency>
<groupId>com.scaledrone</groupId>
<artifactId>scaledrone-java</artifactId>
<version>0.7.0</version>
<type>pom</type>
</dependency>
compile 'com.scaledrone:scaledrone-java:0.7.0'
If you are using this library on Android make sure you add the INTERNET permission to the manifest file.
<uses-permission android:name="android.permission.INTERNET" />
final Scaledrone drone = new Scaledrone("CHANNEL_ID_FROM_DASHBOARD");
drone.connect(new Listener() {
@Override
public void onOpen() {
drone.subscribe("myroom", new RoomListener() {
@Override
public void onOpen(Room room) {
room.publish("Hello world");
}
@Override
public void onOpenFailure(Room room, Exception ex) {
// This can happen when you don't have correct permissions
System.out.println("Failed to subscribe to room: " + ex.getMessage());
}
@Override
public void onMessage(Room room, Message message) {
System.out.println("Message: " + message.getData().asText());
}
});
}
@Override
public void onOpenFailure(Exception ex) {
System.out.println("Failed to open connection: " + ex.getMessage());
}
@Override
public void onFailure(Exception ex) {
System.out.println("Unexcpected failure: " + ex.getMessage());
}
@Override
public void onClosed(String reason) {
System.out.println("Connection closed: " + reason);
}
});
Connecting to a new channel is done by creating a new instance of Scaledrone
and calling the connect()
method. To create your own channel_id
create a Scaledrone account and a new channel from Scaledrone dashboard.
final Scaledrone drone = new Scaledrone("channel_id");
drone.connect(new Listener() {
// overwrite the Listener methods
});
Subscribing to messages is done by subscribing to a room. Rooms are used to group users into groups, to which we can then publish messages. You can subscribe to multiple rooms.
A received message is of type JsonNode
. Jackson JsonNode
can easily be transferred into POJO or String.
drone.subscribe("myroom", new RoomListener() {
@Override
public void onMessage(Room room, Message message) {
// parse as string
System.out.println("Message: " + message.getData().asText());
// or parse as POJO
try {
ObjectMapper mapper = new ObjectMapper();
Pojo pojo = mapper.treeToValue(message.getData(), Pojo.class);
System.out.println("Message: " + pojo);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
// overwrite other methods
});
A published message will be converted to JSON using Jackson. You don't have to be subscribed to a room when publishing to it.
drone.publish("roomName", data);
// or
room.publish(data);
Using authentication is optional, it can be enabled from the channel settings page. Scaledrone uses JSON Web Token for authentication.
A typical authentication flow happens after connecting to a channel. At that point the user would send the drone.getClientID()
to your personal authentication server which returns a JSON Web Token. The token is then passed on to Scaledrone.
Use the jwt.io debugger to help you debug your JWT tokens.
final Scaledrone drone = new Scaledrone("channel_id");
drone.connect(new Listener() {
@Override
public void onOpen() {
final String jwt = requestJWTFromYourAuthServer(drone.getClientID());
drone.authenticate(jwt, new AuthenticationListener() {
@Override
public void onAuthentication() {
// user is now connected to the channel
}
@Override
public void onAuthenticationFailure(Exception ex) {
// something went wront, probably a problem with the JWT
}
});
}
// overwrite methods
See the Scaledrone JWT authentication docs on what the token should look like. See the authentication tests to see how to generate a JWT on the server side.
Observable rooms act like regular rooms but provide additional events for keeping track of connected members.
Observable room names need to be prefixed with observable-
.
final Scaledrone drone = new Scaledrone("channel_id", data);
drone.connect(new Listener() {
@Override
public void onOpen() {
Room room = drone.subscribe("observable-myroom", new RoomListener() {
// Overwrite regular room listener methods
});
room.listenToObservableEvents(listener, new ObservableRoomListener() {
@Override
public void onMembers(Room room, ArrayList<Member> members) {
// Emits an array of members that have joined the room. This event is only triggered once, right after the user has successfully connected to the observable room.
// Keep in mind that the session user will also be part of this array, so the minimum size of the array is 1
Member member = members.get(0);
ObjectMapper mapper = new ObjectMapper();
try {
Data d = mapper.treeToValue(member.getClientData(), Data.class);
} catch (JsonProcessingException e) {
}
}
@Override
public void onMemberJoin(Room room, Member member) {
// A new member joined the room.
}
@Override
public void onMemberLeave(Room room, Member member) {
// A member left the room (or disconnected)
});
});
}
When creating a Scaledrone room you can supply the number of messages to recieve from that room's history. The messages will arrive, in reverse chronological order and one by one, in scaledroneRoomDidReceiveMessage
, just like real-time messages.
Pass the SubscribeOptions
as the second parameter to the subscribe
method to define how many messages you would like to receive.
You can then listen to the history messages using room.listenToHistoryEvents()
.
In order to recieve message history messages, this feature needs to be enabled in the Scaledrone dashboard. You can learn more about Message History and its limitations in Scaledrone docs.
Room room = drone.subscribe(roomName, new RoomListener() {
// implement the default RoomListener methods here
}, new SubscribeOptions(50)); // ask for 50 messages from the history
room.listenToHistoryEvents(new HistoryRoomListener() {
@Override
public void onHistoryMessage(Room room, Message message) {
System.out.println('Received a message from the past ' + message.getData().asText());
}
});
// inside a room listener
@Override
public void onMessage(Room room, Message message) {
if (message.getClientID() == scaledrone.getClientID()) {
// message is sent by session user
}
}
The currect version of the Java library doesn't reconnect automatically after a possible disconnect. This feature will be added in the future.
To handle reconnection you can listen to the onFailure
event.
@Override
public void onFailure(Exception ex) {
tryReconnecting(0);
}
private void tryReconnecting(final int reconnectAttempt) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
final Scaledrone drone = new Scaledrone("channel-id");
drone.connect(new Listener() {
@Override
public void onFailure(Exception ex) {
tryReconnecting(reconnectAttempt + 1);
}
});
// set everything up again..
}
}, reconnectAttempt * 1000);
}
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
This likely means that your Java doesn't support Let's Encrypt Certificates. Upgrade Java7 to 7u111 or newer or Java 8 to 8u101 or newer. Read more..
- Update the version 1.2.3 in
build.gradle
- Run
./gradlew java:assembleRelease
to generate the new release files - Go to https://bintray.com/scaledrone/scaledrone/scaledrone-java and create a new version
- Click "Upload Files"
- Type in
com/scaledrone/scaledrone-java/1.2.3
into "Target Repository Path" ensuring the correct version is included. - Upload all the files from
java/build/release/1.2.3/com/scaledrone/scaledrone-java/1.2.3
- You will see a notice "You have 8 unpublished item(s) for this version", click "Publish". It might take a few minutes
- Update the README with the correct version
0.7.0
- Fixed parsing 'id' field from JSON message.0.6.0
- Added message history features. Created aMessage
class that wraps the sent data, member as well as new properties such as message ID, timestamp and clientID.0.5.0
- Add upclose()
method.0.4.0
- Hook uponFailure
listener. This can be used for reconnecting.0.3.0
- Addmember
parameter toonMessage
listener method.