A server-side push initiator using Java

This sample shows you how to create a push request in the PAP push format or the BlackBerry push format. You can also look at the sample server-side push initiator to see how to send a push request to a client-side push-enabled app.

PAP push format

A PAP push request sends the pushed content to the BlackBerry MDS Connection Service as a multipart message which contains an XML control entity and the content to push. If the request is a cancellation or status-query request, only an XML control entity is sent. Delivery parameters are specified in the XML control entity.

Generate a random PushID for the push request. You must include the PushID when you build the push request.

String push id="_donepushID:13522321608214"+random.nextInt();

Construct the URL to which the push request is posted.

URL mdsUrl = new URL("http", mdsHost, MDS_PORT, "/pap");

Open a connection to the BlackBerry Enterprise Server. Invoke openConnection() on the URL to push content to, and then cast the returned object as an HttpURLConnection. An HttpURLConnection represents a connection to a remote object.

HttpURLConnection mdsConn = (HttpURLConnection)
  mdsUrl.openConnection();

Set the HTTP headers for the request. In a PAP push request, the HTTP headers specify content type of the push request (multipart/related), the application ID with which the client-side push-enabled app sends content to the port on which the client-side push-enabled app is waiting, and the HTTP request method.

String boundary = "";
boundary = "asdlfkjiurwghasf";
mdsConn.setRequestProperty("Content-Type", "multipart/related; 
  type=\"application/xml\"; boundary=" + boundary);
mdsConn.setRequestProperty("X-Wap-Application-Id", "/");
mdsConn.setRequestProperty("X-Rim-Push-Dest-Port","100");
mdsConn.setRequestMethod("POST");

Set doOutput(Boolean) to true to indicate that the app intends to send content to the URL connection.

mdsConn.setDoOutput(true);

To receive responses and result notifications from the BlackBerry MDS Connection Service, set doInput(Boolean) to true to indicate that the app reads incoming content from the URL connection.

mdsConn.setDoInput(true);

Construct the MIME multipart message. In this sample, the PAP control entity is constructed by reading a template multipart message and replacing the template content with real values.

String output = requestTemplate.replaceAll("\\$\\(pushid\\)", 
  pushId); 
output = output.replaceAll("\\$\\(boundary\\)", boundary); 
output = output.replaceAll("\\$\\(notifyURL\\)", "" + notifyURL); 
output = output.replaceAll("\\$\\(pin\\)", "" + _pinField.
  getText()); 

String deliveryMethod = "confirmed"; 

output = output.replaceAll("\\$\\(deliveryMethod\\)", 
  deliveryMethod); 
