The Source for Java Technology Collaboration
User: Password:



Jean-Francois Arcand's Blog

Jean-Francois Arcand Jean-Francois Arcand has worked for Sun Microsystems since 2000. He currently works on GlassFish, mainly on the WebContainer and the new Java NIO based http engine called Grizzly. Before joining Sun, he has worked as a software architect for compagnies such as France Telecom, Microcell Telecom and HMS Software, in both Java and C++. Jean-Francois lives and works from home in Prevost, a very small city in Quebec where life is perfect.



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

Posted by jfarcand on July 08, 2008 at 04:07 PM | Permalink | Comments (0)

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.

technorati:



Extending the Grizzly HTTP Runtime

Posted by jfarcand on July 03, 2008 at 08:52 PM | Permalink | Comments (3)

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!

technorati:



Getting started with Comet and GlassFish v2

Posted by jfarcand on July 02, 2008 at 09:39 AM | Permalink | Comments (0)

The Grizzly users list is bombarded with questions about how to start with Comet and GlassFish v2. Here is a quick explanation...

IMG_0317.JPG

GlassFish v2 ships with Grizzly 1.0.20 (not Grizzly 1.8.0) so to easily compile your application, just download 1.0.20, and then make sure your add that jar file to your classpath. That steps should be quite trivial if you are using Netbeans or Eclipse. Then you are ready to write your first Comet application.

Now once you are ready to deploy your application using Grizzly Comet or GlassFish v3, make sure you read this blog. In short, make sure you add the grizzly-compat.jar to your WEB-INF/lib to be able deploy without having to recompile your application against Grizzly 1.8.0.

technorati:



Porting and Compiling your GlassFish v2 Comet application To v3

Posted by jfarcand on July 01, 2008 at 02:18 PM | Permalink | Comments (2)

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.

technorati:



Writing a TCP/UDP stack supporting the SIP protocol using the Grizzly Framework, part II

Posted by jfarcand on June 25, 2008 at 02:28 PM | Permalink | Comments (4)

Back to technical blog after "buzzwording" for too long :-). Time to resume the tutorial about Grizzly and SIP. The first part was explaining Grizzly's server side components, this time I will concentrate on the client components. Like for the first part, I will not yet jump into the details of the SIP protocol.

IMG_0300.JPG

As for the server side, you first need to create the entry point in Grizzly, which is the Controller.

 Controller controller = new Controller();

Next, we need to configure which transport we want to support. For this blog purpose, I will only explain how to support UDP and TCP, and talk about TLS later. In Grizzly, a transport is represented using the ConnectorHandler interface, and the framework support by default three implementation: TCPConnectorHandler, TLSConnectorHandler and UDPConnectorHandler. By default, the Controller support TCP, but to help understanding how it works, the code below will explicitly configure the Controller to support TCP and UDP:

ConnectorHandler tcpConnector = controller.acquireConnectorHandler(Controller.Protocol.TCP);

ConnectorHandler udpConnector = controller.acquireConnectorHandler(Controller.Protocol.UDP);

Next we need to decide if we want to use a ProtocolChain for handling our request/response, or use a CallbackHandler to experiment with the bytes and the state of the connection. Since SIP is a two way protocol (the client can become the server and vice versa), let's first demonstrate how to use a ConnectorHandler with a ProtocolChain. For the purpose of this blog, let's add a (LogFilter) that output the bytes sent by the server:

ProtocolChain protocolChain = controller.getProtocolChain();
protocolChain.addFilter(new ReadFilter());
protocolChain.addFilter(new LogFilter());

That means that once we are connected to a remote server, all the bytes we are getting back will be processed by the ReadFilter and LogFilter. So let's connect:

tcpConnector.connect(new InetSocketAddress("localhost",8080),null);
tcpConnector.write(ByteBuffer.wrap(sipRequestBytes));

What is interesting here is the ProtocolChain used for reading the bytes can also be used on the server side. So let's say we wrote a SipParserProtocolFilter, we can use that ProtocolFilter for parsing the bytes send by a remote client and also we can use it to parse the response we are getting when connecting to a remote server:


      1 package com.sun.grizzly.utils;
      2 import com.sun.grizzly.ConnectorHandler;
      3 import com.sun.grizzly.Controller;
      4 import com.sun.grizzly.DefaultPipeline;
      5 import com.sun.grizzly.Pipeline;
      6 import com.sun.grizzly.ProtocolChain;
      7 import com.sun.grizzly.ProtocolChainInstanceHandler;
      8 import com.sun.grizzly.TCPSelectorHandler;
      9 import com.sun.grizzly.UDPSelectorHandler;
     10 import com.sun.grizzly.filter.LogFilter;
     11 import com.sun.grizzly.filter.ReadFilter;
     12 
     13 public class SipDemo {
     14 
     15     public void startSIPServerDemo(){
     16 
     17         Controller controller = new Controller();
     18 
     19         TCPSelectorHandler tcpSelector = new TCPSelectorHandler();
     20         tcpSelector.setPort(8080);
     21         controller.addSelectorHandler(tcpSelector);
     22 
     23         UDPSelectorHandler udpSelector = new UDPSelectorHandler();
     24         udpSelector.setPort(8080);
     25         controller.addSelectorHandler(udpSelector);
     26 
     27         Pipeline mySharedPipeline = new DefaultPipeline();
     28         mySharedPipeline.setMaxThreads(5);
     29 
     30         controller.setPipeline(mySharedPipeline);
     31 
     32         ProtocolChainInstanceHandler pciHandler =
     33                 new ProtocolChainInstanceHandler() {
     34 
     35             final private ProtocolChain protocolChain = new DefaultProtocolChain();
     36 
     37             public ProtocolChain poll() {
     38                 return protocolChain;
     39             }
     40 
     41             public boolean offer(ProtocolChain instance) {
     42                 return true;
     43             }
     44         };
     45         controller.setProtocolChainInstanceHandler(pciHandler);
     46 
     47         ProtocolChain protocolChain = pciHandler.poll();
     48         protocolChain.addFilter(new ReadFilter());
     49         protocolChain.addFilter(new LogFilter());
     50 
     51         controller.start();
     52         ConnectorHandler ch = controller.acquireConnectorHandler(Controller.Protocol.TCP);
     53         ch.connect(new InetSocketAddress("localhost",8080),null);
     54     }
     55 
     55 }

Graphically, it looks like the following:

demo1.jpg

Now let's assume we want to use the ConnectorHandler for read and write operations, but this time without using a ProtocolChain. The component we can use in that case is called a CallbackHandler. In the example above, we haven't created any CallbackHandler, but under the hood, Grizzly created one (the DefaultCallbackHandler), which dispatch all connect, read and write operations to the ProtocolChain. By default, the CallbackHandler interface, which is invoked by the Controller every time there is an asynchonous operations ready to be processed, looks like:

 41 /**
 42  * Callback handler for non blocking client operations.
 43  *
 44  * @param E  object containing information about the current
 45  *        non blocking connection
 46  * @author Jeanfrancois Arcand
 47  */
 48 public interface CallbackHandler extends Handler{
 49 
 50     /**
 51      * This method is called when an non blocking OP_CONNECT is ready
 52      * to get processed. This method must invoke ConnectorHandler.finishConnect()
 53      * to complete the connection operations.
 54      *
 55      * @param ioEvent an object containing information about the current
 56      *        non blocking connection.
 57      */
 58     public void onConnect(IOEvent ioEvent);
 59 
 60 
 61     /**
 62      * This method is called when an non blocking OP_READ is ready
 63      * to get processed.
 64      * @param ioEvent an object containing information about the current
 65      *        non blocking connection.
 66      */
 67     public void onRead(IOEvent ioEvent);
 68 
 69 
 70     /**
 71      * This method is called when an non blocking OP_WRITE is ready
 72      * to get processed.
 73      * @param ioEvent an object containing information about the current
 74      *        non blocking connection.
 75      */
 76     public void onWrite(IOEvent ioEvent);
 77 
 78 }

As an example, here is a simple implementation of a CallbackHandler connect, read and write operations:

274             public void onConnect(IOEvent ioEvent) {
275                 SelectionKey key = ioEvent.attachment().getSelectionKey();
276                 try{
277                     tcpConnector.finishConnect(key);
278                 } catch (IOException ex){
279                     ex.printStackTrace();
280                 }   
281                 // Register for read events
282                 ioEvent.attachment().getSelectorHandler().register(key,
283                         SelectionKey.OP_READ);
284             }
285             
286             public void onRead(IOEvent ioEvent) {
287                 SelectionKey key = ioEvent.attachment().getSelectionKey();
288                 SelectorHandler selectorHandler = ioEvent.attachment().
289                         getSelectorHandler(); 
290                 SocketChannel socketChannel = (SocketChannel)key.channel();
291                 
292                 try {
293                     int nRead = socketChannel.read(readBB);
294                     // Do something with the bytes
295                     // ...
296                     // Ask for more bytes
297                     selectorHandler.register(key, SelectionKey.OP_READ);
298                 } catch (IOException ex){
299                     selectorHandler.getSelectionKeyHandler().cancel(key);
300                 }   
301             }   
302 
303             public void onWrite(IOEvent ioEvent) {
304                 SelectionKey key = ioEvent.attachment().getSelectionKey();
305                 SelectorHandler selectorHandler = ioEvent.attachment().
306                         getSelectorHandler();
307                 SocketChannel socketChannel = (SocketChannel)key.channel();
308                 try{
309                     while(writeBB.hasRemaining()){
310                         int nWrite = socketChannel.write(writeBB);
311                         
312                         if (nWrite == 0){
313                             selectorHandler.register(key, SelectionKey.OP_WRITE);
314                             return;
315                         }   
316                     }
317                 } catch (IOException ex){
318                     selectorHandler.getSelectionKeyHandler().cancel(key);
319                 }   
320 
321             }

