Java EE 7 SDK

Samples Main Page

# The HTTP Upgrade Servlet Sample Application

This sample application demonstrates how to use the HTTP Protocol Upgrade API from the Servlet specification.

## Description

HTTP/1.1 allows the client to specify additional communication protocols that it supports and would like to use. The Servlet specification includes support for the HTTP protocol upgrade mechanism. The client (`ClientTest`) initiates the upgrade request. The server (`ServerTest`) receives the upgrade request and invokes the `HttpServletRequest.upgrade()` method, which instantiates the `HttpUpgradeHandler` implementation (`ProtocolUpgradeHandler`). The `HttpUpgradeHandler.init()` method is invoked after exiting the `ProcessRequest()` method of the servlet.

In this sample, the client sends the request to the server. The server accepts the request, sends back the response, and then invokes the `HttpUpgradeHandler.init()` method and continues the communication using a dummy protocol. The client shows the request and response headers during the handshake process.

Client

In `ClientTest.java`, the client initiates the HTTP upgrade request.

    @WebServlet(name = "ClientTest", urlPatterns = {"/"})
    public class ClientTest extends HttpServlet {
        protected void processRequest(HttpServletRequest request, HttpServletResponse response)
                                      throws ServletException, IOException {
    	    ...
            String reqStr = "POST " + contextRoot + "/ServerTest HTTP/1.1" + CRLF;
            reqStr += "User-Agent: Java/1.7" + CRLF;
            reqStr += "Host: " + host + ":" + port + CRLF;
            reqStr += "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" + CRLF;
            reqStr += "Upgrade: Dummy Protocol" + CRLF;
            reqStr += "Connection: Upgrade" + CRLF;
            reqStr += "Content-type: application/x-www-form-urlencoded" + CRLF;
            reqStr += "Transfer-Encoding: chunked" + CRLF;
            reqStr += CRLF;
            reqStr += Data + CRLF;

            // Create socket connection to ServerTest
            s = new Socket(host, port);
            input = s.getInputStream();
            output = s.getOutputStream();
    		// Send request header with data
            output.write(reqStr.getBytes());
            output.flush();
       }
    }

The header `Upgrade: Dummy Protocol` is an HTTP/1.1 header field set to `Dummy Protocol` in this sample. The server decides whether to accept the protocol upgrade request.

Server

`ServerTest.java` checks the `Upgrade` field in the request header. When it accepts the upgrade requests, the server instantiates `ProtocolUpgradeHandler`, which is the implementation of `HttpUpgradeHandler`. If the server does not support the `Upgrade` protocol specified by the client, it sends a response with 404 Status.

    @WebServlet(name="ServerTest", urlPatterns={"/ServerTest"})
    public class ServerTest extends HttpServlet {
        protected void processRequest(HttpServletRequest request, HttpServletResponse response)
                                      throws ServletException, IOException {
            // Checking request header
            if ("Dummy Protocol".equals(request.getHeader("Upgrade"))) {
                System.out.println("Accept to upgrade");
                response.setStatus(101);
                response.setHeader("X-Powered-By", "Servlet/3.1 "
                    + "(GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)");
                response.setHeader("Upgrade", "Dummy Protocol");
                response.setHeader("Connection", "Upgrade");
                response.flushBuffer();
                // Call the upgrade API, and invoke the upgrade handler
                ProtocolUpgradeHandler handler = request.upgrade(ProtocolUpgradeHandler.class);
            } else {
                response.setStatus(400);
                response.setHeader("X-Powered-By", "Servlet/3.1 "
                    + "(GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)");
                response.setHeader("Connection", "Refused");
                response.sendError(400, "The Upgrade request sent by the client was incorrect or can not be accept by the server");
                System.out.println("Upgrade field is: " + request.getHeader("Upgrade"));
                System.out.println("Upgrade refused");
            }
        }
        ...
    }

`ProtocolUpgradeHandler` is the implementation of `HttpUpgradeHandler`, which processes the upgrade request and switchs the comminication protocol. The server checks the value of the `Upgrade` header to determine if it supports that protocol. Once server accepts the request, it must use the `Upgrade` header field within a 101 (Switching Protocols) response to indicate which protocol(s) are being switched.

Implementation of HttpUpgradeHandler

