samedi 27 novembre 2010

GraniteDS Maven archetypes 1.0 RC1 released

We have noticed from a long time that starting a new project with GraniteDS and the usual Java frameworks is not easy enough. We have tried to simplify the configuration as much as possible by allowing to configure GraniteDS directly in the Spring and Seam configuration files but yet there are many steps and caveeats that can take lots of time when setting up a project. It is even more painful when you add the setup of the build system with Ant or Maven.

Fortunately Maven provides a handy mechanism to bootstrap new projects in the form of archetypes. Along with the release of GraniteDS 2.2, we have also released a set of 4 archetypes for common use cases of GraniteDS :
  • graniteds-spring-jpa-hibernate: Flex 4 + Spring 3 + Hibernate/JPA + GraniteDS with standard RemoteObject API
  • graniteds-tide-spring-jpa-hibernate: Flex 4 + Spring 3 + Hibernate/JPA + GraniteDS with Tide API
  • graniteds-tide-seam-jpa-hibernate: Flex 4 + Seam 2.2 + Hibernate/JPA + GraniteDS with Tide API
  • graniteds-tide-cdi-jpa: Flex 4 + CDI/Weld 1.0 + JPA + GraniteDS with Tide API
It is recommended to use Maven 3 but Maven 2.2 should also work. You can run the archetypes from the command line :
mvn archetype:generate
-DarchetypeGroupId=org.graniteds.archetypes
-DarchetypeArtifactId=graniteds-tide-spring-jpa-hibernate
-DarchetypeVersion=1.0.0.RC1
-DgroupId=com.myapp
-DartifactId=example1 -Dversion=1.0-SNAPSHOT
This will create of project named example1 that you can directly build and run with maven :
cd example1
mvn install
cd webapp
mvn jetty:run-war
Then browse http://localhost:8080/example1/example1.swf. The generated project is a multimodule application skeleton with a Java module, a Flex module and a Web module. It includes basic security, service remoting and data synchronization. The default security configuration includes two hardcoded users: admin/admin and user/user.

It is a good starting point to build your own application, after removing the very few example parts. The most interesting thing in these archetypes is that the build poms are automatically created and that they reference selected versions of each framework (Flex, Spring, Seam, Hibernate...) and of build tools (Flexmojos, Jetty plugin...) that work together correctly.

Spring and Seam archetypes are built to be run inside Jetty (for example with the Maven Jetty plugin as shown before). The CDI/Weld example is built to be run inside GlassFish v3.0.1+ and should also work in JBoss 6 M4 (but not later as next versions include the newer and incompatible Weld 1.1). By default it can be run in embedded GlassFish with :
cd example1
mvn install
cd webapp
mvn embedded-glassfish:run
If you don't want to run inside an embedded container but in Tomcat or another container, and still want to use real-time messaging, you will have to change the Gravity servlet implementation in the web.xml file (implementation class names for Tomcat and JBoss 5+ are in comment in the generated web.xml). Then build a war to be deployed in any application server with :
cd webapp
mvn war:war
This is not a final release of these archetypes but they are already usable. They mostly miss the necessary Maven stuff to run unit tests for Flex and Java projects.

As always don't hesitate to give your feedback.

jeudi 25 novembre 2010

Upgrading from GraniteDS 2.1 to GraniteDS 2.2

GraniteDS 2.2 GA has just been released. There have been a few minor changes in APIs and configurations that require some work when upgrading from GDS 2.1 to GDS 2.2 :

API for PagedQuery

PagedQuery now supports sorting on multiple fields, so the API for server-side components has been changed accordingly and expects arrays for order and desc.
public Map find(Map filter, int first, int max, String[] order, boolean[] desc) {
...
}

Configuration property of server-side validator

The property name in services-config.xml has changed from validator-class-name to validatorClassName for consistency with other properties :
<destination id="seam">
<properties>
<validator-class-name>org.granite.tide.hibernate.HibernateValidator</validator-class-name>
</properties>
</destination>
With Spring, it's also possible to define a validator-name that is the name of a bean that implements org.granite.tide.validators.EntityValidator, the default name expected being "tideValidator".
<bean id="tideValidator" class="com.myapp.MyValidator"/>

