Thanks Rob, your email was very helpful, we are just starting next week with
some minor implementation on the new architecture, I'll certainly use this
as a reference, thanks for sharing.

On Fri, Dec 19, 2008 at 10:56 AM, Rob Walker <r...@ascert.com> wrote:

>
>
>  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
>
>

Reply via email to