Package org.directwebremoting.guice

This package provides support for Guice dependency injection in DWR-based web applications.

See:
          Description

Class Summary
AbstractDwrGuiceServletContextListener Not for subclassing directly; this is a common base for two different approaches to Injector creation and configuration, DwrGuiceServletContextListener and CustomInjectorServletContextListener.
AbstractDwrModule An extension of the enhanced AbstractModule from the util subpackage that adds DWR configuration methods when used in conjunction with DwrGuiceServlet.
CustomInjectorServletContextListener Register a concrete subclass of this as a servlet context listener; it uses CustomInjectorServletContextListener.createInjector() to obtain a custom Injector and then stashes it in the servlet context.
DwrGuiceServlet An extension of the basic DwrServlet that configures itself for dependency injection with Guice.
DwrGuiceServletContextListener Register a concrete subclass of this as a servlet context listener to configure an Injector with this as the only Module and stash it in the servlet context.
DwrGuiceUtil Utilities for making Injector and ServletContext instances available.
DwrScopes Scopes available to DWR applications.
GuiceCreator A creator that uses Guice dependency injection to create remoted objects.
InternalAjaxFilterManager Extends an existing ajax filter manager with an injected list of ajax filters specified at Guice bind-time.
InternalConfigurator Delegates to an injected configurator.
InternalConverterManager Extends an existing converter manager with an injected list of converters specified at Guice bind-time.
InternalCreatorManager Extends an existing creator manager with an injected list of creators specified at Guice bind-time.
 

Enum Summary
ParamName Parameters used to configure DWR.
 

Annotation Types Summary
ApplicationScoped Marks classes for which there should be one instance per web application (i.e., per servlet context) and these instances should be created eagerly at servlet init() and closed (when they implement Closeable) at servlet destroy().
GlobalApplicationScoped Marks classes for which there should be one instance per web application (i.e., per servlet context).
RequestParameters Marks fields or parameters of type Map<String, String[]> that are to be injected with the parameter map of the current HTTP request.
RequestScoped Marks classes for which there should be one instance per HTTP request.
ScriptSessionScoped Marks classes for which there should be one instance per script session.
SessionScoped Marks classes for which there should be one instance per HTTP session.
 

Package org.directwebremoting.guice Description

This package provides support for Guice dependency injection in DWR-based web applications. This documentation assumes you already understand Guice concepts.

To use this support minimally,

For example:

   <listener>
     <listener-class>org.myorg.myproj.MyServletContextListener</listener-class>
   </listener>

   <servlet>
     <servlet-name>dwr-invoker</servlet-name>
     <servlet-class>org.directwebremoting.guice.DwrGuiceServlet</servlet-class>
   </servlet>

   <servlet-mapping>
     <servlet-name>dwr-invoker</servlet-name>
     <url-pattern>/dwr/*</url-pattern>
   </servlet-mapping>
 

DwrGuiceServletContextListener is also an abstract Guice module; it extends AbstractDwrModule, which extends AbstractModule, which in turn extends Guice's AbstractModule. Your listener class must define configure; this is where you do your Guice binding. You can also put binding code in a separate class or classes with AbstractModule.install.

Alternatively, if you already have an existing Injector instance with bindings from one or more AbstractDwrModule, use CustomInjectorServletContextListener by defining createInjector to return your existing Injector.

To turn classes into remote DWR services, use the bindRemoted or bindRemotedAs methods. The binding instructs DWR to handle requests for the given type name (or script name, if you use the second variant) by getting a fully-injected instance of the given class from the Guice injector and calling the requested method on that instance. The target type of these bindings can be an abstract class or interface bound in the normal Guice way to a concrete class, instance, or provider; in that case, only the methods defined on the abstract class or interface are accessible on the remoted object, even if the implementing class has other public methods. You can supply different bindings for different script names, including using the same interface with different implementations for different script names, or different interfaces for different script names mapping to the same implementation type (assuming it implements both interfaces).

Alternatively, annotate your remoted classes with RemoteProxy, and remotely callable methods with RemoteMethod, using creator=GuiceCreator. When a request comes in for the remoted type, it is retrieved from the Guice injector using your bindings for that type.

In either case, your data transfer objects should be bound with DataTransferObject, and the remotely accessible properties with RemoteProperty. Use bindAnnotatedClasses to tell DWR which classes need to be scanned for annotations.

You can bind a type or type pattern string to a custom converter with bindConversion, and you can put Ajax filters on scripts with bindFilter. Note, however, that you can achieve the effect of an Ajax filter more flexibly using bindInterceptor.

You can install your own DWR Configurator using bind(Configurator.class).toInstance(yourConfigurator), which then overrides any dwr.xml configuration. You'll probably want to use a FluentConfigurator for this purpose.

You can still configure DWR's settings via <init-param> directives in web.xml, but usually there is no need to. Most DWR settings can be set with bindParameter. The ParamName enum type lists the available parameters.

For creating your own scopes where the instance injected depends on some run-time value, create a concrete extension of AbstractContextScope.

For example:

    public final class MyServletContextListener extends DwrGuiceServletContextListener
    {
        protected void configure()
        {
            bindRemotedAs("Hello", HelloService.class)
                .to(HelloServiceImpl.class)
                .in(ApplicationScoped.class);

            bindInterceptor(
                HelloService.class,
                AuthenticationInterceptor.class);

            bindFilter("Hello")
                .to(TraceFilter.class);

            bind(MessageService.class)
                .to(MessageServiceImpl.class)
                .in(ScriptSessionScoped.class);

            bindAnnotatedClasses(
                DomainService.class,   // @RemoteProxy(creator=GuiceCreator.class)/@RemoteMethod
                HelloRecordImpl.class  // @DataTransferObject/@RemoteProperty
            );

            // When converting HelloRecord, use existing converter for HelloRecordImpl.
            bindConversion(
                HelloRecord.class,
                HelloRecordImpl.class);

            bindConversion(DateTime.class)
                .toInstance(DateTimeConverter.get("yyyy-MM-dd hh:mm a"));

            bind(Configurator.class).toInstance(new FluentConfigurator()
            {
                public void configure() {
                    String localTime = "localTime";
                    withConverterType(localTime, DateTimeConverter.class.getName());
                    withConverter(localTime, LocalTime.class.getName())
                        .addParam("format", "yyyy-MM-dd");
                }
            });

            bindParameter(DEBUG).to(true);
        }
    }
 

This example illustrates:

It does not use an <init-param> directive, and it doesn't have a dwr.xml.

Note that because application scope is larger than script session scope, HelloServiceImpl would have an injected constructor (not shown here) taking a Provider<MessageService> rather than a plain MessageService.

There are several classes in this package with names that start with Internal. These classes have to be public with a parameterless constructor so the non-Guicy DWR machinery can create them. They are not meant to be used directly.

The classes that handle DWR scopes are modeled on the classes in the com.google.inject.servlet package, but are independent of them. You do not need to install com.google.inject.servlet.GuiceFilter and the Guice com.google.inject.servlet.ServletModule to use the DWR scopes. There is the potential for binding conflict with this module, however, so this package creates bindings for the potentially conflicting types using a special @Dwr annotation. It also makes the standard binding if the Guice servlet module is not found in the class loader. The machinery to achieve this is called automatically with DwrGuiceServletContextListener. If you use CustomInjectorServletContextListener, remember to call bindDwrScopes before doing any other bindings. In both cases, the standard behavior can be overridden explicitly; see bindDwrScopes(boolean) and bindPotentiallyConflictingTypes.

Author:
Tim Peierls [tim at peierls dot net]

Copyright 2008