mercredi 6 octobre 2010

Presentation of GraniteDS at 360|Flex DC

Franck and I were at the 360|Flex DC conference in September to give a presentation about GraniteDS. It was a very interesting time for us, as it was our first talk in the US and our first talk in a pure Flash/Flex conference. We met nice people there and it was a refreshing change to attend to sessions made by designers about user experience, visual effects and gaming instead of our usual boring enterprise Java stuff. Thanks again to John & Nicole for inviting us.

Our presentation was partly slides and partly demo code and some people asked if we could publish the demo application. After a bit of polishing, it is now available for download. There is an ear that can be deployed in a vanilla JBoss 4.2.3, and the eclipse project with the complete source code and configuration here.

Note that you will need two things in JBoss to run the example :
- Install APR (Apache Portable Runtime): download and install it from here, see install doc here.
- Comment out the "CommonHeadersFilter" section in jboss-4.2.3.GA/server/default/deploy/jboss-web.deployer/conf/web.xml:
<!--
<filter>
<filter-name>CommonHeadersFilter</filter-name>
<filter-class>org.jboss.web.tomcat.filters.ReplyHeaderFilter</filter-class>
<init-param>
<param-name>X-Powered-By</param-name>
<param-value>Servlet 2.4; JBoss-4.2.3.GA [...]</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>CommonHeadersFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
-->

Once deployed, it can be accessed from http://localhost:8080/gds-onlinebet/Onlinebet.html.

This demo will probably be included in the distribution examples in the next release of GraniteDS.

Finally if you are interested by the slides, they are available on SlideShare.

As always, don't hesitate to give your feedback.

mercredi 15 septembre 2010

At least you don't need a psychiatrist ;-)

WebORB marketing buzz is somewhere beyond the final frontier: to get to GraniteDS into their decision trees, you first have to go with Java, which doesn't even seem to be the most recommended option according to these guys. Then, you'll have to follow this frustrating path:
Complete messaging? No.
Complete data management? No
Complete code generation? No.
A psychiatrist? No. (if you happen to choose Yes here, you get LCDS ;-)
Scale beyond one server? Yes.
J2EE-centric? Yes.
Here you are: GraniteDS.
So, after refusing all the good things, you, as a GraniteDS user, avoid at least the cost of a therapy!

But the most funny thing is at the end of their post:
We respectfully request that the developers of the other integration servers mentioned herein join us (...)
You may guess that William and I are of course seriously studying this unexpected opportunity.

mardi 10 août 2010

Reflection API, Big Numbers Support and Validation Framework (JSR-303-like)

Starting with GraniteDS 2.2, three ActionScript3 new features are available:
  • A reflection API, that greatly simplifies ActionScript3 class introspection;
  • Long, BigInteger, BigDecimal implementations in ActionScript3, with custom serialization options between Java and Flex;
  • A Flex validation framework, based on the "Bean Validation" specification (JSR-303), with code generation tools support in order to replicate your Java entity beans constraint annotations in your ActionScript3 model.
The documentation for these three new features is available as a preview here, here and here (the links will change to here, here and here later, when the final version will be out).

mercredi 4 août 2010

GraniteDS and GlassFish v3

It has been possible to run GraniteDS on GlassFish v3 since the version 2.0, but the configuration is not very well documented and all the example applications (except for CDI) run by default on JBoss and Tomcat.

It's a bit shameful because GlassFish v3 is currently the only stable JEE6 compliant server and provides many features that are well supported by GraniteDS such as JPA 2 and Bean Validation.

First I'm going to show how to run the examples on GlassFish, then I will give more details on the configuration so you will be able to modify the examples to run on GF.

Running the examples


Once you have unzipped the distribution, you will find an examples folder containing various projects. For now only the graniteds_tide_ejb3, graniteds_tide_cdi, graniteds_tide_spring and graniteds_chat provide out-of-the-box configurations for GlassFish.

First setup your environment (Flex SDK and GlassFish home folders) in examples/env.properties :
FLEX_HOME=E:/Dev/flex_sdk_3_5
FLEX_TASKS_JAR=${FLEX_HOME}/ant/lib/flexTasks.jar

