mercredi 26 septembre 2012

Vaadin 6 + GAE + Guice-Servlet - TUTORIAL

How on earth are we supposed to create a Vaadin 6 application which is both managed by Guice and hosted on Google App Engine ? The solution is actually quite simple, but it can take a while to discover it.

The solution I present here also solves a common problem with Vaadin + GAE projects, which require different servlets to be deployed in production and development environments.

First, let me go through the steps I assume you have already completed :
  • Setup Eclipse with GPE
  • Created a GAE project
  • Resolved all dependencies :
    • vaadin.jar
    • guice-3.0.jar
    • guice-servlet-3.0.jar
    • aopalliance.jar
  • Successfully ran the application without Guice injection
(Note that I created the project with the GPE, and then added the vaadin JAR. I found it easier that way than creating the project with the Vaadin plugin)
If you have trouble with these steps, check around the web, there's already many resources that can help you. If still in trouble, post a comment and I'll describe those steps too.

So you have your Vaadin + GAE project, but you want to earn the benefits of Guice and Guice Servlet. In order to do that, you will have to let Guice handle the instanciation of your servlets. So let's configure your web.xml file with the Guice Servlet filter :

  <filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>com.yourcompany.yourproject.guice.Bootstrap</listener-class>
  </listener>
So far, nothing special, it's exactly what you can find on the Guice wiki. Go take a look if you're not familiar with it, it's worth its weight in gold :
http://code.google.com/p/google-guice/wiki/Servlets

In the web.xml, we reference a Bootstrap listener class. So let's code that class :
public class Bootstrap extends GuiceServletContextListener {

 @Override
 protected Injector getInjector() {
  return Guice.createInjector(new MyServletModule(), new DomainModule());
 }
}
Again, nothing new here, just standard Guice Servlet config. But hold on, now is the time to have fun. Look at the code of our ServletModule
public class MyServletModule extends ServletModule {

 @Override
 protected void configureServlets() {

  // Disable Vaadin debug mode in production
  if (GaeEnvironment.isProduction())
   getServletContext().setAttribute("productionMode", "true");

  // Set the application class name
  Map<String, String> params = new HashMap<String, String>();
  params.put("application", MainApplication.class.getName());
  
  // Deploy the servlet which is right for the current environment
  if (GaeEnvironment.isProduction()) {
   bind(ProdApplicationServlet.class).asEagerSingleton();
   serve("/app/*", "/VAADIN/*").with(ProdApplicationServlet.class, params);
  } else {
   bind(DevApplicationServlet.class).asEagerSingleton();
   serve("/app/*", "/VAADIN/*").with(DevApplicationServlet.class, params);
  }

  // Bind your Application implementation
  bind(Application.class).to(MainApplication.class).in(ServletScopes.SESSION);

  // OPTIONAL : In case you user Objectify 4
  bind(ObjectifyFilter.class).in(Singleton.class);
  filter("/*").through(ObjectifyFilter.class);

 }

}

OK, that's a lot of code. Let us review it chunk by chunk :
 // Disable Vaadin debug mode in production
  if (GaeEnvironment.isProduction())
   getServletContext().setAttribute("productionMode", "true");
As you might already be aware of, the debug feature of Vaadin is activated by default. This is not the kind of feature we want users to be able to use, so we want to make sure that it is automatically disabled when the application is in the cloud.
The GaeEnvironment class is only here to clarify the intent of the code, have a look at the implementation :
public class GaeEnvironment {

    public static boolean isProduction() {
        return SystemProperty.environment.value() == SystemProperty.Environment.Value.Production;
    }

    public static boolean isDevelopment() {
        return !isProduction();
    }

}

In the next piece of code, we first create a map of properties that we use to initialize the servlets.
// Set the application class name
  Map<String, String> params = new HashMap<String, String>();
  params.put("application", MainApplication.class.getName());
  
  // Deploy the servlet which is right for the current environment
  if (GaeEnvironment.isProduction()) {
   bind(ProdApplicationServlet.class).asEagerSingleton();
   serve("/app/*", "/VAADIN/*").with(ProdApplicationServlet.class, params);
  } else {
   bind(DevApplicationServlet.class).asEagerSingleton();
   serve("/app/*", "/VAADIN/*").with(DevApplicationServlet.class, params);
  }
And again, we check if we are in a Production or Local/Dev environment. The reason is that the GAE Production environment is different to an everyday servlet container, and Vaadin provides a specific implementation for it.
In the example above, our web application will be available at http://localhost:8888/app/ and http://localhost:8888/VAADIN/. You can get rid of the first one, which is only here to help you make nice looking URLs, but do NOT remove the second one, or you will break the integration.

Now let's look at the code of our ProdApplicationServlet :
@SuppressWarnings ("serial")
@Singleton
public class ProdApplicationServlet extends GAEApplicationServlet {

 private final Provider<Application> applicationProvider;

 @Inject
 public ProdApplicationServlet(Provider<Application> applicationProvider) {
  this.applicationProvider = applicationProvider;
 }

 @Override
 protected Application getNewApplication(HttpServletRequest request) throws ServletException {
  return applicationProvider.get();
 }

}
As you can see, this class is a simple extension of GAEApplicationServlet, which is provided by Vaadin. Since it does not support dependency injection, we have to subclass it and override its getNewApplication() method so that it returns a Guice-managed instance of Application. That way, our implementation of Application can itself be injected.

The DevApplicationServlet is very similar, the only difference is that it extends a non-GAE-specific servlet.
@SuppressWarnings ("serial")
@Singleton
public class DevApplicationServlet extends ApplicationServlet {

 private final Provider<Application> applicationProvider;

 @Inject
 public DevApplicationServlet(Provider<Application> applicationProvider) {
  this.applicationProvider = applicationProvider;
 }

 @Override
 protected Application getNewApplication(HttpServletRequest request) throws ServletException {
  return applicationProvider.get();
 }

}

Don't forget to bind the implementation of Application you want to use :
// Bind your Application implementation
  bind(Application.class).to(MainApplication.class).in(ServletScopes.SESSION);

By now, you might have realized something is wrong. Since the resolution of which implementation of Application to instantiate is made by Guice, there shouldn't be any need to pass its name as an initialization parameter to the servlets. And you would be right, however the servlets follow a FAIL FAST strategy, and they need a valid Application class name on initialization, even if it is different from the actual returned implementation.

I hope you got it to work too, and please give some feedback in the comments if there is anything missing.

P.S.: If you don't know what to do next, just put an @Inject annotation on your MainApplication's constructor so that the parameters get injected.

lundi 23 avril 2012

Annotation-based authorization with Guice Servlet & AOP

Most web applications use an authorization system to make sure the user is logged in and authorized to execute specific procedures. For example, a simple user will only have read access, while an admin can edit and delete. For every server endpoint, we ask ourselves : "Who has the privilege to access that service ?"

For such cross-cutting concerns, we are told that AOP is the key. Intercepting the methods we want to secure and checking authorization levels in a separate security aspect...
One thing that bothers me with such an approach is that when I want to check the access level of a method, I have to go look in the security aspect to see how it was intercepted. I'd rather have a declarative way to explicit the access level of a method, like an annotation :

@AuthorizationRequired(Role.ADMIN)
public void securedMethod() {}

Implementing such a system is deceptively simple using Guice AOP once you have installed Guice Servlet to enable injection of servlet related objects, like HttpSession.

First, we need to create the annotation :

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthorizationRequired{
   Role value();
}

Then we implement the method interceptor :

public class AuthorizationInterceptor implements MethodInterceptor {

   @Inject private Provider<HttpSession> sessionProvider;

   @Override
   public Object invoke(MethodInvocation invoc) throws Throwable {
      Role required = invoc.getMethod().getAnnotation(AuthorizationRequired.class).value();
      User user = getUserFromSession(sessionProvider.get());
      if (isUserAuthorized(user, required))
         return invoc.proceed();
      else
         throw new UnauthorizedException("User is not authorized");
   }
}

Obviously, to get the logged in user you need the session. Thanks to Guice Servlet magic, you can inject a session provider in any object.

Finally, we bind the interceptor in the Guice ServletModule :

AuthorizationInterceptor interceptor = new AuthorizationInterceptor ();
requestInjection(interceptor);
bindInterceptor(classMatcher, annotatedWith(AuthorizationRequired.class), interceptor );

