<style>
/* Changing the layout to use less space for mobiles */
@media screen and (max-device-width: 480px), screen and (-webkit-min-device-pixel-ratio: 2) {
    #email-body { min-width: 30em !important; }
    #email-page { padding: 8px !important; }
    #email-banner { padding: 8px 8px 0 8px !important; }
    #email-avatar { margin: 1px 8px 8px 0 !important; padding: 0 !important; }
    #email-fields { padding: 0 8px 8px 8px !important; }
    #email-gutter { width: 0 !important; }
}
</style>
<div id="email-body">
<table id="email-wrap" align="center" border="0" cellpadding="0" cellspacing="0" style="background-color:#f0f0f0;color:#000000;width:100%;">
    <tr valign="top">
        <td id="email-page" style="padding:16px !important;">
            <table align="center" border="0" cellpadding="0" cellspacing="0" style="background-color:#ffffff;border:1px solid #bbbbbb;color:#000000;width:100%;">
                <tr valign="top">
                    <td bgcolor="#3b4d64" style="background-color:#3b4d64;color:#ffffff;font-family:Arial,FreeSans,Helvetica,sans-serif;font-size:12px;line-height:1;"><img src="https://issues.jboss.org/s/en_USbeh5ai-1988229788/6109/58/_/jira-logo-scaled.png" alt="" style="vertical-align:top;" /></td>
                </tr><tr valign="top">
    <td id="email-banner" style="padding:32px 32px 0 32px;">

                
                    <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%" style="width:100%;">
    <tr valign="top">
        <td style="color:#505050;font-family:Arial,FreeSans,Helvetica,sans-serif;padding:0;">
                                        <img id="email-avatar" src="https://community.jboss.org/people/mwessendorf/avatar/16.png" alt="" height="48" width="48" border="0" align="left" style="padding:0;margin: 0 16px 16px 0;" />
                        <div id="email-action" style="padding: 0 0 8px 0;font-size:12px;line-height:18px;">
                                    <a class="user-hover" rel="mwessendorf" id="email_mwessendorf" href="https://issues.jboss.org/secure/ViewProfile.jspa?name=mwessendorf" style="color:#3b73af;">Matthias Wessendorf</a>
     commented on <img src="https://issues.jboss.org/images/icons/issuetypes/newfeature.png" height="16" width="16" border="0" align="absmiddle" alt="Feature Request"> <a style='color:#3b73af;text-decoration:none;' href='https://issues.jboss.org/browse/AGPUSH-36'>AGPUSH-36</a>
            </div>
                        <div id="email-summary" style="font-size:16px;line-height:20px;padding:2px 0 16px 0;">
                <a style='color:#3b73af;text-decoration:none;' href='https://issues.jboss.org/browse/AGPUSH-36'><strong>Push: GCM: Persistent Connections</strong></a>
            </div>
                    </td>
    </tr>
</table>
    </td>
</tr>
<tr valign="top">
    <td id="email-fields" style="padding:0 32px 32px 32px;">
        <table border="0" cellpadding="0" cellspacing="0" style="padding:0;text-align:left;width:100%;" width="100%">
            <tr valign="top">
                <td id="email-gutter" style="width:64px;white-space:nowrap;"></td>
                <td>
                    <table border="0" cellpadding="0" cellspacing="0" width="100%">
                        <tr valign="top">
    <td colspan="2" style="color:#000000;font-family:Arial,FreeSans,Helvetica,sans-serif;font-size:12px;padding:0 0 16px 0;width:100%;">
        <div class="comment-block" style="background-color:#edf5ff;border:1px solid #dddddd;color:#000000;padding:12px;"><p>The persistent connection is called <em>GCM Cloud Connection Server  (CCS)</em> . CCS itself is XMPP based</p>

<p>Google added an example on how to use CCS:<br/>
<a href="https://developer.android.com/google/gcm/ccs.html#implement" class="external-link" rel="nofollow">https://developer.android.com/google/gcm/ccs.html#implement</a></p>

<p>The example uses Jive's Smack (an Open Source XMPP (Jabber) library):</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">import</span> org.jivesoftware.smack.ConnectionConfiguration;
<span class="code-keyword">import</span> org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
<span class="code-keyword">import</span> org.jivesoftware.smack.ConnectionListener;
<span class="code-keyword">import</span> org.jivesoftware.smack.PacketInterceptor;
<span class="code-keyword">import</span> org.jivesoftware.smack.PacketListener;
<span class="code-keyword">import</span> org.jivesoftware.smack.XMPPConnection;
<span class="code-keyword">import</span> org.jivesoftware.smack.XMPPException;
<span class="code-keyword">import</span> org.jivesoftware.smack.filter.PacketTypeFilter;
<span class="code-keyword">import</span> org.jivesoftware.smack.packet.DefaultPacketExtension;
<span class="code-keyword">import</span> org.jivesoftware.smack.packet.Message;
<span class="code-keyword">import</span> org.jivesoftware.smack.packet.Packet;
<span class="code-keyword">import</span> org.jivesoftware.smack.packet.PacketExtension;
<span class="code-keyword">import</span> org.jivesoftware.smack.provider.PacketExtensionProvider;
<span class="code-keyword">import</span> org.jivesoftware.smack.provider.ProviderManager;
<span class="code-keyword">import</span> org.jivesoftware.smack.util.StringUtils;
<span class="code-keyword">import</span> org.json.simple.JSONValue;
<span class="code-keyword">import</span> org.json.simple.parser.ParseException;
<span class="code-keyword">import</span> org.xmlpull.v1.XmlPullParser;

<span class="code-keyword">import</span> java.util.HashMap;
<span class="code-keyword">import</span> java.util.Map;
<span class="code-keyword">import</span> java.util.Random;
<span class="code-keyword">import</span> java.util.logging.Level;
<span class="code-keyword">import</span> java.util.logging.Logger;

<span class="code-keyword">import</span> javax.net.ssl.SSLSocketFactory;
/**
 * Sample Smack implementation of a client <span class="code-keyword">for</span> GCM Cloud Connection Server.
 *
 * &lt;p&gt;For illustration purposes only.
 */
<span class="code-keyword">public</span> class SmackCcsClient {

  Logger logger = Logger.getLogger(<span class="code-quote">"SmackCcsClient"</span>);

  <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> GCM_SERVER = <span class="code-quote">"gcm.googleapis.com"</span>;
  <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">int</span> GCM_PORT = 5235;

  <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> GCM_ELEMENT_NAME = <span class="code-quote">"gcm"</span>;
  <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-keyword">final</span> <span class="code-object">String</span> GCM_NAMESPACE = <span class="code-quote">"google:mobile:data"</span>;

  <span class="code-keyword">static</span> Random random = <span class="code-keyword">new</span> Random();
  XMPPConnection connection;
  ConnectionConfiguration config;

  /**
   * XMPP Packet Extension <span class="code-keyword">for</span> GCM Cloud Connection Server.
   */
  class GcmPacketExtension <span class="code-keyword">extends</span> DefaultPacketExtension {
    <span class="code-object">String</span> json;

    <span class="code-keyword">public</span> GcmPacketExtension(<span class="code-object">String</span> json) {
      <span class="code-keyword">super</span>(GCM_ELEMENT_NAME, GCM_NAMESPACE);
      <span class="code-keyword">this</span>.json = json;
    }

    <span class="code-keyword">public</span> <span class="code-object">String</span> getJson() {
      <span class="code-keyword">return</span> json;
    }

    @Override
    <span class="code-keyword">public</span> <span class="code-object">String</span> toXML() {
      <span class="code-keyword">return</span> <span class="code-object">String</span>.format(<span class="code-quote">"&lt;%s xmlns=\"</span>%s\<span class="code-quote">"&gt;%s&lt;/%s&gt;"</span>, GCM_ELEMENT_NAME,
          GCM_NAMESPACE, json, GCM_ELEMENT_NAME);
    }

    @SuppressWarnings(<span class="code-quote">"unused"</span>)
    <span class="code-keyword">public</span> Packet toPacket() {
      <span class="code-keyword">return</span> <span class="code-keyword">new</span> Message() {
        <span class="code-comment">// Must override toXML() because it includes a &lt;body&gt;
</span>        @Override
        <span class="code-keyword">public</span> <span class="code-object">String</span> toXML() {

          StringBuilder buf = <span class="code-keyword">new</span> StringBuilder();
          buf.append(<span class="code-quote">"&lt;message"</span>);
          <span class="code-keyword">if</span> (getXmlns() != <span class="code-keyword">null</span>) {
            buf.append(<span class="code-quote">" xmlns=\"</span><span class="code-quote">").append(getXmlns()).append("</span>\"");
          }
          <span class="code-keyword">if</span> (getLanguage() != <span class="code-keyword">null</span>) {
            buf.append(<span class="code-quote">" xml:lang=\"</span><span class="code-quote">").append(getLanguage()).append("</span>\"");
          }
          <span class="code-keyword">if</span> (getPacketID() != <span class="code-keyword">null</span>) {
            buf.append(<span class="code-quote">" id=\"</span><span class="code-quote">").append(getPacketID()).append("</span>\"");
          }
          <span class="code-keyword">if</span> (getTo() != <span class="code-keyword">null</span>) {
            buf.append(<span class="code-quote">" to=\"</span><span class="code-quote">").append(StringUtils.escapeForXML(getTo())).append("</span>\"");
          }
          <span class="code-keyword">if</span> (getFrom() != <span class="code-keyword">null</span>) {
            buf.append(<span class="code-quote">" from=\"</span><span class="code-quote">").append(StringUtils.escapeForXML(getFrom())).append("</span>\"");
          }
          buf.append(<span class="code-quote">"&gt;"</span>);
          buf.append(GcmPacketExtension.<span class="code-keyword">this</span>.toXML());
          buf.append(<span class="code-quote">"&lt;/message&gt;"</span>);
          <span class="code-keyword">return</span> buf.toString();
        }
      };
    }
  }

  <span class="code-keyword">public</span> SmackCcsClient() {
    <span class="code-comment">// Add GcmPacketExtension
</span>    ProviderManager.getInstance().addExtensionProvider(GCM_ELEMENT_NAME,
        GCM_NAMESPACE, <span class="code-keyword">new</span> PacketExtensionProvider() {

      @Override
      <span class="code-keyword">public</span> PacketExtension parseExtension(XmlPullParser parser)
          <span class="code-keyword">throws</span> Exception {
        <span class="code-object">String</span> json = parser.nextText();
        GcmPacketExtension packet = <span class="code-keyword">new</span> GcmPacketExtension(json);
        <span class="code-keyword">return</span> packet;
      }
    });
  }

  /**
   * Returns a random message id to uniquely identify a message.
   *
   * &lt;p&gt;Note:
   * This is generated by a pseudo random number generator <span class="code-keyword">for</span> illustration purpose,
   * and is not guaranteed to be unique.
   *
   */
  <span class="code-keyword">public</span> <span class="code-object">String</span> getRandomMessageId() {
    <span class="code-keyword">return</span> <span class="code-quote">"m-"</span> + <span class="code-object">Long</span>.toString(random.nextLong());
  }

  /**
   * Sends a downstream GCM message.
   */
  <span class="code-keyword">public</span> void send(<span class="code-object">String</span> jsonRequest) {
    Packet request = <span class="code-keyword">new</span> GcmPacketExtension(jsonRequest).toPacket();
    connection.sendPacket(request);
  }

  /**
   * Handles an upstream data message from a device application.
   *
   * &lt;p&gt;This sample echo server sends an echo message back to the device.
   * Subclasses should override <span class="code-keyword">this</span> method to process an upstream message.
   */
  <span class="code-keyword">public</span> void handleIncomingDataMessage(Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt; jsonObject) {
    <span class="code-object">String</span> from = jsonObject.get(<span class="code-quote">"from"</span>).toString();

    <span class="code-comment">// PackageName of the application that sent <span class="code-keyword">this</span> message.
</span>    <span class="code-object">String</span> category = jsonObject.get(<span class="code-quote">"category"</span>).toString();

    <span class="code-comment">// Use the packageName as the collapseKey in the echo packet
</span>    <span class="code-object">String</span> collapseKey = <span class="code-quote">"echo:CollapseKey"</span>;
    @SuppressWarnings(<span class="code-quote">"unchecked"</span>)
    Map&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt; payload = (Map&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt;) jsonObject.get(<span class="code-quote">"data"</span>);
    payload.put(<span class="code-quote">"ECHO"</span>, <span class="code-quote">"Application: "</span> + category);

    <span class="code-comment">// Send an ECHO response back
</span>    <span class="code-object">String</span> echo = createJsonMessage(from, getRandomMessageId(), payload, collapseKey, <span class="code-keyword">null</span>, <span class="code-keyword">false</span>);
    send(echo);
  }

  /**
   * Handles an ACK.
   *
   * &lt;p&gt;By <span class="code-keyword">default</span>, it only logs a INFO message, but subclasses could override it to
   * properly handle ACKS.
   */
  <span class="code-keyword">public</span> void handleAckReceipt(Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt; jsonObject) {
    <span class="code-object">String</span> messageId = jsonObject.get(<span class="code-quote">"message_id"</span>).toString();
    <span class="code-object">String</span> from = jsonObject.get(<span class="code-quote">"from"</span>).toString();
    logger.log(Level.INFO, <span class="code-quote">"handleAckReceipt() from: "</span> + from + <span class="code-quote">", messageId: "</span> + messageId);
  }

  /**
   * Handles a NACK.
   *
   * &lt;p&gt;By <span class="code-keyword">default</span>, it only logs a INFO message, but subclasses could override it to
   * properly handle NACKS.
   */
  <span class="code-keyword">public</span> void handleNackReceipt(Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt; jsonObject) {
    <span class="code-object">String</span> messageId = jsonObject.get(<span class="code-quote">"message_id"</span>).toString();
    <span class="code-object">String</span> from = jsonObject.get(<span class="code-quote">"from"</span>).toString();
    logger.log(Level.INFO, <span class="code-quote">"handleNackReceipt() from: "</span> + from + <span class="code-quote">", messageId: "</span> + messageId);
  }

  /**
   * Creates a JSON encoded GCM message.
   *
   * @param to RegistrationId of the target device (Required).
   * @param messageId Unique messageId <span class="code-keyword">for</span> which CCS will send an <span class="code-quote">"ack/nack"</span> (Required).
   * @param payload Message content intended <span class="code-keyword">for</span> the application. (Optional).
   * @param collapseKey GCM collapse_key parameter (Optional).
   * @param timeToLive GCM time_to_live parameter (Optional).
   * @param delayWhileIdle GCM delay_while_idle parameter (Optional).
   * @<span class="code-keyword">return</span> JSON encoded GCM message.
   */
  <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-object">String</span> createJsonMessage(<span class="code-object">String</span> to, <span class="code-object">String</span> messageId, Map&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt; payload,
      <span class="code-object">String</span> collapseKey, <span class="code-object">Long</span> timeToLive, <span class="code-object">Boolean</span> delayWhileIdle) {
    Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt; message = <span class="code-keyword">new</span> HashMap&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt;();
    message.put(<span class="code-quote">"to"</span>, to);
    <span class="code-keyword">if</span> (collapseKey != <span class="code-keyword">null</span>) {
      message.put(<span class="code-quote">"collapse_key"</span>, collapseKey);
    }
    <span class="code-keyword">if</span> (timeToLive != <span class="code-keyword">null</span>) {
      message.put(<span class="code-quote">"time_to_live"</span>, timeToLive);
    }
    <span class="code-keyword">if</span> (delayWhileIdle != <span class="code-keyword">null</span> &amp;&amp; delayWhileIdle) {
      message.put(<span class="code-quote">"delay_while_idle"</span>, <span class="code-keyword">true</span>);
    }
    message.put(<span class="code-quote">"message_id"</span>, messageId);
    message.put(<span class="code-quote">"data"</span>, payload);
    <span class="code-keyword">return</span> JSONValue.toJSONString(message);
  }

  /**
   * Creates a JSON encoded ACK message <span class="code-keyword">for</span> an upstream message received from an application.
   *
   * @param to RegistrationId of the device who sent the upstream message.
   * @param messageId messageId of the upstream message to be acknowledged to CCS.
   * @<span class="code-keyword">return</span> JSON encoded ack.
   */
  <span class="code-keyword">public</span> <span class="code-keyword">static</span> <span class="code-object">String</span> createJsonAck(<span class="code-object">String</span> to, <span class="code-object">String</span> messageId) {
    Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt; message = <span class="code-keyword">new</span> HashMap&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt;();
    message.put(<span class="code-quote">"message_type"</span>, <span class="code-quote">"ack"</span>);
    message.put(<span class="code-quote">"to"</span>, to);
    message.put(<span class="code-quote">"message_id"</span>, messageId);
    <span class="code-keyword">return</span> JSONValue.toJSONString(message);
  }

  /**
   * Connects to GCM Cloud Connection Server using the supplied credentials.
   *
   * @param username GCM_SENDER_ID@gcm.googleapis.com
   * @param password API Key
   * @<span class="code-keyword">throws</span> XMPPException
   */
  <span class="code-keyword">public</span> void connect(<span class="code-object">String</span> username, <span class="code-object">String</span> password) <span class="code-keyword">throws</span> XMPPException {
    config = <span class="code-keyword">new</span> ConnectionConfiguration(GCM_SERVER, GCM_PORT);
    config.setSecurityMode(SecurityMode.enabled);
    config.setReconnectionAllowed(<span class="code-keyword">true</span>);
    config.setRosterLoadedAtLogin(<span class="code-keyword">false</span>);
    config.setSendPresence(<span class="code-keyword">false</span>);
    config.setSocketFactory(SSLSocketFactory.getDefault());

    <span class="code-comment">// NOTE: Set to <span class="code-keyword">true</span> to launch a window with information about packets sent and received
</span>    config.setDebuggerEnabled(<span class="code-keyword">true</span>);

    <span class="code-comment">// -Dsmack.debugEnabled=<span class="code-keyword">true</span>
</span>    XMPPConnection.DEBUG_ENABLED = <span class="code-keyword">true</span>;

    connection = <span class="code-keyword">new</span> XMPPConnection(config);
    connection.connect();

    connection.addConnectionListener(<span class="code-keyword">new</span> ConnectionListener() {

      @Override
      <span class="code-keyword">public</span> void reconnectionSuccessful() {
        logger.info(<span class="code-quote">"Reconnecting.."</span>);
      }

      @Override
      <span class="code-keyword">public</span> void reconnectionFailed(Exception e) {
        logger.log(Level.INFO, <span class="code-quote">"Reconnection failed.. "</span>, e);
      }

      @Override
      <span class="code-keyword">public</span> void reconnectingIn(<span class="code-object">int</span> seconds) {
        logger.log(Level.INFO, <span class="code-quote">"Reconnecting in %d secs"</span>, seconds);
      }

      @Override
      <span class="code-keyword">public</span> void connectionClosedOnError(Exception e) {
        logger.log(Level.INFO, <span class="code-quote">"Connection closed on error."</span>);
      }

      @Override
      <span class="code-keyword">public</span> void connectionClosed() {
        logger.info(<span class="code-quote">"Connection closed."</span>);
      }
    });

    <span class="code-comment">// Handle incoming packets
</span>    connection.addPacketListener(<span class="code-keyword">new</span> PacketListener() {

      @Override
      <span class="code-keyword">public</span> void processPacket(Packet packet) {
        logger.log(Level.INFO, <span class="code-quote">"Received: "</span> + packet.toXML());
        Message incomingMessage = (Message) packet;
        GcmPacketExtension gcmPacket =
            (GcmPacketExtension) incomingMessage.getExtension(GCM_NAMESPACE);
        <span class="code-object">String</span> json = gcmPacket.getJson();
        <span class="code-keyword">try</span> {
          @SuppressWarnings(<span class="code-quote">"unchecked"</span>)
          Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt; jsonObject =
              (Map&lt;<span class="code-object">String</span>, <span class="code-object">Object</span>&gt;) JSONValue.parseWithException(json);

          <span class="code-comment">// present <span class="code-keyword">for</span> <span class="code-quote">"ack"</span>/<span class="code-quote">"nack"</span>, <span class="code-keyword">null</span> otherwise
</span>          <span class="code-object">Object</span> messageType = jsonObject.get(<span class="code-quote">"message_type"</span>);

          <span class="code-keyword">if</span> (messageType == <span class="code-keyword">null</span>) {
            <span class="code-comment">// Normal upstream data message
</span>            handleIncomingDataMessage(jsonObject);

            <span class="code-comment">// Send ACK to CCS
</span>            <span class="code-object">String</span> messageId = jsonObject.get(<span class="code-quote">"message_id"</span>).toString();
            <span class="code-object">String</span> from = jsonObject.get(<span class="code-quote">"from"</span>).toString();
            <span class="code-object">String</span> ack = createJsonAck(from, messageId);
            send(ack);
          } <span class="code-keyword">else</span> <span class="code-keyword">if</span> (<span class="code-quote">"ack"</span>.equals(messageType.toString())) {
            <span class="code-comment">// <span class="code-object">Process</span> Ack
</span>            handleAckReceipt(jsonObject);
          } <span class="code-keyword">else</span> <span class="code-keyword">if</span> (<span class="code-quote">"nack"</span>.equals(messageType.toString())) {
            <span class="code-comment">// <span class="code-object">Process</span> Nack
</span>            handleNackReceipt(jsonObject);
          } <span class="code-keyword">else</span> {
            logger.log(Level.WARNING, <span class="code-quote">"Unrecognized message type (%s)"</span>,
                messageType.toString());
          }
        } <span class="code-keyword">catch</span> (ParseException e) {
          logger.log(Level.SEVERE, <span class="code-quote">"Error parsing JSON "</span> + json, e);
        } <span class="code-keyword">catch</span> (Exception e) {
          logger.log(Level.SEVERE, <span class="code-quote">"Couldn't send echo."</span>, e);
        }
      }
    }, <span class="code-keyword">new</span> PacketTypeFilter(Message.class));


    <span class="code-comment">// Log all outgoing packets
</span>    connection.addPacketInterceptor(<span class="code-keyword">new</span> PacketInterceptor() {
      @Override
      <span class="code-keyword">public</span> void interceptPacket(Packet packet) {
        logger.log(Level.INFO, <span class="code-quote">"Sent: {0}"</span>,  packet.toXML());
      }
    }, <span class="code-keyword">new</span> PacketTypeFilter(Message.class));

    connection.login(username, password);
  }

  <span class="code-keyword">public</span> <span class="code-keyword">static</span> void main(<span class="code-object">String</span> [] args) {
    <span class="code-keyword">final</span> <span class="code-object">String</span> userName = <span class="code-quote">"Your GCM Sender Id"</span> + <span class="code-quote">"@gcm.googleapis.com"</span>;
    <span class="code-keyword">final</span> <span class="code-object">String</span> password = <span class="code-quote">"API Key"</span>;

    SmackCcsClient ccsClient = <span class="code-keyword">new</span> SmackCcsClient();

    <span class="code-keyword">try</span> {
      ccsClient.connect(userName, password);
    } <span class="code-keyword">catch</span> (XMPPException e) {
      e.printStackTrace();
    }

    <span class="code-comment">// Send a sample hello downstream message to a device.
</span>    <span class="code-object">String</span> toRegId = <span class="code-quote">"RegistrationIdOfTheTargetDevice"</span>;
    <span class="code-object">String</span> messageId = ccsClient.getRandomMessageId();
    Map&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt; payload = <span class="code-keyword">new</span> HashMap&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt;();
    payload.put(<span class="code-quote">"Hello"</span>, <span class="code-quote">"World"</span>);
    payload.put(<span class="code-quote">"CCS"</span>, <span class="code-quote">"Dummy Message"</span>);
    payload.put(<span class="code-quote">"EmbeddedMessageId"</span>, messageId);
    <span class="code-object">String</span> collapseKey = <span class="code-quote">"sample"</span>;
    <span class="code-object">Long</span> timeToLive = 10000L;
    <span class="code-object">Boolean</span> delayWhileIdle = <span class="code-keyword">true</span>;
    ccsClient.send(createJsonMessage(toRegId, messageId, payload, collapseKey,
        timeToLive, delayWhileIdle));
  }
}
</pre>
</div></div></div>
        <div style="color:#505050;padding:4px 0 0 0;">                </div>
    </td>
</tr>
                    </table>
                </td>
            </tr>
        </table>
    </td>
</tr>













            </table>
        </td><!-- End #email-page -->
    </tr>
    <tr valign="top">
        <td style="color:#505050;font-family:Arial,FreeSans,Helvetica,sans-serif;font-size:10px;line-height:14px;padding: 0 16px 16px 16px;text-align:center;">
            This message is automatically generated by JIRA.<br />
            If you think it was sent incorrectly, please contact your JIRA administrators<br />
            For more information on JIRA, see: <a style='color:#3b73af;' href='http://www.atlassian.com/software/jira'>http://www.atlassian.com/software/jira</a>
        </td>
    </tr>
</table><!-- End #email-wrap -->
</div><!-- End #email-body -->