Monday, March 31, 2008

Sun's Java HTTP Server

Some colleagues have pointed out that Sun's implementation of Java SE 6 JRE includes a built-in Java HTTP Server. There is not much information regarding this online, but there are enough details to start using it for small HTTP service needs.

The main step a developer must perform to make use of the built-in HTTP server is to implement the HttpHandler interface. The Javadoc API description for com.sun.net.httpserver contains an example of implementing the HttpHandler and includes an example of how to apply TLS/SSL.

The code listing that follows is my own implementation of the HttpHandler interface and is adapted from the example provided in the Javadoc documentation for package com.sun.net.httpserver.


package dustin.examples.httpserver;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.io.OutputStream;

/**
* Simple HTTP Server Handler example that demonstrates how easy it is to apply
* the Http Server built-in to Sun's Java SE 6 JVM.
*/
public class DustinHttpServerHandler implements HttpHandler
{
/**
* Implementation of only required method expected of an implementation of
* the HttpHandler interface.
*
* @param httpExchange Single-exchange HTTP request/response.
*/
public void handle(HttpExchange httpExchange) throws IOException
{
final String response = buildResponse();
// UPDATE (01 April 2008): Thanks to Christian Ullenboom for pointing
// out the constant used below (see comments on this blog entry below).
httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length());
final OutputStream os = httpExchange.getResponseBody();
os.write( response.getBytes() );
os.close();
}

/**
* Build a String to return to the web browser via an HTTP response.
*
* @return String for HTTP response.
*/
private String buildResponse()
{
final StringBuffer response = new StringBuffer();
response.append("<title>Sun's JVM HttpServer in Action</title>");
response.append("<h1 style=\"color: blue\">Hello, HttpServer!</h1>");
response.append("<p>This example shows that the Java SE 6 HttpServer ");
response.append("included with the Sun JVM is easy to use.</p>");
return response.toString();
}
}


The HttpHandler implementation shown above can be executed with a simple Java application as shown in the next code listing. Note that the port and the URL context that will be used to access the HttpServer are specified in this main executable code rather than in the more generic HttpHandler implementation above.


package dustin.examples.httpserver;

import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.net.InetSocketAddress;

/**
* Simple executable to start HttpServer for HTTP request/response interaction.
*/
public class Main
{
public static final int PORT = 8000;
public static final int BACKLOG = 0; // none
public static final String URL_CONTEXT = "/dustin";

/**
* Main executable to run Sun's built-in JVM HTTP server.
*
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException
{
final HttpServer server =
HttpServer.create(new InetSocketAddress(PORT), BACKLOG);
server.createContext(URL_CONTEXT, new DustinHttpServerHandler());
server.setExecutor(null); // allow default executor to be created
server.start();
}
}


To compile these two classes, one simply performs normal compilation of the Java classes. To run the HTTP Server, one simply runs the main executable just shown. This is demonstrated in the following screen snapshot.



The HTTP Server runs until I instruct it to stop with a CTRL-C. While it is running, I can view the rendered web page by accessing a URL based on port specified in the main class (8000) and a web context specified in the main class ("/dustin"). A screen snapshot of the rendered page in a web browser is shown next.



There are several important observations to be made regarding use of the HTTP Server.

1. The package com.sun.net.httpserver makes it clear that this functionality is part of Sun's JRE implementation and is not standard across all JREs for Java SE 6.

2. It is not shown here, but the Spring framework provides a SimpleHttpInvokerServiceExporter to make use of the Java HTTP Server. Related classes include SimpleHttpServerFactoryBean and SimpleHttpInvokerRequestExecutor. The Spring 2.5, an Update presentation (see slide 16).

3. The Java HTTP server is not a full-fledged HTTP Server.

4. This blog entry refers to the Java built-in HTTP server as "Core HTTP Server" and references "mini servlets."

5. See Bug ID 6270015 ("Support a Light-weight HTTP Server API").


As the code listings and snapshots above demonstrate, it is a straightforward process to implement a simple Java HTTP Server using the Sun-supplied built-in Java HTTP Server.

UPDATE (23 November 2008) Software Development: Easiest way to publish Java Web Services --how to talks about how to use this HTTP Server to publish web services.

4 comments:

Christian Ullenboom said...

Alternative to an own constant

public static final int HTTP_CODE_OK = 200;

you can use

HttpURLConnection.HTTP_OK

Christian

Dustin said...

Christian,

Thanks for pointing out HttpURLConnection.HTTP_OK. That is preferable to my own constant. I thought I had used or seen a constant like this before (it was HttpServletResponse.SC_OK that I was thinking of), but was too lazy to track it down and add it. Thanks for pointing it out.

Dustin

serkan said...

I hope this small http server supports html templates and simple traffic management. It is not nice to use response.append(......

I want to develop web interface for my java application. Do you think it is a good idea to use this server ?

Dustin said...

serkan,

I'd only use this built-in HTTP server for the simplest of demonstration purposes. For anything of significance, and especially for production, I'd use at least Tomcat or a Java-based application server.

Dustin