Rob, do you have any material on that? We are looking to use GWT and GWT-RPC
as our web frontends.
I don't have any real docs as such - all our work has been purely
"internal". I can describe a little of how we work though:
* We use standard Felix, and the Felix Http Service. Although you
can get more advanced Http handling such as filters etc, we prefer
at present to stick only to the standard OSGi Http Service API
* We've found it easiest to bundle everything into a single
"webui.jar" bundle - which includes:
o our handler "GwtServer" (This is the core plumbing - I'll
talk more about this in a moment)
o the standard GWT structure of ./client, and ./server for
compiled GWT packages e.g.
+ obj/com/mycompany/myapp/client
+ obj/com/mycompany/myapp/server
o the "www" resources that the GWT compiler generates. This is
the most vital stuff - it includes the HTML, generated
Javascript, PNGs, GIFs, CSS. In our case we also build this
to /obj under /resources
+ obj/resources/www
o Our manifest is quite simple - since we have all the GWT
stuff in one bundle, we don't need to export any GWT stuff,
and only need to import packages for our external app
services. This is perhaps not the cleanest separation of
concerns, but it is nice and simple and works for us! We
also embed the appropriate gwt-user.jar as an inner JAR for
our GWT bundle, again, for bigger apps this may not be the
cleanest separation but it keeps it simple. So our generated
manifest looks something like this:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.6.5
Bundle-ClassPath: .,gwt-user.jar
Metadata-Location: metadata.xml
Bundle-Name: OurWebUI
Bundle-ManifestVersion: 2
Bundle-Activator: com.mycompany.myapp.ServiceActivator
Bundle-Description: Our WebUI using GWT
Import-Package: javax.cryp
to, javax.crypto.spec, javax.imageio, javax.servlet,
javax.servlet.ht
tp, javax.xml.parsers, org.apache.felix.servicebinder,
org.apache.log
4j, org.osgi.framework, org.osgi.service.http,
org.supercsv.io, org.s
upercsv.prefs, org.w3c.dom
Bundle-SymbolicName: com.mycompany.myapp
o We don't include any application services in this bundle -
they're external OSGi services wired in as dependencies
using service binder in the normal way (alternatives such as
iPojo would work just as well).
* We use an interceptor class between the standard GWT servlet
handler and our own - to ensure there are no nasties with context
classloaders, that can be a problem with OSGi. Our servlets all
subclass from the interceptor:
public class RpcHandlerServlet
extends RemoteServiceServlet
{
...
public RpcHandlerServlet() { }
/**
* Intercept method to make sure classloader is set before
call is processed
*/
public String processCall(String payload) throws
SerializationException
{
Thread.currentThread().setContextClassLoader(
this.getClass().getClassLoader() );
return super.processCall(payload);
}
...
}
* Now onto the bit that does the work - our "GwtServer". When this
becomes "active" having had it's bindHttp method called, we're
ready to start work. We have a range of GWT-RPC servlets that do
our work - these are standard servlets, that extend the
interceptor class above, and bridge into the OSGi services of our
core app. In the GwtServer we register 2 kinds of aliases
o servlet aliases - these handle the RPC calls e.g.
srvHttp.registerServlet("/MyApp/MyRpcService", rpcService,
new Hashtable(), myContext);
(obviously in real use you'd make aliases configurable)
o at least one resource alias - this is key, it resolves
requests for HTML, CSS, JS, GIF etc etc into the bundle
resources under /resource/www (as mentioned above) e.g.
srvHttp.registerResources("/MyApp", "", new WebAppContext);
o and now the most important part - our WebAppContext must
"resolve" resource requests from the GWT client into the
resources in our bundle e.g.
// just needs to match whatever package base/root you
declare for GWT to use
protected String baseUri = "/com.mycompany.myapp.MyApp";
private class WebUiContext implements HttpContext
{
public boolean handleSecurity(HttpServletRequest
request, HttpServletResponse response)
throws IOException
{
return true;
}
public String getMimeType(String resource)
{
return null;
}
public URL getResource(String name)
{
if (name.equals("/") || name.length() == 0)
{
name = indexPage;
}
//Not sure why we need this - but under
Jetty6/GWT1.5.2 there
//seems to be a direct call with alias still attached
if (name.startsWith(alias + "/"))
{
name = name.substring(alias.length());
}
URL retVal = null;
try
{
retVal =
GwtServlet.class.getClassLoader().getResource("resources/www" +
baseUri + name);
}
catch (Exception ge)
{
app.error("Resource get exception: " + ge + " -
" + name);
}
return retVal;
}
}
* In your GWT XML config - make sure your entry class matches your
baseUri e.g.
<entry-point class="com.mycompany.myapp.client.MyApp" />
I forget why now, but there is an extra ".client" needed as the last
part of the package name which isn't needed in the baseUri for
resolving resources
* Last bit as I recall, is the URL to use in client GWT code for
your RPC entry points
instance = (ClientServiceAsync)
GWT.create(ClientService.class);
ServiceDefTarget target = (ServiceDefTarget) instance;
target.setServiceEntryPoint(GWT.getModuleBaseURL() +
"MyRpcService");
Note that you just need the name of the RPC handler servlet here -
GWT takes care of the root path wiring
That's about it for the general stuff - the rest is just variations on
the above - servlets to wire RPC calls into our back end app, and a few
"fancier" contexts for resource handling (e.g. to make it easy to serve
up JNLP embedded apps)
Have fun - we're very happy how our web app has come out with GWT and Felix!
-- Rob