Running JAXRS services in the Cloud in 5 minutes… or less!


Here is a really simple post about how to push REST services in the Cloud. Nothing really technical nor advanced, just some notes and sample using amazing tools CXF + Heroku…

Last time I was speaking about putting some SOAP Web services in the Cloud with Heroku, this time it is the same with REST services… The approach is exactly the same but it uses the JAXRS implementation provided by Apache CXF.

The REST service illustrates how to annotate the Java interface to returns JSON-based responses like:

Once implemented and configured (it uses Spring with the famous WEB-INF/beans.xml file), pushing it to Heroku is as simple as last time, nothing new here. Heroku needs a Procfile to start, and the Maven-based project is configured to generate what the Procfile needs: A shell file which launches a Jetty instance running Apache CXF and all the REST stuff.

The code is located at https://github.com/chamerling/heroku-cxf-jaxrs. You can run it locally to test before pushing to heroku:

  • mvn install
  • sh target/bin/webapp

Pushing your Web services in the Cloud in 5 minutes…


… or less! Heroku is defined as a « Cloud application platform ». I just want to redefine it to « Awesome Cloud application Platform ». So, this awesome platform provides a way to host and scale your application in the Cloud really easily with 3 or 4 commands…

Since I am currently working on my talk at #OW2Con 2011 (coming later this week) dealing with BPM, Services and the Cloud, I wanted to host some Web services on several places. I never had time to test Heroku but I just took this precious time today. After looking some examples, I created a Maven project template (no I do not have time to create an archetype, maybe there is one somewhere) which uses Jetty and Apache CXF to expose JAXWS annotated classes as Web services. So now, using heroku to freely expose your services is easy as:

  1.  Sign up to heroku
  2. Download the heroku client for your platform
  3. Clone/Fork the repository at https://github.com/chamerling/heroku-cxf-jaxws
  4. Add your own services
  5. Login to heroku ‘heroku auth:login
  6. Create the app on heroku ‘heroku create -s cedar
  7. Push your services to heroku ‘git push heroku master‘. There is a git hook somewhere which just automatically compile and start your application after you pushed it.
  8. Open your CXF services summary page ‘heroku open’
The default application name is some random one, you can rename it by using the ‘heroku rename yournewname‘ but in the current case I had an issue on the generated Web service endpoint name. So I suggest restarting your app after renaming (have a look to the ‘heroku ps‘ command).
That’s all, that’s quick!

Injection de dépendances dans une WebApp embarquée dans Jetty


…ou comment se battre quelques heures avec les ClassLoaders…

Le contexte

J’aimerais bien pouvoir démarrer une WebApp depuis un Jetty embarqué dans mon application et rendre accessible des objets de mon application dans la WebApp.

Le problème

Mon application et ma WebApp ont deux ClassLoaders bien distincts = Problème de ‘ClassCastException’

L’explication de la solution

Pour ma part, l’application en question qui va démarrer la tambouille et partager des objets est le bus de service Petals. La WebApp, elle, est développée comme une WebApp classique, elle n’a pas de lien avec mon application sinon une interface, que je qualifierais, d’échange.