With the example above, you can always decide to delegate the processing of the bytes to your ProtocolChain, which wasn't the case with my first example. Graphically, it looks like:

demo3.jpg

To configure your CallbackHandler, you just need to pass an instance when executing the asynchronous connect operation:

tcpConnector.connect(new InetSocketAddress("localhost",8080),new MyConnectorHandler());

The only difference here is instead of passing a null, we are passing an instance of CallbackHandler. What I like with CallbackHandler is that I can decide when I want to delegate the processing to a ProtocolChain, and completely ignore that component if I don't want to write ProtocolFilter. And when I write a non blocking client, I can always decide to either write a CallbackHandler, or a simple ProtocolFilter.

OK, hopefully the next blog for that serie will happens sooner. Next time I will start digging about SIP and how we have implemented it in Sailfin.

technorati:



Ursus arctos horribilis: Grizzly 1.8.0 released (Community release!)

Posted by jfarcand on June 11, 2008 at 03:25 PM | Permalink | Comments (0)

Our biggest release ever :-)...OK last time I've claimed the same fact..naaaa our biggest one will be Grizzly 2.0! Well, 1.8.0 contains a lot of bug fixes, performance improvements, cool new technologies support (GWT, iPhone, etc.), new Comet components, new embeddable features, etc.

IMG_0283.JPG

This release fix multiples bugs and RFE:

More important, the community keep growing and we are getting more and more feedback, test cases, code donation, tutorials, help....this is just amazing :-). On the performance side, we have compared with Grizzly 1.0.20 using Faban (2000 simultaneous connections):

1.8.0:

  ops/sec: 3094.108
  % errors: 0.0
  avg. time: 0.059
  max time: 13.208
  90th %: 0.10

1.0.20:

  ops/sec: 2510.742
  % errors: 0.0
  avg. time: 0.143
  max time: 12.796
  90th %: 0.25   

Looks like we are also improving performance of our http extension. Try it using embeddable/OSGi bundles by downloading them from here! And finally, there are some rumors Grizzly works like a charm on the iPhone...is that cool?

technorati:



AjaxPush/Comet Webinar next June 02 @ 9h00 PST

Posted by jfarcand on May 30, 2008 at 02:58 PM | Permalink | Comments (0)

If you have missed our JavaOne session on Ajax Push/Comet, don't miss the upcoming Webminar. Tomcat, Jetty and GlassFish with a taste of Bayeux Protocol are discussed... Register here.

I'm really becoming a bad evangelist will all those talks :-)...fortunately Ted is there to patch :-)

technorati:



Les presentations de Open Tech Days sont disponibles...

Posted by jfarcand on May 30, 2008 at 12:59 PM | Permalink | Comments (0)

Les présentations de Montréal et Toronto: La première ainsi que la seconde. La prochaine fois, on ne parle qu'en français :-). Pour que l'on rigole un peu, j'invite Alexis pour qu'il nous apprenne a bien utiliser des mots anglais en francais (comme mail, shopping, playback, browser, slides, etc.) :-). En plus on fait cela ici...

IMG_0284.JPG

technorati:



Grizzly & Comet JavaOne's sessions online...with bofs slides as well

Posted by jfarcand on May 30, 2008 at 08:46 AM | Permalink | Comments (0)

IMG_0286.JPG

The AjaxPush/Comet session is now available, as well as the Grizzly session. I've already talked about the GWT and Grizzly Comet bof, and a demo is now online...the last bof I've had was with Jim, Using Comet to Create a Two-Player Web Game, and here are the slides.

technorati:



Grizzly 1.0.20 available for the old bear's lover..with an updated Bayeux Implementation

Posted by jfarcand on May 22, 2008 at 06:24 PM | Permalink | Comments (0)

For the old timer Grizzly 1.0.x users (like open-esb), I've just uploaded the latest grizzly 1.0.20 binaries from GlassFish v2.1. You can download them from here. Of course, you are welcome to try our latest release, which is 1.7.3.3!

