Archive

Archive for July, 2008

Extending the Grizzly HTTP Runtime part IV: Adding native PHP with support for the Bayeux Protocol

Before I deep dive into the AsyncFilter API I’ve proposed in part 3, I’ve decided to show how easy is to add…PHP to your Grizzly based application with support for the Bayeux protocol.

IMG_0321.JPG

In part one, two and three, I have showed how easy is to embed the Grizzly Http Runtime and add JMX and Monitoring support. This time I would like to add PHP to the picture. Yes, PHP! A couple of months ago, my friend Kin-Man blogged about running native PHP using the jsr223 Servlet. The PHP Servlet used in Kin-Man’s blog uses jsr223 scripting API and JNI to communicate with a native PHP runtime. That’s a really good Servlet to serve directly from Grizzly. How, by just doing the following:

   
        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/PHP/Folder");
            sa.setServlet(new com.sun.script.php.PHPServlet());
            // PHP requests are serviced under /php/
            sa.setContextPath("/php/");
            ws.addGrizzlyAdapter(sa);
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

That’s it. One thing you must make sure is to set the -Djava.library.path to point to your native PHP installation libs directory. Example:

 java -Djava.library.path=/path_to_php_installation/php/php-5.0.1/libs/ \ 
          -jar  grizzly-servlet-webserver-1.8.3.jar -p 8080 -a /www/php

will works, assuming you have added the required jars Kin-Man talks about inside the original grizzly-servlet bundle. Now let’s add the Comet based Bayeux protocol to the picture. This is also quite simple:

   
        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/PHP/Folder");
            sa.setServlet(new com.sun.script.php.PHPServlet());
            // PHP requests are serviced under /php/
            sa.setContextPath("/php/");
            ws.addGrizzlyAdapter(sa);

            // Add Comet Support
            ws.addAsyncFilter(new CometAsyncFilter());
 
            //Now that we have Comet support, 
            CometdAdapter cometdAdapter = new CometdAdapter();
            ws.addGrizzlyAdapter(cometdAdapter);

            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

That’s it! You have now a WebServer that supports PHP and the Bayeux protocol, where some requests are dispatched to PHP, and some to the Bayeux implementation. You can also bridge and push data from your PHP application to the Bayeux runtime using the PHP SAPI and by following Shing Wai’s blog on Java API to Bayeux we offer in Grizzly. Coucourouquuiquui! Since it’s vacation time, post your questions to users@grizzly.dev.java.net to be sure you get a response :-)

_uacct = “UA-3111670-1″;
urchinTracker();

technorati:

Categories: Uncategorized

Extending the Grizzly HTTP Runtime part III: Gathering Monster’s Statistics

So far we were able to build a WebServer based on Grizzly and add JMX Support to it. Now it is time to gather statistics of what’s happening inside the monster’ stomach.

mathieu 009.jpg

Part I was about building synchronous and asynchronous Web Server using Grizzly Http Engine, part II demonstrated how to add JMX support and track what’s happening. Let’s re-use the example we used in part II:

 47         GrizzlyWebServer ws = new GrizzlyWebServer(path);
 48         ServletAdapter sa = new ServletAdapter();
 49         sa.setRootFolder("/Path/To/Exploded/War/File");
 50         sa.setServlet(new MyServlet());
 51         sa.setContextPath("/myServlet");
 52         ws.addGrizzlyAdapter(sa);
 53 
 54         ServletAdapter sa2 = new ServletAdapter();
 55         sa2.setRootFolder("/Path/To/Exploded/War2/File");
 56         sa2.setServlet(new MySecondServlet());
 57         sa2.setContextPath("/mySecondServlet");
 58         ws.addGrizzlyAdapter(sa2);
 59 
 60         ws.enableJMX(new Management() {
 61 
 62             public void registerComponent(Object bean, ObjectName oname, String type)
 63                     throws Exception {
 64                 Registry.getRegistry().registerComponent(bean, oname, type);
 65             }
 66 
 67             public void unregisterComponent(ObjectName oname) throws Exception {
 68                 Registry.getRegistry().
 69                         unregisterComponent(oname);
 70             }
 71         });
 72         ws.start();

There are two way to add statistics. First, you can just enable it using JMX and click on enableMonitoring button:

enableMonitoring.jpg

Then start doing request, and you can use jconsole to see the statistics:

Updates.jpg

Programmatically, you can enable statistics by just doing:

     56         GrizzlyWebServer ws = new GrizzlyWebServer(path);
     57         ws.enableJMX(new Management() {
     58 
     59             public void registerComponent(Object bean, ObjectName oname, String type)
     60                     throws Exception{
     61                 Registry.getRegistry().registerComponent(bean,oname,type);
     62             }
     63 
     64             public void unregisterComponent(ObjectName oname) throws Exception{
     65                 Registry.getRegistry().
     66                         unregisterComponent(oname);
     67             }
     68         });
     69 
     70         final Statistics stats = ws.getStatistics();
     71         stats.startGatheringStatistics();

The key method is GrizzlWebServer.getStatistics(). From the Statistics instance, you can start and stop gathering statistics. Below is an example that use a simple scheduler to output data on the console:

     45     // Simple scheduler that will outpot stats every 5 seconds.
     46     private static ScheduledThreadPoolExecutor ste =
     47             new ScheduledThreadPoolExecutor(1);
     48 
     49     public static void main( String args[] ) throws Exception {
     50         String path = args[0];
     51         if (args[0] == null || path == null){
     52             System.out.println("Invalid static resource path");
     53             System.exit(-1);
     54         }
     55 
     56         GrizzlyWebServer ws = new GrizzlyWebServer(path);
     57         ws.enableJMX(new Management() {
     58 
     59             public void registerComponent(Object bean, ObjectName oname, String type)
     60                     throws Exception{
     61                 Registry.getRegistry().registerComponent(bean,oname,type);
     62             }
     63 
     64             public void unregisterComponent(ObjectName oname) throws Exception{
     65                 Registry.getRegistry().
     66                         unregisterComponent(oname);
     67             }
     68         });
     69 
     70         final Statistics stats = ws.getStatistics();
     71         stats.startGatheringStatistics();
     72 
     73         ste.scheduleAtFixedRate(new Runnable() {
     74             public void run() {
     75                 System.out.println("Current connected users: " +
     76                         stats.getKeepAliveStatistics().getCountConnections());
     77                 System.out.println("How many requests since startup:" +
     78                         stats.getRequestStatistics().getRequestCount());
     79                 System.out.println("How many connection we queued because of all" +
     80                         "thread were busy: " +
     81                         stats.getThreadPoolStatistics().getCountQueued());
     82                 return;
     83             }
     84         }, 0, 10,TimeUnit.SECONDS);
     85         System.out.println("Grizzly WebServer listening on port 8080");
     86         ws.start();
     87     }

Another easy things with the monster! You can download the above example from here (bundled as an OSGi bundle if you like OSGi). Next time I will explore ways to write AsyncFilter, which was partially covered in part 1.

_uacct = “UA-3111670-1″;
urchinTracker();

technorati:

Categories: Uncategorized

Extending the Grizzly HTTP Runtime part II: Managing the monster using JMX

Now that we are all able to create Grizzly Web Server in less than 10 lines, let’s complicate our day and add JMX management to the monster

IMG_0159.JPG

In part I, I’ve described how easy it is to create synchronous and asynchronous http based Web Server. One of the most complicated example was:

GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/Exploded/War/File");
            sa.setServlet(new MyServlet());
            sa.setContextPath("/myServlet");
            ws.addGrizzlyAdapter(sa);
  
            ServletAdapter sa2 = new ServletAdapter();
            sa2.setRootFolder("/Path/To/Exploded/War2/File");
            sa2.setServlet(new MySecondServlet());
            sa2.setContextPath("/mySecondServlet");
            ws.addGrizzlyAdapter(sa2);
  
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

That wasn’t too difficult, was it? Now let’s add JMX support:

 47         GrizzlyWebServer ws = new GrizzlyWebServer(path);
 48         ServletAdapter sa = new ServletAdapter();
 49         sa.setRootFolder("/Path/To/Exploded/War/File");
 50         sa.setServlet(new MyServlet());
 51         sa.setContextPath("/myServlet");
 52         ws.addGrizzlyAdapter(sa);
 53 
 54         ServletAdapter sa2 = new ServletAdapter();
 55         sa2.setRootFolder("/Path/To/Exploded/War2/File");
 56         sa2.setServlet(new MySecondServlet());
 57         sa2.setContextPath("/mySecondServlet");
 58         ws.addGrizzlyAdapter(sa2);
 59 
 60         ws.enableJMX(new Management() {
 61 
 62             public void registerComponent(Object bean, ObjectName oname, String type)
 63                     throws Exception {
 64                 Registry.getRegistry().registerComponent(bean, oname, type);
 65             }
 66 
 67             public void unregisterComponent(ObjectName oname) throws Exception {
 68                 Registry.getRegistry().
 69                         unregisterComponent(oname);
 70             }
 71         });
 72         ws.start();