L’implémentation de cette interface est injectée par mon application dans le contexte de la WebApp. Les problèmes commencent ici. En fait le seul problème est un soucis de ClassLoader. En effet, dans la WebApp, le ClassLoader est créé avec le contenu de WEB-INF/lib/*, de WEB-INF/classes/* et du ClassLoader du container Web (on fait souvent le similaire pour expliquer le ClassLoader d’un composant JBI dans le container JBI Petals). Des ressources créées dans mon application ont (généralement mais pas toujours) un ClassLoader spécifique à l’application. Si je les injecte dans la WebApp via le ServletContext, que je les récupère et que j’essaie de les ‘caster’, je me retrouve avec un beau ClassCastException du style ‘foo.Bar cannot be cast to foo.Bar‘. Les personnes développant des applications standard, ne se soucient généralement pas des histoires de ClassLoader et peuvent donc rester perplexes devant un message de la sorte. Quand on développe un container de n’importe quel type, on se dit que la il y a un soucis de ClassLoader ie on essaye de ‘caster’ une ressource qui n’a pas le même ClassLoader que celui du Thread courant. Si on regarde plus finement en passant en mode debug ce qu’il se passe lorsque l’on fait quelque chose du style :

Bar bar = (Bar)o;

On s’aperçoit bien que la JVM va appeler la méthode loadClass(String className) du ClassLoader à un moment où à un autre et que là ca va poser problème. La solution à notre problème est simplement de créer notre propre ClassLoader et ‘d’overrider’ loadClass(String className) intelligemment pour pouvoir enfin accéder à nos objets dans notre WebApp.

Le code

Disons que j’ai une classe foo.BarImpl qui implémente foo.Bar. Je veux passer une instance de cette classe BarImpl à ma WebApp via le contexte de l’application Web (quelques commentaires dans le code suivant).

package foo.bar.myapp;

import java.io.File;
import java.io.IOException;

import org.mortbay.jetty.Server;
import org.mortbay.jetty.webapp.WebAppContext;

public class MyApp {

       public void startServer() Exception {

        File webapp = new File("mywebapp.war");

        if ((webapp == null) || !webapp.exists()) {
            throw new Exception("Can not find the Web application");
        }

        this.server = new Server(9999);
        WebAppContext context = new WebAppContext();
        context.setContextPath("/");
        context.setWar(webapp.getAbsolutePath());

        Foo foo = new FooImpl();
        try {
            // create classloader with current object classloader
            MyClassLoader classloader = new MyClassLoader(foo.getClass()
                    .getClassLoader(), context);
            context.setClassLoader(classloader);
        } catch (IOException e1) {
        }
// put the object in the Jetty context ie in the servlet context
        context.getServletContext().setAttribute("foo", foo);
        context.setAttribute("foo", foo);

        this.server.setHandler(context);
        try {
            this.server.start();
        } catch (Throwable e) {
        }
    }
}

La subtilité dans le code précédent est l’utilisation de ‘MyClassLoader‘. Ici ‘MyClassLoader‘ étend ‘org.mortbay.jetty.webapp.WebAppClassLoader‘ et redéfinit la méthode ‘loadClass(String name)‘ de la facon suivante:

   @Override
    public synchronized Class loadClass(String name) throws ClassNotFoundException {
        Class result = null;
        try {
            result = this.myAppClassLoader.loadClass(name);
        } catch (Exception e) {
        }
        if (result == null) {
            result = super.loadClass(name);
        }
        return result;
    }
<pre>

Où on a ‘myAppClassLoader‘ qui est le ClassLoader de mon application que j’ai passé lors de l’instanciation de mon ClassLoader (dans le listing 1 : foo.getClass().getClassLoader()).

De l’autre coté j’ai une Servlet qui peut maintenant récupérer l’objet stocké dans le contexte sous l’attribut nommé ‘foo‘ sans problème de ClassCastException, par exemple dans la méthode ‘init‘ de la Servlet :

    @Override
    public void init() throws ServletException {
        Object o = this.getServletContext().getAttribute("foo");
        if (o != null) {
            Foo foo = null;
            try {
                foo = (Foo) o;
            } catch (RuntimeException e1) {
            }
        } else {
        }
    }

Le mot de la fin

En me mettant d’accord sur le contract de l’objet d’échange, je peux développer une application Web indépendamment, travailler avec un mock en mode test et basculer finalement sur mon application le moment venu. Finit aussi les appels Web service ou JMX locaux pour accéder à l’application qui lance le container Jetty, c’est plus propre, plus rapide, bref c’est mieux et ca marche!

Handling static resources with Jetty


Here is a quick (and easy) tip on how to handle static resources with Jetty6 (this is really nice and quick to setup such things for a demo ;o)). Here is the code :

package foo.bar;

import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.ContextHandlerCollection;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.servlet.Context;

/**
 * @author Christophe HAMERLING - eBM WebSourcing
 *
 */
public class JettyServer {

    public static void main(String[] args) throws Exception {
        Server server = new Server();
        final ContextHandlerCollection contexts = new ContextHandlerCollection();
        final Context context = new Context(contexts, "/", Context.SESSIONS);
        context.setResourceBase(System.getProperty("user.home"));
        context.addServlet("org.mortbay.jetty.servlet.DefaultServlet", "/");

        final SelectChannelConnector nioConnector = new SelectChannelConnector();
        nioConnector.setPort(1978);
        server.addConnector(nioConnector);
        server.setHandler(contexts);
        server.start();
    }
}

This will display your home directory on http://localhost:1978

Cheers