`ProtocolUpgradeHandler` is the implementation of `HttpUpgradeHandler`.

    public class ProtocolUpgradeHandler implements HttpUpgradeHandler {
        @Override
        public void init(WebConnection wc) {
            this.wc = wc;
            try {
                ServletOutputStream output = wc.getOutputStream();
                ServletInputStream input = wc.getInputStream();
                Calendar calendar = Calendar.getInstance();
                DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

                // Reading the data into byte array
                input.read(echoData);

                // Setting new protocol header
                String resStr = "Dummy Protocol/1.0 " + CRLF;
                resStr += "Server: Glassfish/ServerTest" + CRLF;
                resStr += "Content-Type: text/html" + CRLF;
                resStr += "Connection: Upgrade" + CRLF;
                resStr += "Date: " + dateFormat.format(calendar.getTime()) + CRLF;
                resStr += CRLF;

    			// Appending data with new protocol
                resStr += new String(echoData) + CRLF;

                // Sending back to client
                ...
                output.write(resStr.getBytes());
                output.flush();
            } catch (IOException ex) {
                Logger.getLogger(ProtocolUpgradeHandler.class.getName()).log(Level.SEVERE, null, ex);
            }
    	    ...
        }

        @Override
        public void destroy() {
            ...

            try {
                wc.close();
            } catch (Exception ex) {
                Logger.getLogger(ProtocolUpgradeHandler.class.getName()).log(Level.SEVERE,
                                 "Failed to close connection", ex);
            }
    		...
        }
    }

The `init()` method sets up the new protocol headers. The new protocol is used for subsequent comminications. This sample uses a dummy protocol. The `destroy()` method is invoked when the upgrade process is done.

This sample shows the handshake process of the protocol upgrade. After the handshake process, the subsequent communications use the new protocol. This mechanism only applies to upgrading application-layer protocols upon the existing transport-layer connection. This feature is normally most useful for Java EE Platform providers.

## Key Features

This sample application demonstrates how to handle HTTP Protocol Upgrade requests in Java EE Servlets.

## Building, Deploying, and Running the Application

Following are the instructions for building, deploying, and running this sample application.

1. Set up your build environment and configure the application server with which the build system has to work by following the common build instructions.
2. `app_dir` is the sample application base directory: `samples_install_dir/servlet/http-upgrade-war`.
3. ````Change directory to `app_dir.
   `
4. Build and deploy the sample application using the `mvn` target:

Use the command below to run this sample which is using Cargo framework:

`app_dir> mvn clean verify cargo:run`

You can point Cargo to an already installed and running Glassfish server:

`app_dir> mvn clean verify cargo:run -Dglassfish.home=$<glassfish_dir>` (e.g. ../glassfish4)

You can also build, deploy the sample application without Cargo:

`app_dir> mvn install`

`app_dir> asadmin deploy ./target/<app_name>.war`

5. Run the sample as follows:
   - Use the browser to access
     `http://<javaee.server.name>:<javaee.server.port>/http-upgrade-war`
     The expected message in the browser is as follows:

         Http Upgrade Process

         Sending upgrade request to server......

         Request header with data:

         POST /http-upgrade-war/ServerTest HTTP/1.1
         User-Agent: Java/1.7
         Host: localhost:8080

         Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
         Upgrade: Dummy Protocol
         Connection: Upgrade
         Content-type: application/x-www-form-urlencoded
         Transfer-Encoding: chunked

         Hello World
         ---------------------------------------

         Server accept upgrade request, send back the response:

         Response header:

         HTTP/1.1 101 Web Socket Protocol Handshake
         X-Powered-By: Servlet/3.1 (GlassFish Server Open Source Edition 4.0 Java/Oracle Corporation/1.7)
         Server: GlassFish Server Open Source Edition 4.0
         Upgrade: Dummy Protocol
         Connection: Upgrade
         ---------------------------------------

         Server send back the response with new protocol and data:

         Response header with data:

         Dummy Protocol/1.0
         Server: Glassfish/ServerTest
         Content-Type: text/html
         Connection: Upgrade
         Date: 02/13/2013 18:03:28

         Hello World
         ---------------------------------------

         Connection with new protocol established

6. Use the glassfish command line to undeploy the application.

   `app_dir> asadmin undeploy` <app_name>

7. Use the target `clean` to remove the temporary directories like /target.

   `app_dir> mvn clean`

## Building, Deploying, and Running the Application in NetBeans IDE

Perform the following steps to build, deploy, and run the application using NetBeans IDE:

1. Refer to the common build instructions for setting up NetBeans IDE and Java EE 7 SDK.
2. In the NetBeans IDE, choose File → Open Project (Ctrl-Shift-O), navigate to the `samples_install_dir/servlet/` directory, select `http-upgrade-war`, and click Open Project.
3. In the Projects tab, right click `http-upgrade-war` and select Run to build, deploy, and run the project.

## Troubleshooting

If you have problems when running the application, refer the troubleshooting document.

Copyright © 1997-2013 Oracle and/or its affiliates. All rights reserved.