SERVER_HOME=E:/Dev/glassfishv301/glassfish
SERVER_HOME_DEPLOY=${SERVER_HOME}/domains/domain1/autodeploy

Then modify the build.xml file in the example project, by commenting the default JBoss section and uncommenting the GlassFish v3 section :
<!-- Default configuration: exploded EAR for JBoss
<property name="exploded.ear.packaging" value="yes"/>
<property name="gds-hibernate.lib" value="yes"/>
-->

<!-- Alternative configuration for GlassFish V3 with EclipseLink using JPA API
-->
<property name="war.packaging" value="yes"/>
<property name="resources.dir" value="resources_glassfishv3"/>
<property name="gds-eclipselink.lib" value="yes"/>

After that, just run "ant deploy" from the command line in the project folder and the example will be built and deployed to the GlassFish server.
Then start the GF default database with "asadmin start-database" and the server with "asadmin start-domain domain1", and browse http://localhost:8080/graniteds_tide_ejb3.

The other Tide examples are similar, the necessary configuration files are in the resources_glassfishv3 folder of the examples projects. The chat example is a bit different, you just have to replace the web.xml by the provided servlet3-web.xml and deploy the example with "ant deploy".

The non-Tide examples should be relatively easy to modify as they don't provide as many features. Probably the only things to change will be :
  • Adapt the JPA persistence.xml for EclipseLink

  • Change the security service in granite-config.xml to GlassFishV3SecurityService

  • Change the EJB3 lookup String to java:global/graniteds_ejb3/{capitalized.destination.id}ServiceBean
.
Now let's see the necessary configuration in details.

Full setup with Tide, simplified configuration


Before configuring anything, we first have to add the necessary GraniteDS libraries in WEB-INF/lib :
granite.jar : core library
granite-eclipselink.jar : integration with EclipseLink JPA provider
granite-cdi.jar or granite-spring.jar or granite-seam.jar : integration with various frameworks. This is not needed for EJB3 support, it's already built in the core library.

Now let's have a look at what's in the configuration files, for example in the EJB example (note that contrary to JBoss which is not JEE6 compliant, the examples are deployed as war packages and not ear packages) :

WEB-INF/web.xml : It's the standard configuration for JEE6 web archives, notice that it only contains the definition of the security roles, and the persistence unit reference. Thanks to the new web.xml modularization capabilities and new APIs in Servlet 3, GraniteDS can register automatically its servlets and filters.
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>

<login-config>
<auth-method>BASIC</auth-method>
</login-config>

<security-role>
<role-name>user</role-name>
</security-role>
<security-role>
<role-name>admin</role-name>
</security-role>

</web-app>

GlassFish requires an additional sun-web.xml to define the security roles mapping. Don't forget to create users with roles user or admin in the administration console, otherwise you won't be able to log in the example application.

WEB-INF/classes/META-INF/persistence.xml : Nothing special here, it's a basic JPA persistence unit using the default database and the built-in EclipseLink provider.
<persistence
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">

<persistence-unit name="ejb-pu">
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
</properties>
</persistence-unit>
</persistence>

Note that for now there is absolutely nothing concerning GraniteDS, we have just setup a basic JEE6 application. The configuration for GraniteDS consists in two files. First an empty WEB-INF/classes/META-INF/services-config.properties to indicate to the GDS scanner that it should scan for annotated EJB3 in WEB-INF/classes (note this file is only necessary when using EJB3). Then a configuration class annotated with @FlexFilter that will tell GraniteDS to use automatic configuration.
@FlexFilter(
tide=true,
type="ejb",
factoryClass=EjbServiceFactory.class,
ejbLookup="java:global/graniteds_tide_ejb3/{capitalized.component.name}Bean"
entityManagerFactoryJndiName="java:comp/env/ejb-pu",
tideInterfaces={ EjbIdentity.class }
)
public class GraniteConfig {

@MessagingDestination(noLocal=true, sessionSelector=true)
AbstractMessagingDestination addressBookTopic;

}