Don't forget that only objects instantiated by Guice will have their methods intercepted.

mercredi 28 mars 2012

Editor-compatible EnumListBox for GWT

I remember reading a great article form Uncle Bob about enums. Bottom line was, enums are cool, but where do we use their awesomeness ? It's true that more often than not, I use enums like I would use String constants (but it feels better anyway).
Finally, I have found a context where enums completely rock, without question.

First, I have to admit something. I don't like String manipulation. So when I see an entity with a String-typed field that has a finite number of possible values, I instantly refactor it into an enum. The problem is that at some point, I always have to convert my enum into a String, or parse a String to get my enum back. And that sucks. It makes me feel bad, I just don't want to do that anymore.
So here it is, my solution to keep my typed enums all the way from entity to UI widgets. And it does it so transparently it feels like magic.

Before going further, let me introduce my stack :
GWT with Editor framework & RequestFactory
GAE with Objectify
Even if you don't use that specific stack, you might be able to use the same solution, or at least get some inspiration, so keep on reading !

First, let me describe the context. You develop a GWT application, and your domain entities have enum typed fields. Your proxies/DTOs have enum typed fields. But when it comes to the UI, the ListBox widget only handles Plain Old Dirty String, and there you are going from enum to String, and back from String to enum. Wouldn't it be cool to have something smarter, like an EnumListBox ?

Let's take for example the issue tracker of BitBucket :

We could have an enum listing all those possible values :
public enum Priority {

 TRIVIAL, MINOR, MAJOR, CRITICAL, BLOCKER;

 public String toString() {
  return name().toLowerCase();
 };

}
So, how do we create a ListBox to display those values ? On his blog, David Chandler demonstrates the use of an EnumListBox, however it is not Editor framework compatible. Here's my implementation of an EnumListBox :
public class EnumListBox<E extends Enum<E>> extends ValueListBox<E> {

 public EnumListBox() {
  super(new EnumRenderer<E>(), new EnumKeyProvider<E>());
 }

 public EnumListBox(Class<E> clazz) {
  this();
  setAcceptableValues(Arrays.asList(clazz.getEnumConstants()));
 }

}
We're extending ValueListBox, which implements the IsEditor interface. The second constructor is for commodity, just pass in your enum class and it will initialize itself with the enum values (we'll see an example later). If you want your ListBox to list a subset only of the enum, you can use the default constructor and call setAcceptableValues() yourself.
You'll also need the EnumRenderer and EnumKeyProvider classes :
public class EnumRenderer<E extends Enum<E>> implements Renderer<E> {

 @Override
 public String render(E object) {
  if (object == null)
   return "";
  return object.toString();
 }

 @Override
 public void render(E object, Appendable appendable) throws IOException {
  appendable.append(render(object));
 }

}
On line 6, you can see that I chose to display an empty String when no value is selected. That might be the most significant change you want to make.
public class EnumKeyProvider<E extends Enum<E>> implements ProvidesKey<E> {

 @Override
 public Object getKey(E item) {
  if (item == null)
   return null;
  return item.name();
 }

}
Now that you got your EnumListBox, you must be eager to use it. Remember our example, we want to select the priority of an issue. So in our IssueEditor :
public class IssueEditor extends Composite implements Editor<IssueProxy> {

 @UiField(provided = true) EnumListBox<Priority> priority = new EnumListBox<Priority>(Priority.class);

}
It does make a long verbose line, I wish I could do better. But that's all you need, and it works with any enum.

To continue with our example with RequestFactory, let's show our IssueProxy : 
@ProxyFor(value = Issue.class)
public interface IssueProxy extends EntityProxy {
 
 Priority getPriority();

 void setPriority(Priority priority);

}
Finally, the domain entity :
public class Issue {
 
 @NotNull private Priority priority;

 public Priority getPriority() {
  return priority;
 }

 public void setPriority(Priority priority) {
  this.priority = priority;
 }

}
I hope you got the point by now. As you see, the wiring is completely automatic, thanks to Editor + RequestFactory magic. It is as simple as it can ever get, we have almost attained the highest possible level of abstraction.