Here is a solution to use Restlet (http://www.restlet.org/) with Grizzly (https://grizzly.dev.java.net/) and a Comet async Servlet.
The App.java
is starting a standalone Grizzly Web Server. It is hosting an async Servlet and the Restlet Engine. The Restlet Engine is used as a servlet.
Download Code: AsyncRestlet
App.java
package asyncrestlet; import com.sun.grizzly.comet.CometAsyncFilter; import com.sun.grizzly.http.embed.GrizzlyWebServer; import com.sun.grizzly.http.servlet.ServletAdapter; import org.restlet.ext.servlet.ServerServlet; /** * The App * * Demonstration to use the Restlet framework and an async servlet. * The async servlet uses the comet package. * * Starts grizzly standalone servlet container with restlet and comet servlet. * * * Run server: * * mvn -Dexec.classpathScope=runtime -Dexec.args="-classpath %classpath asyncrestlet.App" -Dexec.executable=java exec:exec * * To test: * * (wget -O - -q "http://localhost:8181/async" &); echo "async GET started"; sleep 2; wget -O - -q "http://localhost:8181/async" * * wget -O - -q "http://localhost:8181/restlet/therestlet" * */ public class App { public static void main(String[] args) throws Exception { // static content is linked from here GrizzlyWebServer gws = new GrizzlyWebServer(8181, "no static content"); // add the async filter for comet functionality gws.addAsyncFilter(new CometAsyncFilter()); // Adding async servlet ServletAdapter simpleServletAdapter = new ServletAdapter(); simpleServletAdapter.setContextPath("/async"); simpleServletAdapter.setServletInstance(new AsyncServlet()); // register above defined adapters gws.addGrizzlyAdapter(simpleServletAdapter, new String[]{"/async"}); // Adding restlet servlet ServletAdapter restletServletAdapter = new ServletAdapter(); restletServletAdapter.setContextPath("/restlet"); // this is the magic restlet servlet restletServletAdapter.setServletInstance(new ServerServlet()); // let the restlet servlet know which appplication to start restletServletAdapter.addContextParameter("org.restlet.application", "asyncrestlet.RestletApplication"); // register above defined adapters gws.addGrizzlyAdapter(restletServletAdapter, new String[]{"/restlet"}); // let Grizzly run gws.start(); System.out.println("to test async:\n\n (wget -O - -q \"http://localhost:8181/async\" &); echo \"async GET started\"; sleep 2; wget -O - -q \"http://localhost:8181/async\"\n\n"); System.out.println("to test restlet:\n\n wget -O - -q \"http://localhost:8181/restlet/therestlet\"\n\n"); } }
AsyncServlet.java
package asyncrestlet; import com.sun.grizzly.comet.CometContext; import com.sun.grizzly.comet.CometEngine; import com.sun.grizzly.comet.CometEvent; import com.sun.grizzly.comet.CometHandler; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * AsyncServlet * * uses comet for async http * * every GET waits 5 seconds. With another GET the wait can be interrupted * */ public class AsyncServlet extends HttpServlet { private class CounterHandler implements CometHandler<HttpServletResponse> { private HttpServletResponse response; @Override public void onInitialize(CometEvent event) throws IOException { } @Override public void onInterrupt(CometEvent event) throws IOException { PrintWriter writer = response.getWriter(); writer.write("timeout from async\n"); writer.flush(); removeThisFromContext(); } @Override public void onTerminate(CometEvent event) throws IOException { removeThisFromContext(); } @Override public void attach(HttpServletResponse attachment) { this.response = attachment; } private void removeThisFromContext() throws IOException { response.getWriter().close(); CometContext context = CometEngine.getEngine().getCometContext(contextPath); context.removeCometHandler(this); } @Override public void onEvent(CometEvent event) throws IOException { if (CometEvent.NOTIFY == event.getType()) { PrintWriter writer = response.getWriter(); writer.write("hello from async\n"); writer.flush(); event.getCometContext().resumeCometHandler(this); } } } private static final long serialVersionUID = 1L; private String contextPath; @Override public void init(ServletConfig config) throws ServletException { super.init(config); contextPath = config.getServletContext().getContextPath() + "/async"; CometEngine cometEngine = CometEngine.getEngine(); CometContext context = cometEngine.register(contextPath); context.setExpirationDelay(5 * 1000); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { CounterHandler handler = new CounterHandler(); handler.attach(res); CometEngine engine = CometEngine.getEngine(); CometContext context = engine.getCometContext(contextPath); context.notify(null); context.addCometHandler(handler); } }
RestletApplication.java
package asyncrestlet; import org.restlet.Application; import org.restlet.Restlet; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; import org.restlet.routing.Router; /* * RestletApplication * * The restlet application */ public class RestletApplication extends Application { /** * Creates a root Restlet that will receive all incoming calls. */ @Override public synchronized Restlet createInboundRoot() { // Create a router Restlet that routes each call to a // new instance of HelloWorldResource. Router router = new Router(getContext()); // Defines only one route router.attach("/therestlet", RestletResource.class); return router; } }
RestletResource.java
package asyncrestlet; import org.restlet.resource.Get; import org.restlet.resource.ServerResource; public class RestletResource extends ServerResource { @Get public String represent() { return "hello from restlet\n"; } }
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>AsyncRestlet</groupId> <artifactId>AsyncRestlet</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>AsyncRestlet</name> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>maven-restlet</id> <name>Maven Restlet Repository</name> <url>http://maven.restlet.org</url> </repository> <repository> <id>JavaNet</id> <name>Maven JavaNet Repository</name> <url>http://download.java.net/maven/2/</url> </repository> </repositories> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.7</version> <scope>test</scope> </dependency> <dependency> <groupId>com.sun.grizzly</groupId> <artifactId>grizzly-comet</artifactId> <version>1.9.18b</version> </dependency> <dependency> <groupId>com.sun.grizzly</groupId> <artifactId>grizzly-servlet-webserver</artifactId> <version>1.9.18b</version> </dependency> <dependency> <groupId>org.restlet.jee</groupId> <artifactId>org.restlet</artifactId> <version>2.0-M7</version> <exclusions> <exclusion> <artifactId>org.osgi.core</artifactId> <groupId>org.osgi</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.restlet.jee</groupId> <artifactId>org.restlet.ext.servlet</artifactId> <version>2.0-M7</version> <type>jar</type> </dependency> </dependencies> </project>
Resources:
http://blogs.sun.com/msreddy/entry/how_to_make_grizzly_comet
http://www.javaworld.com/javaworld/jw-03-2008/jw-03-asynchhttp.html?page=6
http://blogs.sun.com/japod/entry/jersey_aplication_sharing_grizzly_with
Servlet Communication:
http://docstore.mik.ua/orelly/java-ent/servlet/ch11_03.htm