Friday, June 8, 2007

Using Grizzly to create a simple HTTP listener

Today I would like to show how you can use Grizzly, a NIO framework for building scalable applications, to create a simple listener to service HTTP requests/responses. My main goal is to provide a simple example, because currently there is a lack of documentation on how to use this great framework (see jean's blog); although they have just made the javadocs available online.

My team and I have been working recently on developing a JBI Binding Component for RSS. To service the incoming HTTP GETs we decided to use Grizzly. Thankfully you can accomplish this with minimal effort.

The following is a simple example to start a TCP listener and respond with some simple text.

import com.sun.grizzly.http.SelectorThread;
import com.sun.grizzly.tcp.Adapter;
import com.sun.grizzly.tcp.OutputBuffer;
import com.sun.grizzly.tcp.Request;
import com.sun.grizzly.tcp.Response;
import com.sun.grizzly.util.buf.ByteChunk;

import java.net.HttpURLConnection;

public class EmbeddedServer implements Adapter {

public static void main(String[] args) {
SelectorThread st = new SelectorThread();
st.setPort(8282);
st.setAdapter(new EmbeddedServer());
try {
st.initEndpoint();
st.startEndpoint();
} catch (Exception e) {
System.out.println("Exception in SelectorThread: " + e);
} finally {
if (st.isRunning()) {
st.stopEndpoint();
}
}
}

public void service(Request request, Response response)
throws Exception {
String requestURI = request.requestURI().toString();

System.out.println("New incoming request with URI: " + requestURI);
System.out.println("Request Method is: " + request.method());

if (request.method().toString().equalsIgnoreCase("GET")) {
response.setStatus(HttpURLConnection.HTTP_OK);
byte[] bytes = "Here is my response text".getBytes();

ByteChunk chunk = new ByteChunk();
response.setContentLength(bytes.length);
response.setContentType("text/plain");
chunk.append(bytes, 0, bytes.length);
OutputBuffer buffer = response.getOutputBuffer();
buffer.doWrite(chunk, response);
response.finish();
}
}

public void afterService(Request request, Response response)
throws Exception {
request.recycle();
response.recycle();
}

public void fireAdapterEvent(String string, Object object) {}
}

That's basically it in a nutshell. So far Grizzly has worked out well for us and is currently being used in Glassfish and Sailfin.

As a side note I have also been reading a lot about groovy recently, so as an added bonus and a personal challenge to write my first groovy script, here is the equivalent groovy code. Remember that groovy scripts can use existing java classes and can also be consumed by java classes.
import com.sun.grizzly.http.SelectorThread
import com.sun.grizzly.tcp.Adapter
import com.sun.grizzly.tcp.Request
import com.sun.grizzly.tcp.Response
import com.sun.grizzly.util.buf.ByteChunk
import java.net.HttpURLConnection

class BasicAdapter implements Adapter {
public void service(Request request, Response response) {
def requestURI = request.requestURI().toString()

println 'New incoming request with URI: ' + requestURI
println 'Request Method is: ' + request.method()

if (request.method().toString().equalsIgnoreCase("GET")) {
response.status = HttpURLConnection.HTTP_OK
def bytes = 'Here is my response text'.bytes

def chunk = new ByteChunk();
response.contentLength = bytes.length
response.contentType = 'text/plain'
chunk.append(bytes, 0, bytes.length)
def buffer = response.outputBuffer
buffer.doWrite(chunk, response)
response.finish()
}
}

public void afterService(Request request, Response response) {
request.recycle()
response.recycle()
}

public void fireAdapterEvent(string, object) {}
}

def st = new SelectorThread()
st.port = 8282
st.adapter = new BasicAdapter()
try {
st.initEndpoint()
st.startEndpoint()
} finally {
if (st.isRunning()) {
st.stopEndpoint()
}
}

2 comments:

jlorenzen said...

Here is an example on how to use grizzly to recevie tcp/udp packets: http://gallemore.blogspot.com/2007/07/using-grizzly-to-read-tcp-packets.html

WoW Oro said...

Good post