Category: Uncategorized

  • Jetty Session Clustering with Terracotta

    Terracotta is an infrastructure that allows you to pretty much transparently cluster any code in a jvm. We’ve already successfully used it to cluster the channels in Jetty’s Bayeux (aka Cometd) implementation, so we thought it was high time we used it to cluster HTTP sessions.

    Jetty already has a WADI-based solution for HTTP session clustering, so providing a terracotta-based solution provides an alternative for users to be able to choose the most appropriate solution for their needs.

    The code is hot-off-the-press, so thus requires a little more polishing and testing, however it’s ready to try out, so give it a spin. Here’s the instructions:

    Building

    1. There are some changes to Jetty that have not yet been incorporated into trunk, so first you’ll need to check out this branch:

      https://svn.codehaus.org/jetty/jetty/branches/terracotta.
      

      Build it with:

      mvn clean install
      

      I’ll refer to the location where you’ve done the checkout as $JETTY-BRANCH.

    2. Check out the session clustering code from the jetty-contrib repo at:

      https://svn.codehaus.org/jetty-contrib/jetty/trunk/extras/terracotta. 

      Build it with:

      mvn clean install
      
      I'll refer to the location where you've done the checkout as $TC_EXTRAS.
      

    3. Copy the terracotta-sessions-6.1-SNAPSHOT.jar you just built into $JETTY-BRANCH/lib/ext.

    4. Check out terracotta trunk from:
      http://svn.terracotta.org/svn/tc/dso/trunk
      

      Follow the instructions on the terracotta site to build it and produce a bootjar. I'll refer to the root of the build results (usually in code/base/build/) as $TC-BUILD.

    Configuration

    1. You can setup all your webapps to use terracotta-based session clustering by copying the example jetty config file in $TC-EXTRAS/src/main/resources/jetty.xml to your $JETTY-BRANCH/etc/ directory.
    2. You might want to copy the example webapps from $TC-BUILD/dist/terracotta-trunk/samples/sessions into $JETTY-BRANCH/webapps to play with.

    Running

    Start the terracotta server:

    $TC-BUILD/dist/terracotta-trunk/bin/start-tc-server.sh
    -f $TC-EXTRAS/src/main/resources/tc-config-jetty.xml
    

    Start jetty:

    cd $JETTY-BRANCH
    java -Dtc.install-root=$TC_BUILD/dist/terracotta-trunk/
    -Xbootclasspath/p:[path to your boot jar]
    -Dtc.config=$TC-EXTRAS/src/main/resources/tc-config-jetty.xml
    -jar start.jar
    etc/jetty.xml
    

    Job done!

    Any webapps you deployed should have their session instances clustered. Don't forget, you'll need to start more than one jetty instance in order to see session clustering actually happening 🙂

    Many thanks are due to the guys at Terracotta for their expert help in the integration, in particular Tim Eck who was outstandingly helpful - thanks Tim!

    Java One

    If you're attending Java One, we'll be hanging out and demo-ing the session clustering at the Terracotta booth (booth #828) so drop by, eyeball the demo and come and have a chat to us.

  • Jetty Ant Plugin

    Jetty has a sexy new plugin for Ant that has the same features as the Maven plugin. So if you didn’t want to move from Ant to Maven, but you still want fast webapp development, now you can have it!
    The Jetty Maven plugin greatly shortens your development cycle by allowing you to run jetty on your Maven webapp project without first having to assemble it into a fully-formed webapp. Moreover, it’s able to scan the webapp and automatically redeploy it when changes are detected (eg to class files, descriptors, jars etc). You can imagine how convenient that is when you’re using an IDE – you modify the source, the IDE compiles it in the background and your changes are then immediately reflected in the executing container.
    Not everyone, however, is in a position to change to using Maven for building their webapps. Many folks are happy with (or are stuck with) using Ant, but would love to have the advantages of the Maven plugin.
    Well, now they can! The Jetty Ant plugin brings you those same rapid development features.
    Like the Maven plugin, the Ant plugin also directly supports configuration of jetty components like connectors, realms, request logs etc. Similarly, it also supports the use of a jetty.xml file to give you total control of the container environment for your webapp. As you’d expect, you can also specify a jetty-env.xml for doing fine-grained configuration of the JNDI resources.
    Once you’ve done your initial configuration and setup it’s as easy as typing:

    ant jetty.run

    Big thanks to Jakub Pawlowicz and Sabre Holdings for this outstanding contribution to the Jetty project!

  • Jetty supports Annotations for the JSF RI

    Jetty now supports annotations on managed beans with Sun’s JSF RI version 1.2_04.

    For the curious, the magic happens in the Jetty6InjectionProvider class that is distributed in the RI jars.

    However, that’s just an implementation detail. All you need to do is to mark up your jsf beans as usual with annotations (see the annotations supported by jetty, and the jetty/jsf integration will make sure they’re injected and the callbacks called appropriately. Also take a look at how to throw the JSF RI jars into Jetty.

    Big thanks to Ryan Lubke from the JSF RI team who worked very closely with us on implementing this! Ryan has also blogged about the jetty integration.

  • Marc Fluery leaves JBoss/Redhat

    So Marc Fluery has left JBoss/Redhat and thus brings to an end a chapter of the story of professional open source.

    One would have to say it has been a very successful chapter and has shown that OS can produce high quality enterprise infrastructure. As Marc leaves the project (or the professional part of it at least), we should note that the project owes much of it’s great success to the energy, enthusiasm, advocacy and leadership of Marc. Without these, JBoss would not have penetrated the enterprise as it has and nor would there have been the commercial activity around the project that sustains many developers and spin off projects.

    We should applaud Marc that he at least partially delivered on his promise to distribute the rewards of success to the contributors to the project.

    But the problem with this OS fairy tale is that the distribution of reward was simply not fair or balanced. While Marc deserved to be well rewarded for his part in the success of the project and business it sustained, I simple cannot see why his reward was several orders of magnitudes larger than that given to the people that actually wrote the software and implemented the business he inspired. Nor can I see why members of his family who contributed only moderately also received payouts far far far in excess of key developers who committed years of effort.

    As well as building a project and a business, Marc built a personality cult based on ego worship. While this in itself was a great marketing machine (any publicity etc.), it was also used as a mechanism to control dissent within the project and distract from the fact that the egalitarian rhetoric did not match up to the reality of firm control over commercial interests and trademarcs. In the formative years of JBoss group, few dared to question the insanity of “we’ll pay you to fix any bugs and keep the all of the support revenue if there are none – please be available 24×7”. Too many let the “honour” of commit status, access to the “inner circle” and payment by the hour, substitute for real equity or profit share.

    Those that did question, were soon made the target of Marc’s bile and bad mouthing (more Hani than Hani) and received zero or paltry allocations of the developer “frequent flyer” points that would one day turn into Red Hat stock.

    Continued decent would result in ejection or departure from the jboss group cult followed by excommunication from the project, deletion from the contributors lists and being moderated out of the forums and mailing lists. Marc was happy for many to tend the commons, but there was only one shepherd whose flock was allowed to graze.

    Open source is about standing on the shoulders of giants so that greater heights can be reached. But it is also about showing a bit of respect and fair treatment to those shoulders. Marc fluery didn’t just stand on the shoulders, he trampled and kicked heads as well.

    The OS story of JBoss story is about how the many created something for the benefit of all. Unfortunately the business story of JBoss is about how the many were exploited for the benefit of one. It didn’t have to be that way.

  • Hightide Released

    Hightide is a versioned, optimized distro of Jetty, with many J2EE/JavaEE features pre-integrated in a lightweight manner so you can enjoy their benefits but without needing a heavyweight JavaEE Application Server. We’ve also included state-of-the-art, scaleable backend support for Ajax. The idea being to provide a powerful but flexible container for webapp development and deployment. The distro gives you these features already baked in:

    • Servlet 2.5 container (Jetty)
    • JSP2.1 support
    • XA transactions (from Atomikos)
    • JNDI
    • Annotations (coming in the next release)
    • JMS (from ActiveMQ)
    • JDBC (from Derby)
    • JAAS
    • JMX
    • Continuations
    • Hot deployment
    • cometd implementation
    • DWR

    If you prefer to use a different database, XA manager or messaging fabric you can simply swap them in instead.

    You also get a live log viewer accessible from your browser, and integration with JDK logging.

    To help you get started quickly, we’ve included a few Ajax-based webapps that demonstrate the features of Hightide. One of them, the Auction Demo is also available live on the Webtide site if you want a sneak preview.

    Like Jetty, Hightide is open source and uses the Apache 2.0 licence.Via Webtide we are providing full, long term dev and production support for it.

  • Jetty 6.1.0 Release

    The Jetty 6.1.0 release is now available via http://jetty.mortbay.org. It represents both a stabilization of the features already released in 6.0.x, plus a raft of new features. For a full description of
    Jetty 6.1, see http://docs.codehaus.org/display/JETTY/.

    Stabilization

    The core protocol engine of Jetty 6 has been further optimized and refined in 6.1, plus it has been extended to support asynchronous SSL and a future HTTP client API. Compliance testing and exposure on live deployments has allowed many minor and several major issues to be exposed and fixed.

    Deployers

    Web Application Static Deployer

    The WebApp Deployer is for static deployment standard WAR files and webapps with little or no Jetty specific customization.

    See

    http://docs.codehaus.org/display/JETTY/WebAppDeployer

    Context Hot Deployer

    The ContextDeployer may be used to (hot)deploy an arbitrary Context or Web Application with Jetty specific configuration. The ContextDeployer will scan the configuration directory for xml descriptors that define contexts. Any context descriptors found are used to configure and deploy a context and then the descriptor is monitored for changes to redeploy or undeploy the context.
    Arbitrary contexts may be configured deployed including simple static contexts and standard webapplications. The web.xml of a war file may be extended or replaced and additional configuration applied, thus allowing configuration to be customized during deployment without modification to the WAR file itself.

    See:
    http://docs.codehaus.org/display/JETTY/ContextDeployer

    Cometd

    Jetty 6.1 includes a servlet implementation of the bayuex protocol of http://cometd.com from the dojo foundation.

    Cometd is a message bus for Ajax web applications that allows multi channel messaging between client and server – and more importantly – between server and client. The paradigm is publish/subscribe to named channels.

    The Jetty implementation uses continuations and will thus scale to many connected clients. It also supports declarative filters for security and validation of channel content.

    See
    http://docs.codehaus.org/display/JETTY/Cometd

    Servlet Tester

    The jetty infrastructure can be use to test servlets with an embedded server using the ServletTester and HttpTester classes.
    The embedded server uses a special local connector, and thus avoids the need to open sockets in order to test the servlet and is thus ideal for unit testing:

    ServletTester tester=new ServletTester();
    tester.setContextPath("/context");
    tester.addServlet(HelloServlet.class, "/hello/*");
    tester.start();
    HttpTester request = new HttpTester();
    HttpTester response = new HttpTester();
    request.setMethod("GET");
    request.setURI("/context/hello/info");
    response.parse(tester.getResponses(request.generate()));
    assertEquals(200,response.getStatus());
    assertEquals("<h1>Hello Servlet</h1>",
    response.getContent());
    

    See http://docs.codehaus.org/display/JETTY/ServletTester.

    New Connectors

    SSL Engine connector

    A new SSL connector has been added to jetty 6.1 that is based on the javax.net.ssl.SSLEngine class. This allows the asynchronous mechanisms of jetty to be applied to SSL connections, specifically Continuations.

    See http://docs.codehaus.org/display/JETTY/Ssl+Connector+Guide

    AJP13 connector

    Jetty 6.1 now includes an implementation of the apache AJP protocol for forwarding requests from an apache httpd to Jetty. This connector is a significant rewrite from the Jetty 5 connector so more advance IO features can be used.

    See http://docs.codehaus.org/display/JETTY/Configuring+AJP13+Using+mod_jk

    Grizzly connector

    A Grizzly HTTP connector has been added which uses the Grizzly NIO library from Sun’s Glassfish JEE server. This connector provides an integration path into Glassfish server and an alternative HTTP connector.

    See http://docs.codehaus.org/display/JETTY/Grizzly+Connector

    Integrations

    Apache Geronimo

    Jetty 6.1 is integrated with Apache Geronimo. The flexibility of Jetty allows for a very close integration with the core geronimo infrastructure.

    See http://docs.codehaus.org/display/JETTY/Geronimo

    WADI Clustering

    WADI is a clustering system that is integrated with both Jetty 6 standalone and as Jetty 6 within Geronimo.

    See http://wadi.codehaus.org/

    JBoss

    Jetty 6 has been integrated with JBoss 4 and is an alternative webtier that will provide Servlet 2.5 and asynchronous servlets within this popular J2EE server.

    See http://docs.codehaus.org/display/JETTY/JBoss

    GWT

    The Google Widget Toolkit needs some small extentions in order to be able to be used with Jetty Continuations. This has been done to great effect on the aployr.com games sites, with gpokr.com and kdice.com games both being run from a single Jetty server capable of handling many more simultaneous users than the previous dual apache+tomcat configuration.

    See http://docs.codehaus.org/display/JETTY/GWT

    Windows service

    A windows service wrapper module is included in jetty 6.1.

    See http://docs.codehaus.org/display/JETTY/Win32Wrapper

    Works in Progress

    Annotations, Resource Injection and LifeCycle Callbacks

    The release of Jetty 6.1 includes support for web.xml based resource injections and lifecycle callbacks as defined in the 2.5 Servlet Specification.

    Resource injection removes the need for certain servlet-related classes to perform explicit JNDI lookups to obtain resources.
    Instead, a resource from JNDI is automatically injected into
    designated fields and/or methods of the class instance at runtimeby Jetty.

    Lifecycle callbacks allow certain servlet-related class instances
    to nominate a method to be called just before the instance goes
    into service and another to be called just before the instance
    goes out of service.

    This release supports these features when defined in the web.xml
    descriptor. For example:

    <resource-ref>
    <res-ref-name>jdbc/mydatasource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <injection-target>
    <injection-target-class>com.acme.JNDITest</injection-target-class>
    <injection-target-name>myDatasource</injection-target-name>
    </injection-target>
    </resource-ref>
    <post-construct>
    <lifecycle-callback-class>com.acme.JNDITest</lifecycle-callback-class>
    <lifecycle-callback-method>postConstruct</lifecycle-callback-method>
    </post-construct>
    <pre-destroy>
    <lifecycle-callback-class>com.acme.JNDITest</lifecycle-callback-class>
    <lifecycle-callback-method>preDestroy</lifecycle-callback-method>
    </pre-destroy>
    


    Resource injection is supported for env-entry, resource-ref and resource-env-ref
    elements. Both post-construct and pre-destroy callbacks are also supported.
    The 2.5 Servlet Specification also allows for these features to be defined
    directly in the source code of servlet-related classes via java annotations.
    A forthcoming release of Jetty 6.1.x will implement @Resource, @Resources, @PostConstruct,
    @PreDestroy, @DeclaresRoles and @RunAs annotations.

    Client API

    The protocol engines of Jetty have been refactored so that as well as request parsing and response generation, they now support request generation and response parsing. This will allow a HTTP client API to be developed within Jetty to efficiently implement non-blocking proxies.

    Jetty Hightide

    The extensive features of Jetty 6.1 are further enhanced and
    extended in the Jetty Hightide release from Webtide
    Hightide is a versioned and supported distribution of Jetty providing:

    • Jetty 6.1 scalable HTTP server, servlet container and Ajax support, patched with performance enhancements available with a targeted distribution.
    • JettyPlus JNDI framework and JEE services.
    • Access to Webtide’s premium support services.
    • Atomikos XA transaction manager.
    • AMQ with AJAX support configured and integrated into the XA transaction manager.

    See http://www.webtide.com/products.jsp

  • Unit Test Servlets with Jetty

    This rainy weekend, I was inspired by a question from hani about testing servlets. As a result I’ve added a module to Jetty to simply test servlets with an embedded server configured by the ServletTester class. The HTTP requests and responses for testing can be generated and parsed with the
    HttpTest
    class.
    An example of a test harness that uses these classes is ServletTest.

    Setting up the tester

    The ServletTester can configure a single context. Servlets and Filters may be added to the context by class name or class instance. Context attributes, a resource base or a classloader may optionally be set. eg.

    ServletTester tester=new ServletTester();
    tester.setContextPath("/context");
    tester.addServlet("come.acme.TestFilter", "/*");
    tester.addServlet(TestServlet.class, "/servlet/*");
    tester.addServlet(HelloServlet.class, "/hello");
    tester.addServlet("org.mortbay.jetty.servlet.DefaultServlet", "/");
    tester.start();


    Raw HTTP requests and responses.

    The ServletTester takes a string containing requests and
    returns a string containing the corresponding responses (eventually byte arrays will be supported for testing character encoding and binary content). More than one request can be pipelined and multiple responses will be returned if persistent connection conditions are met. eg.

    String requests=
    "GET /context/servlet/info?query=foo HTTP/1.1rn"+
    "Host: testerrn"+
    "rn"+
    "GET /context/hello HTTP/1.1rn"+
    "Host: testerrn"+
    "rn";
    String responses = tester.getResponses(requests);
    String expected=
    "HTTP/1.1 200 OKrn"+
    "Content-Type: text/html; charset=iso-8859-1rn"+
    "Content-Length: 21rn"+
    "rn"+
    "<h1>Test Servlet</h1>" +
    "HTTP/1.1 200 OKrn"+
    "Content-Type: text/html; charset=iso-8859-1rn"+
    "Content-Length: 22rn"+
    "rn"+
    "<h1>Hello Servlet</h1>";
    assertEquals(expected,responses);


    Generated Requests, Parsed Responses

    Dealing with raw HTTP can be a bit verbose and difficult to test non protocol aspects. The
    HttpTest
    class allows for simple generation of requests and parsing of response (it can also parse requests and generate responses). eg.

    HttpTester request = new HttpTester();
    HttpTester response = new HttpTester();
    request.setMethod("GET");
    request.setHeader("Host","tester");
    request.setURI("/context/hello/info");
    request.setVersion("HTTP/1.0");
    response.parse(tester.getResponses(request.generate()));
    assertTrue(response.getMethod()==null);
    assertEquals(200,response.getStatus());
    assertEquals("<h1>Hello Servlet</h1>",response.getContent());



    Once setup, the HttpTester instances may be reused and only the parts that change need to be
    set for subsequent requests. eg.

    request.setURI("/context");
    response.parse(tester.getResponses(request.generate()));
    assertEquals(302,response.getStatus());
    assertEquals("http://tester/context/",response.getHeader("location"));


    Requirements

    This will be in the 6.1.0 release and is currently in 6.1-SNAPSHOT. To use these classes you need the jars for servlet-api, jetty-util, jetty, jetty-servlet-tester.

  • Gaming with GWT and Jetty continuations

    The Google Widget Toolkit allows Ajax applications to be developed in java code using the traditional UI widget paradigm. The toolkit includes support for RPC, but not for comet style Ajax push.
    Online Gaming is an excellent use-case for Ajax and I’ve been working with Ryan Dewsbury of www.aplayr.com to convert his GWT powered games of risk and poker to use Jetty continuations.
    First… play a lot of poker!
    Then the main challenge is to convert the getEvents() RPC call that the aplayr games make for their Comet Ajax Push aspects. The getEvents() is a long poll, in that it waits until there is an event be returned before generating a response.
    This had been implemented with a wait/notify, which works fine but has scalability issues as each player waiting for an event has an outstanding getEvents() request that is consuming a thread and associated resources. It was not possible to have more simultaneous players then there were threads in the thread pool. This is exactly the problem that Jetty continuations have been designed to solve.
    Unfortunately GWT has not made it easy to use continuations within their RPC mechanism. Firstly they catch Throwable, so he Jetty RetryException is caught. Secondly they have made most of the methods on the GWT servlet final, so you cannot fix this by extension.
    Luckily GWT is open source under the apache 2.0 license, so it was possible to do a cut/paste/edit job to fix this. The
    OpenRemoteServiceServlet recently added to Jetty is version of GWTs RemoteServiceServlet without the final methods and a protected method for extending exception handling. We are lobbying Google to make this part of the next release.
    Once the GWT remote service servlet has been opened up, it is trivial to extend it to support Continuations, which has been done in AsyncRemoteServiceServlet.
    Because GWT RPC uses POSTS, the body of the request is consumed when the request is first handled and is not available when the request is retried. To handle this, the parsed contents of the POST are stored as a request attribute so they are available to retried requests without reparsing:

    protected String readPayloadAsUtf8(HttpServletRequest request)
    throws IOException, ServletException
    {
    String payload=(String)request.getAttribute(PAYLOAD);
    if (payload==null)
    {
    payload=super.readPayloadAsUtf8(request);
    request.setAttribute(PAYLOAD,payload);
    }
    return payload;
    }

     
    The exception handling is also extended to allow the continuation RetryException to propagate to the container. This has been done without any hard dependencies on Jetty code:

    protected void handleException( String responsePayload,
    Throwable caught )
    {
    throwIfRetyRequest(caught);
    super.handleException( responsePayload, caught );
    }
    protected void throwIfRetyRequest( Throwable caught )
    {
    if (caught instanceof RuntimeException &&
    "org.mortbay.jetty.RetryRequest"
    .equals(caught.getClass().getName()))
    {
    throw (RuntimeException) caught;
    }
    }

     
    With these extensions, the AsyncRemoteServiceServlet allows
    any GWT RCP method to use continuations to suspend/resume processing. For example below is the Table class used by gpokr where a continuation is used to wait for an event to be available for a player.

    class Table
    {
    Set waiters = new HashSet();
    public Events getEvents( Context c )
    {
    Player p = getPlayer( c );
    // if the player has no events.
    if( p.events.size() == 0 )
    {
    synchronized( this )
    {
    // suspend the continuation waiting for events
    Continuation continuation =
    ContinuationSupport.getContinuation
    (c.getRequest(),this);
    waiters.add(continuation);
    continuation.suspend(30000);
    }
    }
    catch (InterruptedException e)
    {
    log(e);
    }
    }
    return p.events;
    }
    protected void addEvent( Event e )
    {
    // give the event to all players
    Iterator it = players.values().iterator();
    while( it.hasNext() )
    {
    Player p = (Player)it.next();
    player.events.add( event );
    }
    // resume continuations waiting for events
    synchronized( this )
    {
    Iterator iter = waiters.interator();
    while (iter.hasNext())
    ((Continuation)iter.next()).resume();
    waiters.clear();
    }
    }

    With the same style of event loop, the kdice game has been able to run over 200 players and many spectators with only a 100 threads!
    And most importantly, you must remember never to go in with just pocket jacks and a full table. What was I thinking?

  • Jetty and Pitchfork (Spring EJB3)

    Having had a couple of emails on the Jetty lists about using EJB3 with Jetty, I’ve been looking at the various embeddable technologies around.

    Last week I looked at the JBoss Embeddable EJB3 product and got it working in Jetty.

    I briefly also mentioned some work we’re doing with the EasyBeans guys – a blog entry is coming on that soon.

    A couple of people have mentioned Pitchfork to me in the space of a week, so I decided I’d better check it out. Turns out that it is a an EJB3 implementation for deployment with Spring. There’s an InfoQ article on it, describing it as the result of collaboration between Spring committers and some of the BEA Weblogic team.

    Having checked out Christian Dupuis’s blog about using it with Tomcat, I decided to see how hard it would be to use it with Jetty.

    The answer was that it was easy!

    I’ve added a couple of simple Spring classes to the extras/spring module in Jetty to hook up a webapp to Pitchfork’s resource and ejb injection facilities.

    They’re checked in to jetty svn trunk at the moment, so you’ll need to checkout and build jetty to get them. Then:

    1. make a new directory $jetty.home/lib/ext/spring, and copy the $jetty.home/extras/spring/target/jetty-spring-6.1-SNAPSHOT.jar into it
    2. download Pitchfork and copy all of the dist/ and lib/ jars into $jetty.home/lib/ext/spring

    Now you can create yourself a webapp, some ejbs and some beans that reference the ejbs using @EJB injection notation, and deploy it to Jetty!

    I’ve put more detailed instructions on the Jetty wiki, plus a very simple webapp that uses EJB3s as an example to get you started.