output = output.replaceAll("\\$\\(headers\\)", "Content-Type: 
  text/plain"); 
output = output.replaceAll("\\$\\(content\\)", data); 
output = output.replaceAll("\r\n", "EOL"); 
output = output.replaceAll("\n", "EOL"); 
output = output.replaceAll("EOL", "\r\n");

Write the push request content to the server connection. Invoke getOutputStream() to access an output stream, write to the output stream, and then close it.

System.out.println(output);
OutputStream outs = mdsConn.getOutputStream(); 
copyStreams(new ByteArrayInputStream(output.getBytes()), outs);

Read the BlackBerry MDS Connection Service response by invoking getInputStream() to access an input stream.

copyStreams(mdsConn.getInputStream(), response);
 
int httpCode = mdsConn.getResponseCode();
 
if (httpCode != HttpURLConnection.HTTP_ACCEPTED) 
{ 
    throw new Exception("MDS returned HTTP status: " + httpCode);
} 

BlackBerry push format

A BlackBerry push request sends the pushed content to the BlackBerry MDS Connection Service as a byte stream. Delivery parameters are specified in HTTP headers sent as part of the byte stream.

Generate a random PushID for the push request. You must include the PushID when you build the push request.

String push id="_donepushID:13522321607216"+random.nextInt();

Construct the URL to which the server-side push app sends the push request.

URL _pushURL = null;

_pushURL = new URL("http", "localhost", MDS_PORT, 
  "/push?DESTINATION="+ DevicePin +"&PORT="+DEVICE_PORT+
  "&REQUESTURI=localhost");

Open a connection to the BlackBerry Enterprise Server. Invoke openConnection() on the URL to push content to, and then cast the returned object as an HttpURLConnection object. An HttpURLConnection represents a connection to a remote object.

HttpURLConnection conn =(HttpURLConnection)url.openConnection();

Set the HTTP headers for the request. The HTTP headers specify the delivery parameters, such as reliability level or delivery time stamp, for the push request.

conn.setRequestMethod("POST");
conn.setRequestProperty("X-RIM-PUSH-ID", pushId);            
conn.setRequestProperty("X-RIM-Push-NotifyURL", 
  notifyURL);            
conn.setRequestProperty("X-RIM-Push-Reliability-Mode",
  "APPLICATION");

Set doOutput(Boolean) to true to indicate that the app intends to send content to the URL connection.

conn.setDoOutput(true);

To receive responses and result notifications from the BlackBerry MDS Connection Service, set doInput(Boolean) to true to indicate that the app reads incoming content from the URL connection.

conn.setDoInput(true);

Write the push request content to the server connection. Invoke getOutputStream() to access an output stream, write the content to the output stream, and then close the output stream.

OutputStream out = conn.getOutputStream(); 
out.write(data); 
out.close();

Read the BlackBerry MDS Connection Service response. Invoke getInputStream() to access an input stream. Determine the size of the response content and, if the content size is nonzero, open a content input stream, and then read in the content.

InputStream ins = conn.getInputStream(); 
int contentLength = conn.getContentLength(); 
if (contentLength > 0) 
{ 
    byte[] someArray = new byte [contentLength]; 
    DataInputStream dins = new DataInputStream(ins); 
    dins.readFully(someArray); 
    System.out.println(new String(someArray)); 
} 
ins.close();

Close the connection by invoking disconnect() to indicate that the app plans to make no further requests to the server.

conn.disconnect();

Server-side sample app

You can use the following code sample to submit push requests that are delivered to a client-side app that is listening on a port. A dialog box allows you to specify the BlackBerry MDS Connection Service information, and whether to use the BlackBerry push format or the PAP push format for the push request.

  • View the code sample

    package com.rim.samples.server.httppushdemo;
    
    import java.io.*;
    import javax.swing.*;
    import javax.swing.border.*;
    import java.net.*;
    import java.util.*;
    import java.awt.Color;
    
    /**
     * The HTTPPushDemo class provides a simple PUSH server sample.
     * This program sends text to a listening device. The associated 
     * client demo is HTTPPushDemo in the com.rim.samples.device package. Start up both 
     * the device simulator and MDS before executing this program. For reliable push, 
     * append the port that you are pushing to in rimpublic.property file 
     * (push.application.reliable.ports): push.application.reliable.ports=7874,100
     * The general form of the URL for posting (pushing) content to the device is:
     * http://<host>:<port>/push?DESTINATION=<device pin>&PORT=<device_port>&REQUESTURI=<post uri>;
     */
    public class HTTPPushDemo extends javax.swing.JFrame {
    
        //constants -----------------------------------------------------------------
        private static final String RESOURCE_PATH = "com/rim/samples/server/httppushdemo/resources";
        private static final String DEVICE_PIN = "2100000A";
        private static final String DEVICE_PORT = "100";
        private static final int MDS_PORT = 8080;
    
        private static final String IMAGE_TYPE = ".png";
        private String requestTemplate;
        private String notifyURL="http://localhost:7778";
        private Random random= new Random();
        private Thread notificationThread;
    
        //statics -------------------------------------------------------------------
        private static ResourceBundle _resources = java.util.ResourceBundle.getBundle(RESOURCE_PATH);
    
        //constructors --------------------------------------------------------------
        /** Creates a new HTTPPushDemo instance*/
        public HTTPPushDemo() {
    
            initComponents ();
            pack ();
    
            //sizing code for the main frame
            setSize(_panel.getWidth(), _panel.getHeight());
            setLocation(100,100);
            notificationThread= new NotificationThread();
        }
    
        private URL getPushURL(String DevicePin)
        {
            /**
             * The format of the URL is:
             * http://<host>:<port>/push?DESTINATION=<device pin>&PORT=<device_port>&REQUESTURI=<post uri>
             */
            URL _pushURL = null;
            try {
                if ((DevicePin == null) || (DevicePin.length() == 0))
                {
                    DevicePin = DEVICE_PIN;
                }
                _pushURL = new URL("http", "localhost", MDS_PORT, "/push?DESTINATION="+ DevicePin +"&PORT="+DEVICE_PORT+"&REQUESTURI=localhost");
                
            } catch (MalformedURLException e) {
                System.err.println(e.toString());
            }
            return _pushURL;
        }
    
        /** 
         * This method is called from within the constructor to
         * initialize the form.
         * WARNING: Do NOT modify this code. The content of this method is
         * always regenerated by the FormEditor.
         */
        private void initComponents() {//GEN-BEGIN:initComponents
            _panel = new javax.swing.JPanel();
            _textField = new javax.swing.JTextField();
            _textArea= new javax.swing.JTextArea();
            _pinField = new javax.swing.JTextField(DEVICE_PIN);
            _label = new javax.swing.JTextArea();
            _notification=new javax.swing.JTextArea();
            _rimButton= new javax.swing.JRadioButton("rim");
            _papButton= new javax.swing.JRadioButton("pap");
            _buttonGroup= new javax.swing.ButtonGroup();
            _buttonGroup.add(_rimButton);
            _buttonGroup.add(_papButton);
    
            _sendButton = new javax.swing.JButton();
            getContentPane().setLayout(null);
            setTitle(_resources.getString("HTTPPushDemo.title"));
            setResizable(false);
            addWindowListener(new java.awt.event.WindowAdapter() {
                public void windowClosing(java.awt.event.WindowEvent evt) {
                    exitForm(evt);
                }
            });
    
            _panel.setLayout(null);
            _panel.setPreferredSize(getSize());
    
            _textArea.setToolTipText(_resources.getString("HTTPPushDemo._textField.toolTipText"));
            _panel.add(_textArea);
            _textArea.setBounds(10, 50, 270, 100);
            _textArea.setBorder(new LineBorder(Color.BLACK));
    
    
            _pinField.setToolTipText(_resources.getString("HTTPPushDemo._pinField.toolTipText"));
            _panel.add(_pinField);
            _pinField.setBounds(10, 170, 150, 30);
    
            _panel.add(_rimButton);
            _panel.add(_papButton);
            _rimButton.setBounds(170, 170, 50, 30);
            _papButton.setBounds(240, 170, 50, 30);
    
            _label.setWrapStyleWord(true);
            _label.setLineWrap(true);
            _label.setEditable(false);
            _label.setText(_resources.getString("HTTPPushDemo._label.text"));
            _label.setBackground((java.awt.Color) javax.swing.UIManager.getDefaults ().get ("Button.background"));
            _panel.add(_label);
            _label.setBounds(10, 10, 270, 40);
    
            _sendButton.setLabel(_resources.getString("HTTPPushDemo._sendButton.label"));
            _sendButton.addMouseListener(new java.awt.event.MouseAdapter() {
                public void mouseClicked(java.awt.event.MouseEvent evt) {
                    sendButtonMouseClicked(evt);
                }
            });
    
            _panel.add(_sendButton);
            _sendButton.setLocation(10, 210);
            _sendButton.setSize(_sendButton.getPreferredSize());
    
            JScrollPane _scrollPane = new javax.swing.JScrollPane(_notification);
            _scrollPane.setVerticalScrollBarPolicy(
                            JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
    
            _panel.add(_scrollPane);
            _scrollPane.setBounds(10,250,270, 150);
    
    
            getContentPane().add(_panel);
            _panel.setBounds(0, 0, 300, 450);
    
        }//GEN-END:initComponents
    
        private void sendButtonMouseClicked(java.awt.event.MouseEvent evt) 
        {//GEN-FIRST:event_sendButtonMouseClicked
    
            String text =_textArea.getText();
    
            if(_rimButton.isSelected()) postData(text);
            else if(_papButton.isSelected()) papPush(text);
    
        }//GEN-LAST:event_sendButtonMouseClicked
    
       /**
        * Posts the specified content to the device
        * The URL is hardcoded for the purposes of this demo, and takes the form:
        * http://<host>:<port>/push?DESTINATION=<device pin>&PORT=<device_port>&REQUESTURI=<post uri>
        * param data the data to post
        *
        */
        private void postData(String data)
        {
    
            String push id="_donepushID:13522321629133"+random.nextInt();
    
            setupNotifyThread();
            
            try {
                URL url = getPushURL(_pinField.getText());
                System.out.println(_resources.getString("HTTPPushDemo.status.sendingToString") + url.toString());
    
                // Open the connection using the static member
                HttpURLConnection conn =(HttpURLConnection)url.openConnection();
                conn.setDoInput(true);//For receiving the confirmation
                conn.setDoOutput(true);//For sending the data
                conn.setRequestMethod("POST");
                conn.setRequestProperty("X-RIM-PUSH-ID", pushId);
                conn.setRequestProperty("X-RIM-Push-NotifyURL", notifyURL);
                conn.setRequestProperty("X-RIM-Push-Reliability-Mode","APPLICATION");
                // Write the data
                OutputStream out = conn.getOutputStream();
                out.write(data.getBytes());
                out.close();
                InputStream ins =conn.getInputStream();
                int contentLength =conn.getContentLength();
                System.out.println( _resources.getString("HTTPPushDemo.status.contentLengthDescription")+ contentLength);
                if (contentLength > 0)
                {
                    byte[] someArray = new byte [contentLength];
                    DataInputStream dins = new DataInputStream(ins);
                    dins.readFully(someArray);
                    System.out.println(new String(someArray));
                }
    
                conn.disconnect();
    
            } catch (IOException e) {
                System.err.println(e);
            }
        }
    
        private void readPapTemplate()
        {
    
            try {
                String papFilename =  "com/rim/samples/server/httppushdemo/pap_push.txt";
    	      	InputStream ins = new BufferedInputStream(new FileInputStream(papFilename));            
                ByteArrayOutputStream bouts = new ByteArrayOutputStream();
                copyStreams(ins, bouts);
                this.requestTemplate = new String(bouts.toByteArray());
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
        
        private void setupNotifyThread()
        {
            if( !notificationThread.isAlive() )
            {
                notificationThread = new NotificationThread();
                notificationThread.start(); 
            }
        }   
    
        private void papPush(String data)
        {
            String push id="_donepushID:13522321628822"+random.nextInt();
            
            setupNotifyThread();
            
            readPapTemplate();
            String errorCode = null;
            try {
                String mdsHost = "localhost";
                URL mdsUrl = new URL("http", mdsHost, MDS_PORT, "/pap");
                System.out.println(" sending PAP request to " + mdsUrl.toString() + "; pushId = " + pushId);
    
                HttpURLConnection mdsConn = (HttpURLConnection)mdsUrl.openConnection();
    
                String boundary = "";
                boundary = "asdlfkjiurwghasf";
                mdsConn.setRequestProperty("Content-Type", "multipart/related; type=\"application/xml\"; boundary=" + boundary);
                mdsConn.setRequestProperty("X-Wap-Application-Id", "/");
                mdsConn.setRequestProperty("X-Rim-Push-Dest-Port","100");
                mdsConn.setRequestMethod("POST");
    
                mdsConn.setAllowUserInteraction(false);
                mdsConn.setDoInput(true);
                mdsConn.setDoOutput(true);
    
                String output = requestTemplate.replaceAll("\\$\\(pushid\\)", pushId);
                output = output.replaceAll("\\$\\(boundary\\)", boundary);
                output = output.replaceAll("\\$\\(notifyURL\\)", "" + notifyURL);
                output = output.replaceAll("\\$\\(pin\\)", "" + _pinField.getText());
    
                String   deliveryMethod = "confirmed";
    
                output = output.replaceAll("\\$\\(deliveryMethod\\)", deliveryMethod);
    
    
                output = output.replaceAll("\\$\\(headers\\)", "Content-Type: text/plain");
                output = output.replaceAll("\\$\\(content\\)", data);
    
                output = output.replaceAll("\r\n", "EOL");
                output = output.replaceAll("\n", "EOL");
                output = output.replaceAll("EOL", "\r\n");
    
    
                System.out.println(output);
                OutputStream outs = mdsConn.getOutputStream();
                copyStreams(new ByteArrayInputStream(output.getBytes()), outs);
    
                mdsConn.connect();
    
                ByteArrayOutputStream response = new ByteArrayOutputStream();
                copyStreams(mdsConn.getInputStream(), response);
    
                int httpCode = mdsConn.getResponseCode();
    
                if (httpCode != HttpURLConnection.HTTP_ACCEPTED) {
                    throw new Exception("MDS returned HTTP status: " + httpCode);
                }
    
            } catch (Exception exception) {
                if (errorCode == null)
                {
                    errorCode = exception.getClass().getName();
                }
    
                System.out.println(" encountered error on submission: " + exception.toString());
            }
        }
    
        public void copyStreams(InputStream ins, OutputStream outs) throws IOException
        {
                int maxRead = 1024;
                byte [] buffer = new byte[1024];
                int bytesRead;
    
                for(;;)
                {
                    bytesRead = ins.read(buffer);
                    System.out.println(buffer);
                    if (bytesRead <= 0) break; 
                    outs.write(buffer, 0, bytesRead);
                }
        }
    
        /** Exit the Application */
        private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm
            System.exit (0);
        }//GEN-LAST:event_exitForm
    
        /**
        * @param args the command line arguments
        */
        public static void main (String args[]) {
            new HTTPPushDemo ().show ();
        }
    
        // Variables declaration - do not modify//GEN-BEGIN:variables
        private javax.swing.JPanel _panel;
        private javax.swing.JTextField _textField;
        private javax.swing.JTextArea _textArea;
        private javax.swing.JTextField _pinField;
        private javax.swing.JTextArea _label;
        private javax.swing.JTextArea _notification;
        private javax.swing.JButton _sendButton;
        private javax.swing.JRadioButton _rimButton;
        private javax.swing.JRadioButton _papButton;
        private javax.swing.ButtonGroup _buttonGroup;
        private javax.swing.JScrollPane _scrollPane;
    
        // End of variables declaration//GEN-END:variables
    
        public class NotificationThread extends Thread {
    
            public void run() 
            {
                try {
                    System.out.println("Waiting for notification on port " + 7778 + "...");
                    while (true)
                    {
                        ServerSocket serverSocket = new ServerSocket(7778);
                        serverSocket.setSoTimeout(120000);
                        try {
                            Socket clientSocket = serverSocket.accept();
                            _notification.setText("Received notification:");
                            InputStream input = clientSocket.getInputStream();
                            StringBuffer str= new StringBuffer();
                            int byteRead = input.read();
                            while ((byteRead != -1) && (input.available() > 0))
                            {
                                str.append((char)byteRead);
                                byteRead = input.read();
                            }
                            _notification.append(str.toString());
                            PrintWriter output = new PrintWriter(clientSocket.getOutputStream());
                            output.close();
                            clientSocket.close();
                        } catch (SocketTimeoutException ste) {
                            System.out.println("Notification connection timeout. Restarting...");
                        }               
                        serverSocket.close();
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }
        }
    }

XML control entity template

The server-side sample app uses the following template to create the XML control entity when the PAP push format is used. The sample app reads the template, then replaces the template content with real values.

--$(boundary)
Content-Type: application/xml; charset=UTF-8

<?xml version="1.0"?>
<!DOCTYPE pap PUBLIC "-//WAPFORUM//DTD PAP 2.0//EN" 
        "http://www.wapforum.org/DTD/pap_2.0.dtd" 
        [<?wap-pap-ver supported-versions="2.0,1.*"?>]>
<pap>
    <push-message push-id="_done$(pushid)13522321621189" 
          source-reference="$(username)"
          deliver-before-timestamp="2009-10-10T19:00:00Z"
          ppg-notify-requested-to="$(notifyURL)">
       <address address-value="$(pin)"/>
       <quality-of-service delivery-method="$(deliveryMethod)"/>
    </push-message>
</pap>
--$(boundary)
$(headers)

$(content)
--$(boundary)--

Last modified: 2015-06-11



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus