public abstract class Guice extends Object
Any non trivial application will require supporting objects for the handler implementations, for persistence for example. These supporting objects can be managed by Guice and made available to handlers (either by dependency injection or registry lookup) for increased reusability, modularity and testability.
The Guice integration is not part of the Ratpack core library, but is available as a separate add on.
That said, Ratpack is designed to support something like Guice as an integral piece via it's Registry
abstraction.
Guice is the “official” solution.
Below is a complete example for bootstrapping a Guice based Ratpack application.
import com.google.inject.AbstractModule;
import ratpack.guice.Guice;
import ratpack.handling.Context;
import ratpack.handling.Handler;
import ratpack.test.embed.EmbeddedApp;
import javax.inject.Inject;
import javax.inject.Singleton;
import static org.junit.Assert.*;
public class Example {
static class SomeService {
private final String value;
SomeService(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
static class SomeOtherService {
private final String value;
SomeOtherService(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
public static class ServiceModule extends AbstractModule {
protected void configure() {
bind(SomeService.class).toInstance(new SomeService("foo"));
bind(SomeOtherService.class).toInstance(new SomeOtherService("bar"));
bind(InjectedHandler.class);
}
}
@Singleton
static class InjectedHandler implements Handler {
private final SomeService service;
@Inject
public InjectedHandler(SomeService service) {
this.service = service;
}
public void handle(Context ctx) {
ctx.render(service.getValue() + "-" + ctx.get(SomeOtherService.class).getValue());
}
}
public static void main(String... args) throws Exception {
EmbeddedApp.of(s -> s
.registry(Guice.registry(b -> b.module(ServiceModule.class)))
.handlers(chain -> {
// The registry in a Guice backed chain can be used to retrieve objects that were bound,
// or to create objects that are bound “just-in-time”.
chain.get("some/path", InjectedHandler.class);
})
).test(httpClient -> {
assertEquals("foo-bar", httpClient.get("some/path").getBody().getText());
});
}
}
There are two ways to use Guice bound objects in your handler implementations.
The handler()
methods used to create a Guice backed application take an Action
that operates on a Chain
instance.
This chain instance given to this action provides a Guice backed Registry
via its Chain.getRegistry()
method.
This registry is able to retrieve objects that were explicitly bound (i.e. defined by a module), and bind objects “just in time”.
This means that it can be used to construct dependency injected Handler
implementations.
Simply pass the class of the handler implementation to create a new dependency injected instance of to this method, then add it to the chain.
See the code above for an example of this.
The Context
object that is given to a handler's Handler.handle(Context)
method is also a registry implementation. In a Guice backed app, Guice bound objects can be retrieved via the Registry.get(Class)
method of
the context. You can retrieve any bound object via its publicly bound type.
However, this will not create “just-in-time” bindings. Only objects that were explicitly bound can be retrieved this way.
Add on Ratpack functionality is typically provided via Guice modules.
For example, the Jackson integration for JSON serialisation
is provided by the ratpack-jackson
add-on which ships a Guice module.
To use its functionality simply register the module it provides with the BindingsSpec
used to bootstrap the application.
The Ratpack Groovy add-on provides application modes that automatically incorporate Guice (namely the “Ratpack Script” mode). The module registration process is simpler and more convenient in this mode, and there are additional options for obtaining Guice bound objects.
See the Groovy add-on's documentation for more details.
Modifier and Type | Method and Description |
---|---|
static Function<Module,Injector> |
newInjectorFactory(ServerConfig serverConfig) |
static Function<Registry,Registry> |
registry(Action<? super BindingsSpec> bindings) |
static Registry |
registry(Injector injector)
|
static Function<Registry,Registry> |
registry(Injector parentInjector,
Action<? super BindingsSpec> bindings) |
public static Registry registry(Injector injector)
Registry
backed by the given Injector
that will NOT create objects via “just-in-time” binding.injector
- The injector to back the registrypublic static Function<Registry,Registry> registry(Action<? super BindingsSpec> bindings)
public static Function<Registry,Registry> registry(Injector parentInjector, Action<? super BindingsSpec> bindings)
public static Function<Module,Injector> newInjectorFactory(ServerConfig serverConfig)