/** Bean init method to perform one time setup of the Hazelcast cluster node. */
  public void init() {
    // validate bean setup
    if (this.hazelcastInstance == null) {
      throw new IllegalArgumentException(
          "The 'hazelcastInstance' property (HazelcastInstance) is mandatory.");
    }
    if (this.hazelcastTopicName == null || this.hazelcastTopicName.length() == 0) {
      throw new IllegalArgumentException(
          "The 'hazelcastTopicName' property (String) is mandatory.");
    }

    // cluster topic initialisation
    ITopic<String> topic = this.hazelcastInstance.getTopic(this.hazelcastTopicName);
    if (topic == null) {
      throw new IllegalArgumentException(
          "Did not find Hazelcast topic with name: '"
              + this.hazelcastTopicName
              + "' - cannot init.");
    }

    // find the beans that are interested in cluster messages and register them with the service
    Map<String, ClusterMessageAware> beans =
        this.applicationContext.getBeansOfType(ClusterMessageAware.class);
    this.clusterBeans = new HashMap<>();
    for (final String id : beans.keySet()) {
      final ClusterMessageAware bean = beans.get(id);
      final String messageType = bean.getClusterMessageType();
      // beans that do not specify a message type can still post messages via the service or just
      // keep a reference
      // but they are not registered in the list of handler beans that can accept cluster messages
      if (messageType != null) {
        if (this.clusterBeans.containsKey(messageType)) {
          throw new IllegalStateException(
              "ClusterMessageAware bean with id '"
                  + id
                  + "' attempted to register with existing Message Type: "
                  + messageType);
        }
        this.clusterBeans.put(messageType, bean);
      }
      bean.setClusterService(this);
    }
    if (logger.isDebugEnabled()) {
      logger.debug("Registered beans for cluster messages:");
      for (final String id : beans.keySet()) {
        logger.debug(id + " [" + beans.get(id).getClusterMessageType() + "]");
      }
    }

    // start listening for cluster messages
    this.clusterTopic = topic;
    this.clusterTopic.addMessageListener(this);

    logger.info("Init complete for Hazelcast cluster - listening on topic: " + hazelcastTopicName);
  }
  /**
   * Hazelcast MessageListener implementation - called when a message is received from a cluster
   * node
   *
   * @param message Cluster message JSON string
   */
  @Override
  public void onMessage(final Message<String> message) {
    final boolean debug = logger.isDebugEnabled();

    // process message objects and extract the payload
    final String msg = message.getMessageObject();
    final MessageProcessor proc = new MessageProcessor(msg);
    if (!proc.isSender()) {
      if (debug) logger.debug("Received message of type:" + proc.getMessageType() + "\r\n" + msg);

      // call an implementation of a message handler bean
      final ClusterMessageAware bean = this.clusterBeans.get(proc.getMessageType());
      if (bean != null) {
        bean.onClusterMessage(proc.getMessagePayload());
      } else {
        logger.warn(
            "Received message of unknown type - no handler bean found: " + proc.getMessageType());
      }
    }
  }