david_essai.jpg

1.0.20 contains bug fixes and a back port of Grizzly Comet and its Bayeux Protocol (cometd) implementation from 1.7.3.3. This allow GlassFish v2 users to have the latest and greatest Bayeux implementation! You can download Bayeux example from here. 1.0.20 should be the latest release...snif snif snif for the now old Grizzly 1.0!

technorati:



Building GWT Comet based web app using Grizzly Comet

Posted by jfarcand on May 20, 2008 at 12:58 PM | Permalink | Comments (9)

I'm getting a lot of requests to share our JavaOne BOF slides where we have demonstrated the use of GWT + Grizzly Comet.

IMG_0268.JPG

Download the presentation here. We are still working on cleaning up the demo (and make sure I can commit the GWT code inside the Grizzly workspace). So stay tuned for the demo, but it is so simple to use Grizzly Comet + GWT you might not even need a demo :-). Unlike Jetty, you don't need any changes to GWT core classes to make it work :-) I was thinking to start blogging about GWT + Grizzly Comet integration, but I still need to write the follow up to my Grizzly SIP implementation first, so the preso should be a good startup. If you have questions, post them here or send an email to users@grizzly.dev.java.net

technorati:



Bye Bye Grizzly's JRuby extension, long live inside glassfish-scripting project.

Posted by jfarcand on May 20, 2008 at 11:32 AM | Permalink | Comments (0)

Starting today, we have voted to move out of the Grizzly umbrella the grizzly-jruby extension and its OSGi bundle. Where the code is going? Under the new glassfish-scripting project.

IMG_0255.JPG

The grizzly-jruby module is the foundation for the JRuby support in GlassFish v3 (aka GlassFish gem). Originally donated by TAKAI Naoto and maintained by the community, this Grizzly extension has grown enough to live outside the bear territories.....and have fun with other Grizzly based scripting extension like Groovy/Grails :-)

technorati:



Grizzly's OSGi bundles

Posted by jfarcand on May 15, 2008 at 01:23 PM | Permalink | Comments (4)

Grizzly has OSGi bundles available for a while, but we haven't made any noise about it yet to let the spotlight on GlassFish v3. Since OSGi is the current buzz, let's the monster enter the buzz circus...

DSC_0162.JPG

Since release 1.7.0 (we are now shipping 1.7.3.3), Grizzly ships with jar file manifests that include appropriate OSGi bundle information. This means that you can import the Grizzly jars into an OSGi framework and use them, for example, to build a I/O application using the framework classes, to build a static Web Server or a Comet messages bus. Those jars are currently self-contained for the reason that you can use them for testing using a simple command like:

java -jar [bundle-name] -p [port] -a [war|jar|directory location] [Component_name]

As an example, you can:

% java -jar grizzly-messagesbus-webserver-1.7.3.3.jar -p 8080 -a jmaki-messagesbus-demo.war

which start a simple Comet messages bus (I will soon blog about this new module). As usual, let us know what you think about those OSGi bundles, if they are ok or not, as none of us are OSGi expert. You can download those OSGi bundles from here...

technorati:



Upcoming ICEFaces/Grizzly/Comet talks in Canada

Posted by jfarcand on May 14, 2008 at 12:53 PM | Permalink | Comments (8)

Our ICEFaces/Comet/Grizzly Framework sessions at JavaOne were well attended and we have decided to give a couple of replay across Canada. Sessions on AjaxPush, GlassFish/Grizzly Framework and ICEFaces will be available May 27 (Toronto), May 29 (Montreal) and June 3 (Vancouver). Click here to register. I'm tempted to do the Montreal one in French ;-) Just need to convince Ted :-)

technorati:



JavaOne.CometBufferOverflowException: Asynchronous Ajax for Revolutionary Web Applications session Replay this Friday

Posted by jfarcand on May 07, 2008 at 06:03 PM | Permalink | Comments (1)

euhh..1100 peoples showed up for our Asynchronous Ajax for Revolutionary Web Applications session this morning...Good news for peoples that couldn't enter the room: Replay this Friday @ 12h10! And well, since you are there, why not registering for the Grizzly general session, which start Fri at 13h20! :-)

technorati:



Grizzly related talks @ JavaOne 2008

Posted by jfarcand on April 30, 2008 at 08:13 PM | Permalink | Comments (0)

Not yet tired of Grizzly? After CommunityOne and JavaOne, you will :-). The GlassFish's v1|2|3 favorite worst nightmare is coming to San Francisco...

CampsPhotosLeoJeanne 129.jpg

