DWR provides support for Guice dependency injection in DWR-based web applications. This documentation assumes you already understand Guice concepts. The DWR-Guice integration is maintained by Tim Peierls.
To use this support minimally,
DwrGuiceServletContextListener
as a <listener>
in your web application's configuration
file (web.xml
), DwrGuiceServlet
for all
requests to /dwr/*
. <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 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
.
Use GuiceCreator
when annotating classes with RemoteProxy
. When you use a
GuiceCreator
to create your remoted objects, it gets an
instance from a Guice injector using your bindings.
For bind-time control over how JavaScript names map to Java targets, use the
bindRemoted
or
bindRemotedAs
methods. The target of the script 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, 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).
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 same effect (and more flexibly) using Guice's
bindInterceptors
method.
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 normally 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.
To be able to use the DWR scopes for all your injected objects, not just
DWR-remoted objects, your binding code should call
bindDwrScopes
at some point.
For creating your own scopes where the instance injected depends on some
run-time value, create a concrete extension of
AbstractContextScope
.
This example illustrates two ways to define remoted objects,
calling bindRemotedAs
and annotating with @RemoteProxy
;
two ways to define conversions, using bindConversion
and using a custom configurator; how to register annotated classes
at bind-time; how to bind a script name to an AjaxFilter
; and
how to set a DWR parameter (debug, in this case) at bind-time.
It does not use an <init-param>
directive, and it doesn't have
a dwr.xml
.
public final class MyServletContextListener extends DwrGuiceServletContextListener { protected void configure() { bindRemotedAs("Hello", HelloService.class) .to(HelloServiceImpl.class) .in(DwrScopes.APPLICATION); bindFilter("Hello") .to(TraceFilter.class); bind(MessageService.class) .to(MessageServiceImpl.class) .in(DwrScopes.SCRIPT); 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); bindDwrScopes(); } }
Note that because application scope is larger than script session scope,
HelloServiceImpl
has an injected constructor (not shown here)
that takes a Provider<MessageService>
rather than a plain
MessageService
.
There are four classes 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 the Guice ServletModule
and
GuiceFilter
to use the DWR scopes, but if you do, you have to be
careful to install the DWR scopes without creating conflicting bindings
for request, response, and session. Calling
bindDwrScopes(false)
accomplishes this.
Further information on using DWR and Guice together is available in the Guice JavaDoc, or from Tim's blog: