protected void notifySubscribers(String topicKey,
                                     String userKey,
                                     List<SubscriberData> subscribers,
                                     boolean selfNotify,
                                     String jsonMessage) throws SubscriberNotificationException {
        Map<String, Exception> sendMessageErrorsBySubscriberName = new HashMap<String, Exception>();

        for (SubscriberData subscriber : subscribers) {
            if (selfNotify || !userKey.equals(subscriber.userKey)) {
                String subscribersClientId = getClientId(topicKey, subscriber.userKey);
                try {
                    getChannelService().sendMessage(new ChannelMessage(subscribersClientId, jsonMessage));
                } catch (Exception e) {
                    sendMessageErrorsBySubscriberName.put(subscriber.userName, e);
                }
            }
        }

        if (!sendMessageErrorsBySubscriberName.isEmpty()) {
            //then not all messages were sent successfully
            StringBuilder msg = new StringBuilder("Error notifying subscribers: ");
            for (Map.Entry<String, Exception> userNameAndException : sendMessageErrorsBySubscriberName.entrySet()) {
                msg.append("\n\t")
                        .append(userNameAndException.getKey()).append(": ")
                        .append(userNameAndException.getValue());
            }
            throw new SubscriberNotificationException(msg.toString());
        }
    }