I'm doing the monkey all next week, and get ready to listen the Quebecois way of speaking English...as worst as when I write blog, pictures included :-):

After JavaOne, I promise....I hibernate Grizzly, and instead watch the atmosphere...

technorati:



GlassFish Vee(gri)zzly(v3): Unofficial benchmarks results

Posted by jfarcand on April 24, 2008 at 07:37 PM | Permalink | Comments (4)

We are still working hard on GlassFish v3 and will soon release a new technology preview (JavaOne is coming :-)). What about its performance? As you may know, in v3 we have cleaned up the noise by using a modular approach (thanks Jerome!). In Quebecois (French peoples are probably using some English world to say the same ;-), we say "Faire le Grand Menage"

mathieu 071.jpg

What about Grizzly-In-V3? In v3, the monster is now integrated using its framework module (no http pollution like in v2, just NIO:-)). So when v3 starts, part of its startup logic is done on top of Grizzly (using 1.7.3.1 runtime). Does it make a difference at startup and more important, at runtime? It make a huge one because now, with the modular nature of v3 there is no longer modules that add noise in Grizzly. So let's benchmark the static resources (.html) performance using Faban (see Scott's blog about it what is Faban) by using

java -classpath fabandriver.jar:fabancommon.jar -server 
-Xmx1500m -Xms1500m com.sun.faban.driver.ab -c 2000 http://xxx:8080/index.html

This command runs 2000 separate clients (each in its own thread), each of which continually requests index.html with no think time. The common driver reports three pieces of information: the number of requests served per second, the average response time per request, and the 90th percentile for requests: 90% of requests were served with that particular response time or less. Let's focus on the number of operations per seconds for now by running the test against Grizzly Http 1.0.20, Grizzly Http 1.7.3, v2 and v3:

Grizzly_1.0 Grizzly_1.7 GlassFish_v2 GlassFish_v3
 5739.025    5979.917    5432.300     5882.808

Hey hey v3 is almost as fast as Grizzly 1.7.3. Why? It really because v3 run on top of Grizzly directly, without any noise in between. Now let's compare the dynamic resource performance using a very simple Servlet


    public void doPost(HttpServletRequest request, HttpServletResponse response){
        response.setContentType("text/plain");
        response.setStatus(HttpServletResponse.SC_OK);
        PrintWriter wrt = response.getWriter();
        for (int i = 0; i < 1 ; i++) {
            wrt.write("Hello world");
        }
    }

Yes, its a dummy Servlet!


Grizzly_1.7 GlassFish_v2 GlassFish_v3
 3621.600    3256.775      2998.225

v3 is a little slower here......most probably because of the container's mapping algorithm. What is that? With v3, a tcp/udp port can handle any type of web applications (jruby, groovy, servlet, phobos, etc. (all build on top of Grizzly http :-)). So when a request comes in, v3 inspects and dispatch it to the proper container. That code introduces overhead and I suspect it is part of the regression. But a lot of changes has been made in v3, so I might be wrong...still, I consider the number very impressive as we have now a modular architecture which required a lot of changes.

But wait a minute. Grizzly 1.7 has a Servlet Container? Naaa not a real one. I'm just experimenting a tiny Servlet container, with great help from the Grizzly community. But forget Grizzly for now and look at the number :-) The goal for our v3 official release is set: We want to be better than Grizzly, which I'm sure we will :-). We need to improve the Grizzly extension in v3...in case you want to learn how to write such extension, just stop by us at JavaOne!

technorati:



Jersey 0.7 released...with a tiny taste of Grizzly Comet Support

Posted by jfarcand on April 18, 2008 at 10:31 AM | Permalink | Comments (0)

Last week, before unleashing the Grizzly at ApacheCon 2008, I've traveled to Grenoble to see if we can make a Comet to REST....

IMG_0127.JPG

Fortunately, it took Paul and I one day to have Jersey supporting Comet. This is not yet fully integrated in Jersey 0.7 (still working on a branch) but gives us a couple weeks and we gonna have something really amazing, as writing Comet applications using Jersey promises to be quite simple! We have started a discussion thread here in case you want to follow what we are doing. And for sure I will talk about it at JavaOne :-)

technorati:



July 2008
Sun Mon Tue Wed Thu Fri Sat
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    


Search this blog:
  

Categories
Community: Glassfish
Community: Java Enterprise
J2EE
Archives

July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
December 2006
November 2006
October 2006
September 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
June 2005

Recent Entries

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

Extending the Grizzly HTTP Runtime

Getting started with Comet and GlassFish v2



Powered by
Movable Type 3.01D


 Feed java.net RSS Feeds