To enable JMX, you just need to implement the Management interface, and set it using the enableJMX method of the GrizzlyWebServer class. As you can see, you can plug your own JMX implementation easily using the Management interface. In the example above, I’ve just used the Apache Commons Modeler, which does all the JMX “bla bla bla” for me via its org.apache.commons.modeler.Registry static class.

To see it live, I just do:

%  java -Dcom.sun.management.jmxremote.port=1199 -Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false -jar grizzly-embed-samples.jar

// Start jconsole
% jconsole

Hey hey I can see:

jconsole.jpg

Miaaaaaam! Next time I will explain how to grab statistics from your embedded GrizzlyWebServer, like number of requests, time spend, thread pool stats, etc. You can download the example above here. The binary can be used as it is and include all the Grizzly required classes to run.

_uacct = “UA-3111670-1″;
urchinTracker();

technorati:

Categories: Uncategorized

Extending the Grizzly HTTP Runtime

Project Grizzly provides developers with a simple and consistent mechanism for extending the functionality of the Grizzly HTTP Runtime and for bridging existing HTTP based technologies like JRuby-on-Rail, Grail, Servlet, the Bayeux Protocol or any http based protocol.

IMG_0320.JPG

There is three important classes to know when you want to extend (and embed):

  • GrizzlyAdapter: The GrizzlyAdapter is the main extensible point when you want to write an http based extension. This class is invoked by the Grizzly Http Runtime as soon as the http request has been parsed. It’s main method is defined as service(GrizzlyRequest req, GrizzlyResponse res). You can get all the http information from the GrizzlyRequest and write the response using the GrizzlyResponse. Grizzly ships with several implementation of the GrizzlyAdapter: ServletAdapter, CometdAdapter, StaticResourceAdapter, etc. You can look at the details by browsing the code from here
  • AsyncFilter: AsyncFilter are helpful when you want to write an asynchronous request processing based web server. AsyncFilter allows you to suspend the processing of an http request, and resume it once you are ready. When suspending the request execution, an AsyncFilter doesn’t block on a Thread so you don’t waste a Thread until the execution is resumed. AsyncFilter always execute before any GrizzlyAdapter
  • GrizzlyWebServer: The main entry point. You always first create an instance of the GrizzlyWebServer, and then add GrizzlyAdapter(s) and AsyncFilter(s).

Sound complicated? Not at all! Let’s describe some really simple examples.

First, let’s create a WebServer that serve static resources:

        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

Now let’s write a very simple GrizzlyAdapter that return an html page when a static resource is not found.

        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ws.addGrizzlyAdapter(new GrizzlyAdapter(){  
                
                public void service(GrizzlyRequest request, GrizzlyResponse response){
                    try {
                        response.getWriter().println("Grizzly is soo cool..but you request cannot be found!");
                    } catch (IOException ex) {                        
                    }
                }
            });
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

Now let’s add Servlet support to our WebServer (note that the Grizzly’s Servlet support is limited in term of functionalities..no deployment support, all done programatically)

   
        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/Exploded/War/File");
            sa.setServlet(new MyServlet());
            ws.addGrizzlyAdapter(sa);
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        } 

Well, why not adding two Servlet support

        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/Exploded/War/File");
            sa.setServlet(new MyServlet());
            ws.addGrizzlyAdapter(sa);
  
            ServletAdapter sa2 = new ServletAdapter();
            sa2.setRootFolder("/Path/To/Exploded/War2/File");
            sa2.setServlet(new MySecondServlet());
            ws.addGrizzlyAdapter(sa2);
  
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

Easy, it is (to speak like Yoda). Now let’s go back to basic, which is to serve static resources. Let’s assume we want to delay the request processing when we are under load, using an AsyncFilter. Let’s assume for now that all requests will be suspended 10 seconds before they get executed by the GrizzlyAdapter.

        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ws.addAsyncFilter(new AsyncFilter() {
                private final ScheduledThreadPoolExecutor scheduler = 
                        new ScheduledThreadPoolExecutor(1);
                public boolean doFilter(final AsyncExecutor asyncExecutor) {
                    //Throttle the request
                    scheduler.schedule(new Callable() {
                        public Object call() throws Exception {
                            asyncExecutor.execute();
                            asyncExecutor.postExecute();
                            return null;
                        }
                    }, 10, TimeUnit.SECONDS);
                    
                    // Call the next AsyncFilter
                    return true;
                }
            });
                                        
            ws.addGrizzlyAdapter(new GrizzlyAdapter(){                  
                public void service(GrizzlyRequest request, GrizzlyResponse response){
                    try {
                        response.getWriter().println("Grizzly is soon cool");
                    } catch (IOException ex) {                        
                    }
                }
            });
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

This is cool, is it? Now let’s add Servlet to the picture:

        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            ws.addAsyncFilter(new AsyncFilter() {
                private final ScheduledThreadPoolExecutor scheduler = 
                        new ScheduledThreadPoolExecutor(1);
                public boolean doFilter(final AsyncExecutor asyncExecutor) {
                    //Throttle the request
                    scheduler.schedule(new Callable() {
                        public Object call() throws Exception {
                            asyncExecutor.execute();
                            asyncExecutor.postExecute();
                            return null;
                        }
                    }, 10, TimeUnit.SECONDS);
                    
                    // Call the next AsyncFilter
                    return true;
                }
            });
  
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/Exploded/War/File");
            sa.setServlet(new MyServlet());
            ws.addGrizzlyAdapter(sa);
 
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        }

Miam Miam! OK now let do something really really complicated :-). Let’s add Comet into the picture. Naa not enough complicated. Let’s add the Bayeux Protocol (cometd) but also be able to serve static resources and Servlet.

        GrizzlyWebServer ws = new GrizzlyWebServer("/var/www");
        try{
            // Add Comet Support
            ws.addAsyncFilter(new CometAsyncFilter());
 
            //Add Bayeux support
            CometdAdapter cometdAdapter = new CometdAdapter();
            ws.addGrizzlyAdapter(cometdAdapter);
  
            ServletAdapter sa = new ServletAdapter();
            sa.setRootFolder("/Path/To/Exploded/War/File");
            sa.setContextPath("/servlets/");
            sa.setServlet(new MyServlet());
            ws.addGrizzlyAdapter(sa);
 
            ws.start();
        } catch (IOException ex){
            // Something when wrong.
        } 

Wow. With just a couple of line we were able to create a Web Server that supports the Bayeux Protocol, a single Servlet and static resources. Now you can do things much more complicated, like writing complex and powerful GrizzlyAdapter, and call it GlassFish v3 :-). v3 is a good example of how easy it is to build really powerful HTTP extension using the Grizzly extensible point like the GrizzlyAdapter.

Want to give it a try? Download the Grizzly HTTP extension, add it to your classpath, and look at the GrizzlyWebServer API. Now if you want to do things more complicated liked adding JMX support, monitoring, etc, then read that old blog serie and look at the now infamous SelectorThread documentation :-). If you have question, just stop by users@grizzly.dev.java.net…we have more and more peoples shaking the Grizzly those days!

_uacct = “UA-3111670-1″;
urchinTracker();

technorati:

Categories: Uncategorized

Porting and Compiling your GlassFish v2 Comet application To v3

When Grizzly became a top level project on java.net, we renamed it’s package from com.sun.enterprise.web.connector.grizzly to com.sun.grizzly. For the core package, the transition was quite smooth, but for Comet based application, having to rename the imported packages and then recompile was painful. Worse, building an application that works for both v2 and v3 was quite complicated, having to support two version of the same application. That’s what we call a backward compatibility!

IMG_0312.JPG

So why have we changed the package name? Well, the original package name was quite confusing (and we didn’t have the choice at that time..in 2006). The web.connector.grizzly didn’t make any sense as well. So renaming was the best thing we have to grow our new community. Hence, the Comet package has been renamed from com.sun.enterprise.web.connector.grizzly.comet to com.sun.grizzly.comet. If you are planning to write a Comet based application, I strongly recommend you use the old package name so your Comet application will work on v2 and v3 without the need to changes anything.

How to do that? First, download the grizzly-compat package, and use that module to build against it. As an example (much simpler with an IDE like Eclipse or Netbeans, but just for an example):

% javac -classpath grizzly-compat-1.8.0.jar your_classes

This will compile your application and make it work on all GlassFish anf Grizzly version that support Comet. You might also want to put the grizzly-compat jar file under WEB-INF/lib as early versions of GlassFish v3 didn’t included this module, hence you application will fail to deploy. That way you are sure your Comet applications works on all GlassFish flavors without requiring any changes.

_uacct = “UA-3111670-1″;
urchinTracker();

technorati:

Categories: Uncategorized
Follow

Get every new post delivered to your Inbox.

Join 50 other followers