Archive

Archive for January, 2009

Extending the Grizzly HTTP Runtime part VI: Writting A GrizzlyAdapter customized to run on an iPhone/IPod Touch

To support the Mozilla foundation (and others) against Apple, I’ve decided to follow Bruno Ghisi’s how to and install Java on my iPhone. I wasn’t able to resist to try Grizzly and set the bar high by trying to run my Twitter like application, which is powered by the Grizzly Comet Framework. Wow it works…but wait, let’s write a GrizzlyAdapter that’s snoop some iPhone info :-).

More info about what is a GrizzlyAdapter ->(I,II,II,IV, V)

First, download Grizzly from here (pick the Grizzly Comet or WebServer bundle), and then the sample from here. Next ssh those 2 files to your iPhone. Et voila!:

screen-0.png

Now lauch your favorite browser and boom:

screen-1.png

OK, that’s too easy. Now let’s use SQLLite to display my current set of contacts by writing our own GrizzlyAdapter:

        GrizzlyWebServer ws = new GrizzlyWebServer(path);
        ServletAdapter adapter = new ServletAdapter(new HttpServlet() {
            private ArrayList contacts;

            protected void doGet( HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                contacts = new ArrayList();

                try{
                    SQLite.Database ab = new SQLite.Database();
                    ab.open("/private/var/mobile/Library/AddressBook/AddressBook.sqlitedb", 0666); try {
                        SQLite.Stmt st = ab.prepare("select first, last from ABPerson where first is not null order by first");
                        try {
                            while (st.step())
                                contacts.add(st.column_string(0) + " "+ st.column_string(1));
                        } finally { st.close(); }
                    } finally { ab.close(); }

                    resp.setStatus(HttpServletResponse.SC_OK);
                    for (int i=0; i < contacts.size(); i++){
                        resp.getWriter().write("Contact: " + contacts.get(i) + "\n");
                    }
                } catch (Throwable t){
                    t.printStackTrace();
                }
            }
        });

        ws.addGrizzlyAdapter(adapter new String[]{"/"});
        System.out.println("Grizzly iPhoneServer listening on port 8080");
        ws.start();

Naaa you whispered I will show you my contacts! Naaa just cut & paste the above and compile…and see by yourself!! Need help: ping us on users@grizzly.dev.java.net, or Tweet us on Twitter.

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

technorati:

Categories: Uncategorized

Extending the Grizzly HTTP Runtime part V: Programatically configuring Servlet and GrizzlyAdapter

A lot of applications/framework (like Jersey, Hudson, DWR, etc.) out there just consist of a single Servlet which dispatch requests to its appropriate internal components. In such case, a full blown Servlet Container might not be needed….but a tiny 800k Grizzly might be!

IMG_0146.JPG

Like I’ve described in previous post on the topic (I,II,II,IV), it is extremely simple to build an HTTP extension/WebServer using Grizzly:

  1 GrizzlyWebServer ws = new GrizzlyWebServer(80);
  2 GrizzlyAdapter adapter = new GrizzlyAdapter() {
  3     @Override               
  4         public void service(GrizzlyRequest req, GrizzlyResponse res) {
  5             String uri = req.getRequestURI();                   
  6             File file = new File("/var/www",uri);                               
  7             long length = file.length();                                                        
  8                                                                                                                 
  9             if (file.exists()){                                                                                 
 10                 FileInputStream fis = null;                                                                                             
 11                 try{
 12                     fis = new FileInputStream(file);                                                                                           
 13                     FileOutputBuffer fob = (FileOutputBuffer)res.getOutputBuffer();
 14                     long nWrite = 0;                                                                                                           
 15                     while (nWrite < length) {
 16                         nWrite += fob.sendFile(fis.getChannel(), nWrite, length - nWrite);                                                     
 17                     }                                        
 18                 } catch (IOException ex){                                                                                                      
 19                     res.setStatus(404);                                              
 20                     res.setDetailMessage("Not Found");                                                                                         
 21                 } finally {                                                                                  
 22                     try{                                                                                                                       
 23                         fis.close();                                                                                                         
 24                     } catch (IOException ex){};
 25                 }                                                                                                                              
 26             } else {                                                                                                                           
 27                 res.setStatus(404);
 28                 res.setDetailMessage("Not Found");                                                                                             
 29             }                                                                                                                    
 30         }
 31 };                                                                                                                                             
 32 ws.addGrizzlyAdapter(adapter, new String[]{"/"});   

In 30 lines you just wrote a simple file server. But what about Servlet? Let’s take a very difficult application and try to launch it with Grizzly: Hudson. Let’s programmatically configure Hudson, similar to what we did for our simple file server. First, let’s create a simple wrapper.

  1 GrizzlyWebServer ws = new GrizzlyWebServer(80);
  2 ServletAdapter adapter = new ServletAdapter();
  3 adapter.setRootFolder("/tmp/hudson");
  4 adapter.setHandleStaticResources(true);
  5                                         
  6 adapter.setContextPath("/hudson");      
  7                                                 
  8 Servlet servlet = (Servlet)ClassLoaderUtil.load("org.kohsuke.stapler.Stapler");
  9 adapter.setServletInstance(servlet);                    
 10                                                                 
 11 Filter filter = (Filter)ClassLoaderUtil.load("hudson.security.HudsonFilter"); 
 12 adapter.addFilter(filter, "authentication-filter", null);               
 13                                                                                 
 14 adapter.addInitParameter("default-encoding", "UTF-8");                          
 15 
 16 filter = (Filter)ClassLoaderUtil.load("hudson.util.PluginServletFilter");               
 17 adapter.addFilter(filter, "plugins-filter", null);
 18                                                                                                 
 19 adapter.addServletListener("hudson.WebAppMain");
 20                                                                                                         
 21 adapter.setProperty("load-on-startup","1");                                                             
 22 
 23 ws.addGrizzlyAdapter(adapter, new String[]{"/hudson"});        

As you can see, this is quite simple. First, we create an instance of ServletAdapter (line 2), then configure the appropriate Servlet, Filter, and deployment information (line 8 to 21), taken from Hudson’s web.xml. Note line 23 where we finally add the Adapter to GrizzlyWebServer: just pass the ServletAdapter and a mapping (context) used to map requests. That’s it. You can download the result here and lunch Hudson on top of Grizzly by just doing:

java -jar grizzly-hudson-1.9.3.jar -p 8080 -a hudson.war

OK but this is cool as a demo, but doesn't add anything special to Hudson. Let's extends it by adding a chat functionality so we can blame each other when someone breaks the build. Let first add another Adapter that support the Bayeux protocol so we can chat using Comet

 24 ws.addGrizzlyAdapter(new CometdAdapter(), new String[]{"/cometd"});

So now we can package our 24 lines of code, and have a very small Hudson server with chat capability. Requests to /hudson goes to Hudson, /cometd goes to our Bayeux/Cometd chat application. Nothing fancy here as you can already do that using GlassFish. But quite simple to do it programmatically!. Another way to add Bayeux support could have been:

 24 ServletAdapter adapter2 = new ServletAdapter();
 25 adapter2.setRootFolder("/tmp/hudson");
 26 adapter2.setHandleStaticResources(true);
 27 
 28 adapter2.setContextPath("/cometd");
 29 
 30 Servlet servlet = (Servlet)ClassLoaderUtil.load("com.sun.grizzly.cometd.servlet.CometdServlet");
 31 adapter2.setServletInstance(servlet);
 32 
 33 ws.addGrizzlyAdapter(adapter2, new String[]{"/cometd"});

A little more complicated, but just to demonstrate how to programmatically deploy more than one Servlet.

Want to try it? download the grizzly-webserver.jar and uses your favorite IDE to build powerful HTTP based applications. Need help: ping us on users@grizzly.dev.java.net, or Tweet us on Twitter.

_uacct = "UA-3111670-1";
urchinTracker();

technorati:

Categories: Uncategorized