The Source for Java Technology Collaboration
User: Password:



Jean-Francois Arcand

Jean-Francois Arcand's Blog

Understanding Grizzly part I: Embedding Grizzly HTTP Web Server in 5 lines

Posted by jfarcand on December 08, 2006 at 11:33 AM | Comments (7)

Grizzly is more and more embedded in frameworks and products, and since the documentation is not as good as I would like, let's start a series of blogs that explain how to embed and extend the framework. All islands are available, I just need to describe how to move from island to island :-).

framework.jpg

The main entry point when embedding Grizzly is the SelectorThread. This class contains all the methods required to configure, start and stop the framework. Unfortunately, the number of methods is very large, making life difficult for new user. The good news is I'm currently working on refactoring that class and hiding all the methods that aren't required. OK enough wording......below is a simple example that instantiate the SelectorThread, configure it for tcp/http support and starts it:


     63         SelectorThread selectorThread = new SelectorThread();
     64         selectorThread.setPort(port);
     65         selectorThread.setAdapter(
     66                 new StaticResourcesAdapter());
     67         selectorThread.initEndpoint();
     68         selectorThread.startEndpoint();

First, you create the SelectorThread and set the TCP port on which the server will listen to requests. Next is to set an implementation of Adapter class (line 65). The Adapter is the glue code between the Grizzly framework and the program that embed Grizzly. In the example below, the StaticResourcesAdapter is servicing static html pages. The important method is:


    101     public void service(Request req, final Response res) throws Exception {
    102         MessageBytes mb = req.requestURI();
    103         ByteChunk requestURI = mb.getByteChunk();
    104

Grizzly parse the tcp/http request and store the result inside the Request and Response object and pass them to the Adapter.service() method. Those objects can then be used to get information about the request,configure the response, and flush it back to the client:


    152             res.setContentLength((int)resource.length());
    153             ((SocketChannelOutputBuffer)res.getOutputBuffer()).flush();
    154
    155             SocketChannel socketChannel =
    156                     ((SocketChannelOutputBuffer)res.getOutputBuffer()).getChannel()        ;
    157             FileInputStream stream = new FileInputStream(resource);
    158             FileChannel fileChannel = stream.getChannel();
    159
    160             long nread =0;
    161             while (nread < resource.length() && socketChannel.isOpen()) {
    162                 nread += fileChannel.transferTo(nread, fileChannel.size(),
    163                         socketChannel);
    164             }

The complete implementation can be found here.It may look complicated but it is really really easy to implement an Adapter. You can see Takai extension here for JRuby support in GlassFish, and Brian's Grizzly Asynchronous Request Processing (ARP) implementation.

What about the thread pool used by Grizzly(called Pipeline)? By default, it use the one that showed the best performance, and use only 20 threads. That will be the topic of my next blog on Understanding Grizzly.

technorati:


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Jean-Francois,

    I tried to start two SelectorThread endpoints in one class and the first thread never returned to allow the main to start the second.

    How can I accomplish this?

    My end goal is to basically create two simple servers on ports 8080 and 9090 and create a pass-through proxy where the input request stream of the first is wired to the second server whose port is being held open indefinitely.

    Any idea on the simplest way to create this?

    Jeff

    Posted by: tblack on February 13, 2007 at 02:49 PM

  • Right. By default, the SelectorThread will execute on the same thread as the client. To implement what you want, just do SelectorThread.start() instead of SelectorThread.startEndpoint(). Thanks!

    Posted by: jfarcand on February 13, 2007 at 03:15 PM

  • Hi,

    I tried your code to run WebServer by starting SelectorThread but when i tried to get index.html file from the server, it return blank page example http://localhost:8082/index.html , i just want to access some static file, let me know how to do this.I have index.html file in the start directory.

    I used port 8082 .

    Thanks for your great work.

    Pai

    Posted by: paipiski on March 04, 2007 at 02:16 PM

  • Hi, have you added the proper location when you started Grizzly. Something like java -jar grizzly.jar 8082 PATH_TO_INDEX.html? Thanks!

    Posted by: jfarcand on March 05, 2007 at 07:42 AM

  • Hi, I am trying to use this example in my implementation of a binding component in JBI, but for some reason the call to selectorThread.startEndpoint() hangs forever. If I implement it as a standalone java application it works as it should, but not within JBI (in glassfish). Any idea what might be the problem?

    Posted by: ermhawi on January 28, 2008 at 07:59 AM

  • Which version are you using? startEndpoint block because it start listening on the port you selected. Try using SelectorThread.listen() method or spawn a thread that invoke startEndpoint(). Next time if you can post your question on users@grizzly.dev.java.net....a lot of code/peoples can help!

    Thanks!

    Posted by: jfarcand on January 28, 2008 at 08:14 AM

  • hi
    how to publish my papers
    help me
    please

    Posted by: energyglassfish on June 29, 2008 at 10:11 AM



Only logged in users may post comments. Login Here.


Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds