Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# pusher-websocket-java changelog

### Version 2.4.0 - 15th July 2022
* Add support for Subscription count events

### Version 2.3.0 - 4th July 2022
* Added support for user sign in and server to user messages
* Fixed issue with calling disconnect while the client is attempting reconnection
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The pusher-java-client is available in Maven Central.
<dependency>
<groupId>com.pusher</groupId>
<artifactId>pusher-java-client</artifactId>
<version>2.3.0-beta</version>
<version>2.4.0</version>
</dependency>
</dependencies>
```
Expand All @@ -83,7 +83,7 @@ The pusher-java-client is available in Maven Central.

```groovy
dependencies {
compile 'com.pusher:pusher-java-client:2.3.0-beta'
compile 'com.pusher:pusher-java-client:2.3.1'
}
```

Expand Down Expand Up @@ -256,6 +256,19 @@ Channel channel = pusher.subscribe("my-channel", new ChannelEventListener() {

// Other ChannelEventListener methods
});
```
If you wish to be informed for subscription count events, pass an implementation of the `ChannelEventListener` interface:

```java
Channel channel = pusher.subscribe("my-channel", new ChannelEventListener() {
@Override
public void onSubscriptionCountChanged(String channelName, int count) {
System.out.println("Members in channel: " + channelName + " are: " + count);
}

// Other ChannelEventListener methods
});

```

### Private channels
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def getProperty = { property ->
}

group = "com.pusher"
version = "2.3.0-beta"
version = "2.4.0"
sourceCompatibility = "1.8"
targetCompatibility = "1.8"

Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/pusher/client/channel/ChannelEventListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,19 @@ public interface ChannelEventListener extends SubscriptionEventListener {
* The name of the channel that was successfully subscribed.
*/
void onSubscriptionSucceeded(String channelName);

/**
* <p>
* Callback fired when a subscription success count
* of a channel changes
* </p>
*
*
* @param channelName
* The name of the channel for which the count changed.
*
* @param count
* The latest count of subscribers on the channel.
*/
void onSubscriptionCountChanged(String channelName, int count);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't bring myself to let it go like this. This makes it harder for anyone who wants to upgrade, even if they don't want to use the feature.

I know the way it's currently designed is annoying to work with. But let's create a new interface that extends this.
e.g. ChannelWithSubscriptionCountEventListener

You probably have to add two more interfaces that extend that for private channels too. PrivateChannelWithSubscriptionCountEventListener, PrivateEncryptedChannelWithSubscriptionCountEventListener

It's pretty ugly but at least it doesn't force everyone to change their implementation.

Sorry for the late feedback.

We will need to rethink and redesign how these event listeners are added in the next major release.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SDK is not designed for this to happen elegantly and will complicate the integration process a lot for subscription count.
If not breaking the older implementations is a non-negotiable then I would suggest removing this event listener entirely and renaming the event to pusher:subscription_count so it can be handled with the .bind() function like in JS SDK
What do you think ?

}
25 changes: 24 additions & 1 deletion src/main/java/com/pusher/client/channel/impl/BaseChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

Expand All @@ -11,19 +10,22 @@
import com.google.gson.GsonBuilder;
import com.pusher.client.channel.*;
import com.pusher.client.channel.impl.message.SubscribeMessage;
import com.pusher.client.channel.impl.message.SubscriptionCountData;
import com.pusher.client.channel.impl.message.UnsubscribeMessage;
import com.pusher.client.util.Factory;