GraniteDS is registered as a Servlet 3 initializer class that is triggered by the @FlexFilter annotation. The configuration itself is defined by the annotation parameters. The fields annotated with @MessagingDestination define messaging destinations with the same name than the field name.

This defines the simplified configuration for the application. It is however possible to override all this with the 'standard' GraniteDS configuration files.

Full setup with Tide, detailed configuration


Basically there are 3 configuration files :

WEB-INF/web.xml : defines the GDS listeners and servlets
<!-- Granite config context listener -->
<listener>
<listener-class>org.granite.config.GraniteConfigListener</listener-class>
</listener>

<filter>
<filter-name>AMFMessageFilter</filter-name>
<filter-class>org.granite.messaging.webapp.AMFMessageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AMFMessageFilter</filter-name>
<url-pattern>/graniteamf/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>AMFMessageServlet</servlet-name>
<servlet-class>org.granite.messaging.webapp.AMFMessageServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AMFMessageServlet</servlet-name>
<url-pattern>/graniteamf/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>GravityServlet</servlet-name>
<servlet-class>org.granite.gravity.servlet3.GravityAsyncServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>GravityServlet</servlet-name>
<url-pattern>/gravityamf/*</url-pattern>
</servlet-mapping

This defines exactly the same thing as the simplified configuration, and there is rarely any good reason to use a different url mapping.

Next is the more interesting WEB-INF/flex/services-config.xml. It is similar to the equivalent Flex Remoting / BlazeDS / LCDS configuration.
<services-config>

<!--
! Declares channels.
!-->
<channels>
<channel-definition id="graniteamf" class="mx.messaging.channels.AMFChannel">
<endpoint
uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>

<channel-definition id="gravityamf" class="org.granite.gravity.channels.GravityChannel">
<endpoint
uri="http://{server.name}:{server.port}/{context.root}/gravityamf/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>

<!--
! Declares ejbFactory service factory.
!-->
<factories>
<factory id="tideEjbFactory" class="org.granite.tide.ejb.EjbServiceFactory">
<properties>
<lookup>java:global/graniteds_tide_ejb3/{capitalized.component.name}Bean</lookup>
</properties>
</factory>
</factories>

<!--
! Declares Flex services. This configuration uses automated destinations
! discovery: see test.granite.ejb3.service.PersonServiceBean.java (the
! @RemoteDestination(id="person", securityRoles={"user","admin"}) annotation)
! and granite-config.xml (the scan="true" attribute). There is no need to
! set the factory: since only one factory is configured, it will be used by
! default.
!
! See also Persons.mxml for the RemoteObject configuration.
!-->
<services>
<service id="granite-service"
class="flex.messaging.services.RemotingService"
messageTypes="flex.messaging.messages.RemotingMessage">
<!--
! Use "tideEjbFactory" and "graniteamf" for "ejb" destination (see below).
!-->
<destination id="ejb">
<channels>
<channel ref="graniteamf"/>
</channels>
<properties>
<factory>tideEjbFactory</factory>
<entity-manager-factory-jndi-name>java:/DefaultEMF</entity-manager-factory-jndi-name>
</properties>
</destination>
</service>

<service id="gravity-service"
class="flex.messaging.services.MessagingService"
messageTypes="flex.messaging.messages.AsyncMessage">
<adapters>
<adapter-definition id="simple" class="org.granite.gravity.adapters.SimpleServiceAdapter"/>
</adapters>

<destination id="addressBookTopic">
<properties>
<no-local>true</no-local>
<session-selector>true</session-selector>
</properties>
<channels>
<channel ref="gravityamf"/>
</channels>
<adapter ref="simple"/>
</destination>
</service>
</services>

</services-config>

First are the channel definitions. Here we have one AMF remoting channel and one Gravity (comet-style messaging) channel. Of course the endpoint URIs should match the servlet mappings what we specified in web.xml.

Then we find the factory definitions. In this example we define an EJB3 service factory that will route AMF remoting request to the corresponding beans. This factory requires one specific property, the JNDI lookup string. Other factories could require different properties.

Lastly we have the more interesting service definitions. Here we define one remoting service with the Tide EJB destination mapped to the AMF channel and the EJB service factory. Then we define a messaging service with a simple messaging destination. As before this is exactly the same configuration than was defined with the simplified configuration. These defaults are suitable for most usages, you will very rarely need to change something here. The only things that you will eventually have to define here are messaging destinations (but you can also define them with the simplified configuration). Remoting destinations are automatically discovered by the GraniteDS class scanner.

The last configuration file is WEB-INF/granite/granite-config.xml. It contains all the GraniteDS specific internal configuration parameters (thread pool parameters, externalizers, converters...). You can refer to the documentation to get details on these parameters.

That's all for the basic stuff. As you have noticed, there are not many specific parameters for GlassFish, except maybe the EJB lookup string, and the Gravity Servlet 3 servlet. Let's see now how to integrate GraniteDS with the various pieces of JEE6 features :

Integration with container security


The simplified configuration auto-detects the container and registers the correct security integration service. You can also define it manually in granite-config.xml :
<granite-config scan="true">
<security type="org.granite.messaging.service.security.GlassFishV3SecurityService"/>
</granite-config>

This integration service allows to use container security to authenticate and authorize Flex clients. It also allows to propagate the security context to other server components.

Integration with EclipseLink JPA provider


GraniteDS is able to serialize correctly EclipseLink detached entities. When using the default configuration with scanning enabled, adding the granite-eclipselink.jar is enough to provide this support, otherwise you can manually add the externalizer and class getter configuration in granite-config.xml :
<class-getter type="org.granite.eclipselink.EclipseLinkClassGetter"/>

<externalizers>
<externalizer type="org.granite.eclipselink.EclipseLinkExternalizer">
<include annotated-with="javax.persistence.Entity"/>
</externalizer>
</externalizers>

When using the Tide framework, Tide needs to have access to an EntityManager to support transparent lazy loading. You can define it in services-config.xml in the property entity-manager-factory-jndi-name of the Tide destination :
<destination id="ejb">
<channels>
<channel ref="graniteamf"/>
</channels>
<properties>
<factory>tideEjbFactory</factory>
<entity-manager-factory-jndi-name>java:comp/env/ejb-pu</entity-manager-factory-jndi-name>
</properties>
</destination>

You can also define this in the simplified configuration :
@FlexFilter(
tide=true,
type="ejb",
factoryClass=EjbServiceFactory.class,
entityManagerFactoryJndiName="java:comp/env/ejb-pu",
tideInterfaces={EjbIdentity.class}
)
public class GraniteConfig {
}

As this is a relative JNDI name, you also have to define the persistence-unit-ref in web.xml :
<persistence-unit-ref>
<persistence-unit-ref-name>ejb-pu</persistence-unit-ref-name>
</persistence-unit-ref>

Alternatively you can use the entity manager JNDI name. It's maybe better because it lets the container manage the persistence context.
<destination id="ejb">
<channels>
<channel ref="graniteamf"/>
</channels>
<properties>
<factory>tideEjbFactory</factory>
<entity-manager-jndi-name>java:comp/env/ejb-pc</entity-manager-jndi-name>
</properties>
</destination>

Or
@FlexFilter(
tide=true,
type="ejb",
factoryClass=EjbServiceFactory.class,
entityManagerJndiName="java:comp/env/ejb-pc",
tideInterfaces={EjbIdentity.class}
)
public class GraniteConfig {
}

And
<persistence-context-ref>
<persistence-context-ref-name>ejb-pc</persistence-context-ref-name>
<persistence-unit-name>ejb-pu</persistence-unit-name>
</persistence-context-ref>

Integration with Bean Validation


The integration mostly consists in correct exception translation of validation errors to standardized client-side errors, and of support of remote validation of input fields with the TideInputValidator Flex component. Note that it is supported only when using the Tide service factory.
First you need to add the granite-beanvalidation.jar library in WEB-INF/lib.
If you disable the automatic scanning, you have to register the exception converter manually in granite-config.xml :
<exception-converters>
<exception-converter>org.granite.tide.validation.BeanValidationExceptionConverter</exception-converter>
<exception-converters>

For remote validation, you have to define the validator class name in the destination properties :
<destination id="ejb">
<channels>
<channel ref="graniteamf"/>
</channels>
<properties>
<factory>tideEjbFactory</factory>
<entity-manager-jndi-name>java:comp/env/ejb-pc</entity-manager-jndi-name>
<validatorClassName>org.granite.tide.validation.BeanValidation</validatorClassName>
</properties>
</destination>

Note that this will not be necessary from GraniteDS 2.2.0.RC1 as this will be the default when bean validation libraries are available. Also the property name will be changed to validator-class-name for consistency with other property names.

I've probably not covered all questions about GlassFish v3 support in GraniteDS, so don't hesitate to post comments if some things are still unclear.

mardi 3 août 2010

GraniteDS and the current state of Servlet 3

GraniteDS, and in particular the Gravity comet-like push greatly benefit from the asynchronous capabilities of the servlet containers to get a much better scalability than traditional synchronous servlets. It allows the server to handle long-polling http requests without blocking threads unnecessarily: basically long-polling http requests do nothing most of the time and wait for the server to have something to send.

Asynchronous processing has been supported for a long time on the most popular containers (Tomcat, Jetty, JBossWeb) but the implementations depend on the container-specific APIs (CometProcessor for Tomcat, Continuations for Jetty, HttpEvent for JBossWeb). The Servlet 3 API, approved almost a year ago as part of JEE6, is supposed to bring standardisation to this domain. It's very interesting for Gravity because it means that we could have only one implementation for all containers. Unfortunately the only stable container currently supporting Servlet 3 is GlassFish v3 which is the reference implementation, thus we built our experimental support for Servlet 3 in GraniteDS 2.0 on this server.

There are now a few near-stable containers supporting Servlet 3 and we have made some improvements to our servlet 3 support, so it's interesting to have a look now at how GraniteDS behaves on the following containers :
  • GlassFish v3.0.1 (download here)

  • Tomcat 7 beta (download here)

  • Jetty 8 M1 (download here)

  • JBoss 6 M4 (download here)


Gravity can be configured for Servlet 3 with the following snippet in web.xml :
<servlet>
<servlet-name>GravityServlet</servlet-name>
<servlet-class>org.granite.gravity.servlet3.GravityAsyncServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GravityServlet</servlet-name>
<url-mapping>/gravityamf/*</url-mapping>
</servlet-mapping>


Thanks to the new servlet 3 APIs, it's also possible to simply add a marker class to configure GraniteDS :
@FlexFilter
public class GraniteConfig {
}

In this case, there is nothing to configure in web.xml, and the Gravity servlet will be mapped on /gravityamf/* by default.

The good news is that the GraniteDS examples (in particular the chat) all work correctly on these containers with this Servlet 3 support. But of course there are a few issues that I'm going to detail.

Tomcat 7 beta

Even if it was functioning relatively correctly, the CometProcessor API in Tomcat 6 was sort of a hack and had lots of issues. It seems to be better with Servlet 3 on Tomcat 7 but there are still problems.
Tomcat requires either a NIO connector or the APR native library to handle asynchronous servlets, and these connectors have quite different behaviours with GDS 2.1.0.GA. None seems to lose messages or drop requests though, but APR triggers lots of strange NullPointerExceptions. We do not know yet if the problem comes from Tomcat or from Gravity (GDS-703).

JBoss 6 M4

Support of Servlet 3 in JBossWeb has been added since JBoss 6 M2. It works much better that Tomcat 7, but there are occasional IllegalStateExceptions that maybe come from Gravity. Notice that you will also need a NIO connector or the APR native library (JBossWeb is more or less a modified Tomcat).
Also note that due to this bug, support for asynchronous servlets will not work with CDI.

Jetty 8 M1

As always with Jetty, everything seems to work just fine without too much hassle. Just download, install and start. We have not found any particular issue yet with GDS 2.1.0.GA.

GlassFish v3.0.1

No big issue detected until now. We have not conducted extensive testing, but Servlet 3 support can be considered stable. Of course for production use, you should run your own stress tests depending on your application.

It's nice to see JEE6 taking shape in the open source space and hopefully all these containers will be released before the end of the year. Support in WebLogic or WebSphere seems a lot more distant, but who knows.