GWT RPC from non-servlet-container (2)
In the second post, I would like to show-off the project structure of a simple GWT application served by pure Restlet (which means not running in a servlet container) Application as a sample and basis of further discussion.
The GWT Client
In order to deploy a GWT application in non-servlet container like Restlet, I can not package the GWT client in a war. I choose to package everything (class files, java sources, gwt compiled js and other static resources) into a single jar. It might be also friend to OSGi environment.
I use gwt-maven plugin as the build tool, which is quite handy in our case. For detail usage of gwt-maven plugin, please check the example. I made some modification in order to create this "special" jar.
<plugin>
<groupId>com.totsp.gwt</groupId>
<artifactId>maven-googlewebtoolkit2-plugin</artifactId>
<version>2.0-beta24</version>
<configuration>
...
<output>${project.build.directory}/classes/_gwt</output>
</configuration>
</plugin>
I changed the output directory of GWT resources, so that they can easily get packaged by maven jar plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classifier>gwt</classifier>
<excludes>
<exclude>_gwt/.gwt-tmp/**</exclude>
</excludes>
</configuration>
</execution>
</executions>
<configuration>
<excludes>
<exclude>_gwt/**</exclude>
</excludes>
</configuration>
</plugin>
Two jars are created, one with classifier "gwt" includes all static resources.
<build>
<resources>
<resource>
<directory>./src/main/java</directory>
</resource>
<resource>
<directory>./src/main/resources</directory>
</resource>
</resources>
...
</build>
This is a small trick to package java sources into GWT jar.
The Restlet Application
(Sorry for using Scala as the example language, but hopefully you will see how Scala can ease the development)At current moment, there is no standard way to deploy a web application using Restlet. Basically in Restlet, you expose dynamic part as a Resource, and serve static things using Directory (see example on Restlet site).
I create a GwtApp trait for serving GWT client an Application scope.
The small "abstract override" trick creates a kind of AOP around aspect over
trait GwtApp extends Application{
val gwtDir = new Directory(null, "clap://class/_gwt/")
abstract override def createRoot():Restlet={
gwtDir.setContext(getContext)
super.createRoot match{
case root:Router=>
root.attach("/_gwt", gwtDir);root
case r@_=>
val root = new Router
root.attachDefault(r)
root.attach("/_gwt",gwtDir)
root
}
}
}
createRoot
method, see this. So I can just mixin this trait into my application without any change.
class App extends Application with GwtApp{
override def createRoot():Restlet={
val r = // ... get Root as a Router
r.attach("/test", classOf[TestResource])
//attach the main view
r.attach("/main", new Restlet(getContext){
override def handle(req:Request, resp:Response){
val r = new InputRepresentation(
getClass.getResourceAsStream("/host.html"),
MediaType.TEXT_HTML)
resp.setEntity(r)
}
})
r
}
}
Two endpoints are exposed by this application.
/main
- return the host page of above GWT client, the src location of GWT bootstrap js file is/_gwt/gr.demo.App/gr.demo.App.nocache.js
/test
- a very simple restful service acceptingtext/html
request and serving back atext/plain
representation, see below;
class TestResource(ctx:Context, req:Request, resp:Response)
extends Resource(ctx,req,resp){
getVariants.add(new Variant(MediaType.TEXT_HTML))
override def represent(v:Variant)={
new StringRepresentation("Helo@"+new Date, MediaType.TEXT_PLAIN);
}
}
After you package all of above into a Component;
val com = new Component
Array(HTTP, FILE, CLAP).foreach(x=>com.getClients.add(x))
com.getServers.add(HTTP, 8080)
com.getDefaultHost.attachDefault(new App)
You get a client served by pure Restlet application.
So next post of this series will be the prototype of serving GWT RPC using Restlet, hopeful it will be cool.
0 comments:
Post a Comment