السبت، 20 مارس 2010

Google goodness: using GWT with Guice

The Google Web Toolkit and Guice are two very useful technologies. This post explains what they are, how they can be used together and what benefits this brings.



The Google Web Toolkit enables one of the most elegant ways of writing web applications. With version 2, it has reached a new level of ease of use: simple install, quick development turn-around, testing in an external browser, CSS-based layout that works even for complicated scenarios, etc. Guice is a lightweight dependency injection framework and helps with structuring an application. It also has one of the most elegant Java APIs around. Combining them means that Guice manages GWT’s services and server-side objects. These are the installation steps:



Step 1: Install GWT. Installing the GWT has become simple, because both the GWT SDK and the Google Plugin (with IDE support for GWT) can be installed as Eclipse plugins.



Step 2: Install Guice. Also simple. Download the JAR, drop it into the directory war/WEB-INF/lib inside the directory of your GWT project, add it to the Java build path.



Step 3: Let Guice manage all remote services, as explained in the article “Guice with GWT”. I needed aopalliance.jar in addition to the two JARs that were mentioned in the article. Unfortunately, the @RemoteServiceRelativePath is relative to the module path. The following is an example where this has been taken into consideration.

public class ServiceModule extends ServletModule {
@Override
protected void configureServlets() {
serve("/"+ServerConstants.SERVICE_PATH).with(MyServlet.class);

bind(MyService.class).to(MyServiceImpl.class);
}
}

@RemoteServiceRelativePath("../"+ServerConstants.SERVICE_PATH)
public interface MyService extends RemoteService {
//...
}
Benefits: As all services are managed by a single servlet, one just registers a new service with Guice and it becomes available to the client. No need to set up an additional servlet. To fully appreciate Guice, first learn about basic (constructor) dependency injection. Afterward, you are ready for an explanation of scopes: The Guice injector is a factory for objects. By default, it creates a new instance each time it is invoked. This can be changed by assigning scopes to classes. For example, the singleton scope means that a class is only instantiated once; if the injector is told to produce more than one instance, it will always return the same one. Each invocation of a service method is a separate HTTP request. Accordingly, classes in request scope are created freshly for each request. The injector has a binding for HttpServletRequest, and can thus inject it into an instance in request scope. A service method handles a request by asking the injector for a request-scoped instance and by invoking one of its methods. Scopes can also be used for session management, as there is a session scope. Instances are created once per session and can hold any kind of session data (who is currently logged in, etc.). No more direct fiddling with HttpSession! By requesting a Provider<MySessionScopedClass>, instances in singleton scope can access the current instance of MySessionScopedClass.



More Guice tips: If you want to extend a class Component with implementers of an interface Plugin, you can do so via multibindings. Interface Plugin is multibound to a set of classes and Component requests a Set<Plugin>. It is then free to iterate over all Plugin instances, in order to make them perform tasks or to inform them of important events. Guice also helps one with logging:

Guice has a built-in binding for java.util.logging.Logger, intended to save some boilerplate. The binding automatically sets the logger’s name to the name of the class into which the Logger is being injected. [source]


Thread safety: If you are in singleton or session scope, you need to be thread-safe. If you are in request scope or “no scope” (=created each time), you don’t. Interestingly, Crazy Bob Lee recommends:

If the object truly is stateless, it’s faster for Guice to create a new instance than it is to retrieve a singleton. If Guice creates a new instance every time, it can bypass the scoping layer entirely, not to mention the logic inside the singleton scope.
Moral: use the latter two scopes as often as possible.

ليست هناك تعليقات:

إرسال تعليق