1 /** 2 * <p> 3 * This package provides support for 4 * <a HREF="http://code.google.com/p/google-guice/">Guice</a> 5 * dependency injection in DWR-based web applications. 6 * This documentation assumes you already understand Guice concepts. 7 * </p> 8 * <p> 9 * To use this support minimally, 10 * <ul> 11 * <li> install a concrete extension of 12 * {@link org.directwebremoting.guice.DwrGuiceServletContextListener} 13 * as a {@code <listener>} in your web application's configuration 14 * file ({@code web.xml}), </li> 15 * <li> install {@link org.directwebremoting.guice.DwrGuiceServlet} for all 16 * requests to {@code /dwr/*}. </li> 17 * </ul> 18 * For example: 19 * </p> 20 * <pre> 21 * <listener> 22 * <listener-class>org.myorg.myproj.MyServletContextListener</listener-class> 23 * </listener> 24 * 25 * <servlet> 26 * <servlet-name>dwr-invoker</servlet-name> 27 * <servlet-class>org.directwebremoting.guice.DwrGuiceServlet</servlet-class> 28 * </servlet> 29 * 30 * <servlet-mapping> 31 * <servlet-name>dwr-invoker</servlet-name> 32 * <url-pattern>/dwr/*</url-pattern> 33 * </servlet-mapping> 34 * </pre> 35 * <p> 36 * {@link org.directwebremoting.guice.DwrGuiceServletContextListener DwrGuiceServletContextListener} 37 * is also an abstract Guice module; it extends 38 * {@link org.directwebremoting.guice.AbstractDwrModule AbstractDwrModule}, 39 * which in turn extends Guice's {@link AbstractModule}. 40 * Your listener class must define 41 * {@link org.directwebremoting.guice.AbstractDwrModule#configure configure}; 42 * this is where you do your Guice binding. 43 * You can also put binding code in a separate class or classes with 44 * {@link AbstractModule#install AbstractModule.install}. 45 * </p> 46 * <p> 47 * Use {@link org.directwebremoting.guice.GuiceCreator GuiceCreator} 48 * when annotating classes with {@code RemoteProxy}. When you use a 49 * {@code GuiceCreator} to create your remoted objects, it gets an 50 * instance from a Guice injector using your bindings. 51 * </p> 52 * <p> 53 * For bind-time control over how JavaScript names map to Java targets, use the 54 * {@link org.directwebremoting.guice.AbstractDwrModule#bindRemoted(Class) bindRemoted} 55 * or 56 * {@link org.directwebremoting.guice.AbstractDwrModule#bindRemotedAs(String,Class) bindRemotedAs} 57 * methods. The target of the script can be an abstract class or interface 58 * bound in the normal Guice way to a concrete class, instance, or provider. 59 * In that case only the methods defined on the abstract class or 60 * interface are accessible, even if the implementing class has other public 61 * methods. You can supply different bindings for different script names, including 62 * using the same interface with different implementations for different script names, 63 * or different interfaces for different script names mapping to the same implementation 64 * type (assuming it implements both interfaces). 65 * </p> 66 * <p> 67 * You can bind a type or type pattern string to a custom converter with 68 * {@link org.directwebremoting.guice.AbstractDwrModule#bindConversion(Class) bindConversion}, 69 * and you can put Ajax filters on scripts with 70 * {@link org.directwebremoting.guice.AbstractDwrModule#bindFilter(String) bindFilter}. 71 * Note, however, that you can achieve the same effect (and more flexibly) using Guice's 72 * {@code bindInterceptors} method. 73 * </p> 74 * <p> 75 * You can install your own DWR configurator using 76 * {@code bind(Configurator.class).toInstance(yourConfigurator)}, 77 * which then overrides any {@code dwr.xml} configuration. 78 * You'll probably want to use a 79 * {@link org.directwebremoting.fluent.FluentConfigurator FluentConfigurator} 80 * for this purpose. 81 * </p> 82 * <p> 83 * You can still configure DWR's settings normally via {@code <init-param>} 84 * directives in {@code web.xml}, but usually there is no need to. Most DWR 85 * settings can be set with 86 * {@link org.directwebremoting.guice.AbstractDwrModule#bindParameter(ParamName) bindParameter}. 87 * The {@link org.directwebremoting.guice.ParamName ParamName} 88 * enum type lists the available parameters. 89 * </p> 90 * <p> 91 * To be able to use the DWR scopes for all your injected objects, not just 92 * DWR-remoted objects, your binding code should call 93 * {@link org.directwebremoting.guice.AbstractDwrModule#bindDwrScopes() bindDwrScopes} 94 * at some point. 95 * </p> 96 * <p> 97 * For creating your own scopes where the instance injected depends on some 98 * run-time value, create a concrete extension of 99 * {@link org.directwebremoting.guice.AbstractContextScope AbstractContextScope}. 100 * </p> 101 * <p> 102 * This example illustrates two ways to define remoted objects, 103 * calling {@code bindRemotedAs} and annotating with {@code @RemoteProxy}; 104 * two ways to define conversions, using {@code bindConversion} 105 * and using a custom configurator; how to register annotated classes 106 * at bind-time; how to bind a script name to an {@code AjaxFilter}; and 107 * how to set a DWR parameter (debug, in this case) at bind-time. 108 * It does not use an {@code <init-param>} directive, and it doesn't have 109 * a {@code dwr.xml}. 110 * </p> 111 * <pre> 112 * public final class MyServletContextListener extends DwrGuiceServletContextListener 113 * { 114 * protected void configure() 115 * { 116 * bindRemotedAs("Hello", HelloService.class) 117 * .to(HelloServiceImpl.class) 118 * .in(DwrScopes.APPLICATION); 119 * 120 * bindFilter("Hello") 121 * .to(TraceFilter.class); 122 * 123 * bind(MessageService.class) 124 * .to(MessageServiceImpl.class) 125 * .in(DwrScopes.SCRIPT); 126 * 127 * bindAnnotatedClasses( 128 * DomainService.class, // @RemoteProxy(creator=GuiceCreator.class)/@RemoteMethod 129 * HelloRecordImpl.class // @DataTransferObject/@RemoteProperty 130 * ); 131 * 132 * // When converting HelloRecord, use existing converter for HelloRecordImpl. 133 * bindConversion(HelloRecord.class, HelloRecordImpl.class); 134 * 135 * bindConversion(DateTime.class) 136 * .toInstance(DateTimeConverter.get("yyyy-MM-dd hh:mm a")); 137 * 138 * bind(Configurator.class).toInstance(new FluentConfigurator() 139 * { 140 * public void configure() { 141 * String localTime = "localTime"; 142 * withConverterType(localTime, DateTimeConverter.class.getName()); 143 * withConverter(localTime, LocalTime.class.getName()) 144 * .addParam("format", "yyyy-MM-dd"); 145 * } 146 * }); 147 * 148 * bindParameter(DEBUG).to(true); 149 * 150 * bindDwrScopes(); 151 * } 152 * } 153 * </pre> 154 * <p> 155 * Note that because application scope is larger than script session scope, 156 * {@code HelloServiceImpl} has an injected constructor (not shown here) 157 * that takes a {@code Provider<MessageService>} rather than a plain 158 * {@code MessageService}. 159 * </p> 160 * <p> 161 * There are four classes with names that start with "Internal". These classes 162 * have to be public with a parameterless constructor so the non-Guicy DWR 163 * machinery can create them. They are not meant to be used directly. 164 * </p> 165 * <p> 166 * The classes that handle DWR scopes are modeled on the classes in the 167 * {@code com.google.inject.servlet} package, but are independent of them. 168 * You do <em>not</em> need to install the Guice {@code ServletModule} and 169 * {@code GuiceFilter} to use the DWR scopes, but if you do, you have to be 170 * careful to install the DWR scopes without creating conflicting bindings 171 * for request, response, and session. Calling 172 * {@link org.directwebremoting.guice.AbstractDwrModule#bindDwrScopes(boolean) bindDwrScopes(false)} 173 * accomplishes this. 174 * </p> 175 * @author Tim Peierls [tim at peierls dot net] 176 */ 177 package org.directwebremoting.guice; 178