public abstract class BaseChannel implements InternalChannel {
protected final Gson GSON;
private static final String INTERNAL_EVENT_PREFIX = "pusher_internal:";
protected static final String SUBSCRIPTION_SUCCESS_EVENT = "pusher_internal:subscription_succeeded";
protected static final String SUBSCRIPTION_COUNT_EVENT = "pusher_internal:subscription_count";
private Set<SubscriptionEventListener> globalListeners = new HashSet<SubscriptionEventListener>();
private final Map<String, Set<SubscriptionEventListener>> eventNameToListenerMap = new HashMap<String, Set<SubscriptionEventListener>>();
protected volatile ChannelState state = ChannelState.INITIAL;
private ChannelEventListener eventListener;
private final Factory factory;
private final Object lock = new Object();
private Integer subscriptionCount;

public BaseChannel(final Factory factory) {
GsonBuilder gsonBuilder = new GsonBuilder();
Expand All @@ -37,6 +39,11 @@ public BaseChannel(final Factory factory) {
@Override
abstract public String getName();

@Override
public Integer getCount() {
return subscriptionCount;
}

@Override
public void bind(final String eventName, final SubscriptionEventListener listener) {
validateArguments(eventName, listener);
Expand Down Expand Up @@ -112,6 +119,8 @@ public PusherEvent prepareEvent(String event, String message) {
public void onMessage(String event, String message) {
if (event.equals(SUBSCRIPTION_SUCCESS_EVENT)) {
updateState(ChannelState.SUBSCRIBED);
}else if (event.equals(SUBSCRIPTION_COUNT_EVENT)) {
handleSubscriptionCountEvent(message);
} else {
final Set<SubscriptionEventListener> listeners = getInterestedListeners(event);
if (listeners != null) {
Expand Down Expand Up @@ -184,6 +193,20 @@ private void validateArguments(final String eventName, final SubscriptionEventLi
}
}

private void handleSubscriptionCountEvent(final String message) {
String channelName = getName();
final SubscriptionCountData subscriptionCountMessage = GSON.fromJson(message, SubscriptionCountData.class);
subscriptionCount = subscriptionCountMessage.getCount();
if (eventListener != null ) {
factory.queueOnEventThread(new Runnable() {
@Override
public void run() {
eventListener.onSubscriptionCountChanged(channelName, subscriptionCountMessage.getCount());
}
});
}
}

protected Set<SubscriptionEventListener> getInterestedListeners(String event) {
synchronized (lock) {
Set<SubscriptionEventListener> listeners = new HashSet<SubscriptionEventListener>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public interface InternalChannel extends Channel, Comparable<InternalChannel> {

String toUnsubscribeMessage();

Integer getCount();

PusherEvent prepareEvent(String event, String message);

void onMessage(String event, String message);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.pusher.client.channel.impl.message;

import com.google.gson.annotations.SerializedName;

public class SubscriptionCountData {
@SerializedName("subscription_count")
public Integer count;

public int getCount(){
return count;
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/pusher/client/example/ExampleApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ public void onEvent(PusherEvent event) {
System.out.println(String.format(
"Received event [%s]", event.toString()));
}

@Override
public void onSubscriptionCountChanged(String channelName, int count) {
System.out.println(String.format(
"Count for channel [%s], changed to [%d]", channelName, count));
}
};

// subscribe to the channel and with the event listener for the event name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ public void userUnsubscribed(String channelName, User user) {
System.out.println(String.format("A user has left channel [%s]: %s", channelName, user));
printCurrentlySubscribedUsers();
}

@Override
public void onSubscriptionCountChanged(String channelName, int count) {
System.out.println(String.format(
"Count for channel [%s], changed to [%d]", channelName, count));
}
};

// subscribe to the channel and with the event listener for the event name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ public void onAuthenticationFailure(String message, Exception e) {
System.out.println(String.format(
"Authorization failure due to [%s], exception was [%s]", message, e));
}

@Override
public void onSubscriptionCountChanged(String channelName, int count) {
System.out.println(String.format(
"Count for channel [%s], changed to [%d]", channelName, count));
}
};

// subscribe to the channel and with the event listener for the event name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ public void onDecryptionFailure(String event, String reason) {
System.out.println(String.format(
"An error was received decrypting message for event:[%s] - reason: [%s]", event, reason));
}

@Override
public void onSubscriptionCountChanged(String channelName, int count) {
System.out.println(String.format(
"Count for channel [%s], changed to [%d]", channelName, count));
}
};

// subscribe to the channel and with the event listener for the event name
Expand Down