All Projects → centrifugal → centrifuge-java

centrifugal / centrifuge-java

Licence: MIT License
General Java and Android Websocket client for Centrifugo server and Centrifuge library

Programming Languages

java
68154 projects - #9 most used programming language

centrifuge-java

This is a Websocket client for Centrifugo and Centrifuge library. Client uses Protobuf protocol for client-server communication. centrifuge-java runs all operations in its own threads and provides necessary callbacks so you don't need to worry about managing concurrency yourself.

Status of library

This library is feature rich and supports almost all available Centrifuge/Centrifugo features (see matrix below). But it's very young and not tested in production application yet. Any help and feedback is very appreciated to make it production ready and update library status. Any report will give us an understanding that the library works, is useful and we should continue developing it. Please share your stories.

Installation

Library available in Maven: https://search.maven.org/artifact/io.github.centrifugal/centrifuge-java

Javadoc online

http://www.javadoc.io/doc/io.github.centrifugal/centrifuge-java

Before you start

Centrifuge-java library uses Protobuf library (Lite version) for client protocol. This fact and the fact that Protobuf Lite uses reflection internally can cause connection errors when releasing your application with Android shrinking and obfuscation features enabled. See protocolbuffers/protobuf#6463 for details. To deal with this add the following Proguard rule into proguard-rules.pro file in your project:

-keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite {
  <fields>;
}

More information about Android shrinking.

Basic usage

Connect to server based on Centrifuge library:

EventListener listener = new EventListener() {
    @Override
    public void onConnect(Client client, ConnectEvent event) {
        System.out.println("connected");
    }

    @Override
    public void onDisconnect(Client client, DisconnectEvent event) {
        System.out.printf("disconnected %s, reconnect %s%n", event.getReason(), event.getReconnect());
    }
};

Client client = new Client(
        "ws://localhost:8000/connection/websocket?format=protobuf",
        new Options(),
        listener
);
client.connect();

Note that you must use ?format=protobuf in connection URL as this client communicates with Centrifugo/Centrifuge over Protobuf protocol. While this client uses binary Protobuf protocol nothing stops you from sending JSON-encoded data over it.

Also in case of running in Android emulator don't forget to use proper connection address to Centrifuge/Centrifugo (as localhost is pointing to emulator vm and obviously your server instance is not available there).

To connect to Centrifugo you need to additionally set connection JWT:

...
Client client = new Client(
        "ws://localhost:8000/connection/websocket?format=protobuf",
        new Options(),
        listener
);
client.setToken("YOUR CONNECTION JWT")
client.connect()

Now let's look at how to subscribe to channel and listen to messages published into it:

EventListener listener = new EventListener() {
    @Override
    public void onConnect(Client client, ConnectEvent event) {
        System.out.println("connected");
    }

    @Override
    public void onDisconnect(Client client, DisconnectEvent event) {
        System.out.printf("disconnected %s, reconnect %s%n", event.getReason(), event.getReconnect());
    }
};

SubscriptionEventListener subListener = new SubscriptionEventListener() {
    @Override
    public void onSubscribeSuccess(Subscription sub, SubscribeSuccessEvent event) {
        System.out.println("subscribed to " + sub.getChannel());
    }
    @Override
    public void onSubscribeError(Subscription sub, SubscribeErrorEvent event) {
        System.out.println("subscribe error " + sub.getChannel() + " " + event.getMessage());
    }
    @Override
    public void onPublish(Subscription sub, PublishEvent event) {
        String data = new String(event.getData(), UTF_8);
        System.out.println("message from " + sub.getChannel() + " " + data);
    }
}

Client client = new Client(
        "ws://localhost:8000/connection/websocket?format=protobuf",
        new Options(),
        listener
);
// If using Centrifugo.
client.setToken("YOUR CONNECTION JWT")
client.connect()

Subscription sub;
try {
    sub = client.newSubscription("chat:index", subListener);
} catch (DuplicateSubscriptionException e) {
    e.printStackTrace();
    return;
}
sub.subscribe();

See more example code in console Java example or in demo Android app

To use with Android don't forget to set INTERNET permission to AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Usage in background

When a mobile application goes to the background there are OS-specific limitations for established persistent connections - which can be silently closed shortly. Thus in most cases you need to disconnect from a server when app moves to the background and connect again when app goes to the foreground.

CI status

Build Status

Feature matrix

  • connect to server using JSON protocol format
  • connect to server using Protobuf protocol format
  • connect with JWT
  • connect with custom header
  • automatic reconnect in case of errors, network problems etc
  • exponential backoff for reconnect
  • connect and disconnect events
  • handle disconnect reason
  • subscribe on channel and handle asynchronous Publications
  • handle Join and Leave messages
  • handle Unsubscribe notifications
  • reconnect on subscribe timeout
  • publish method of Subscription
  • unsubscribe method of Subscription
  • presence method of Subscription
  • presence stats method of Subscription
  • history method of Subscription
  • top-level publish method
  • top-level presence method
  • top-level presence stats method
  • top-level history method
  • top-level unsubscribe method
  • send asynchronous messages to server
  • handle asynchronous messages from server
  • send RPC commands
  • subscribe to private channels with token (JWT)
  • connection JWT refresh
  • private channel subscription token (JWT) refresh
  • handle connection expired error
  • handle subscription expired error
  • ping/pong to find broken connection
  • server-side subscriptions
  • message recovery mechanism for client-side subscriptions (works with Centrifugo >= 2.5.0 with v3_use_offset option set to true)
  • message recovery mechanism for server-side subscriptions
  • history stream pagination

License

Library is available under the MIT license. See LICENSE for details.

For Contributors

This section contains an information for library contributors. You don't need generating protobuf code if you just want to use centrifuge-java in your project.

Generate proto

Make sure options set in client.proto:

option java_package = "io.github.centrifugal.centrifuge.internal.protocol";
option java_outer_classname = "Protocol";

Then:

protoc --java_out=lite:./ client.proto
mv io/github/centrifugal/centrifuge/internal/protocol/Protocol.java centrifuge/src/main/java/io/github/centrifugal/centrifuge/internal/protocol/Protocol.java
rm -r io/

For maintainer

release

Create configuration file gradle.properties in GRADLE_USER_HOME:

signing.keyId=<LAST_8_SYMBOLS_OF_KEY_ID>
signing.password=<PASSWORD>
signing.secretKeyRingFile=/Path/to/.gnupg/secring.gpg

ossrhUsername=<USERNAME>
ossrhPassword=<PASSWORD>

Bump version in centrifuge/build.gradle. Write changelog. Create new library tag. Then run:

./gradlew publish

Then follow instructions:

https://central.sonatype.org/pages/releasing-the-deployment.html

I.e.

  1. Login here: https://oss.sonatype.org/
  2. Go to Staging repositories
  3. Find release, push Close button, wait
  4. Push Release button

Special thanks

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].