Getting started¶
Getting started guide briefly shows the most commonly used features. Advanced description of guicey concepts may be found in the concepts section.
Installation¶
Available from maven central and bintray jcenter.
Maven:
<dependency>
<groupId>ru.vyarus</groupId>
<artifactId>dropwizard-guicey</artifactId>
<version>5.3.0</version>
</dependency>
Gradle:
implementation 'ru.vyarus:dropwizard-guicey:5.3.0'
BOM¶
Guicey pom may be also used as maven BOM.
Note
If you use guicey extensions then use extensions BOM instead (it already includes guicey BOM).
Gradle:
dependencies {
implementation platform('ru.vyarus:dropwizard-guicey:5.3.0')
// uncomment to override dropwizard and its dependencies versions
// implementation platform('io.dropwizard:dropwizard-dependencies:2.0.20')
// no need to specify versions
implementation 'ru.vyarus:dropwizard-guicey'
implementation 'io.dropwizard:dropwizard-auth'
implementation 'com.google.inject:guice-assistedinject'
testImplementation 'io.dropwizard:dropwizard-test'
testImplementation 'org.spockframework:spock-core'
}
Maven:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>ru.vyarus</groupId>
<artifactId>dropwizard-guicey</artifactId>
<version>5.3.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- uncomment to override dropwizard and its dependencies versions
<dependency>
<groupId>io.dropwizard/groupId>
<artifactId>dropwizard-dependencies</artifactId>
<version>2.0.20</version>
<type>pom</type>
<scope>import</scope>
</dependency> -->
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>ru.vyarus</groupId>
<artifactId>dropwizard-guicey</artifactId>
</dependency>
</dependencies>
BOM includes:
BOM | Artifact |
---|---|
Guicey itself | ru.vyarus:dropwizard-guicey |
Dropwizard BOM | io.dropwizard:dropwizard-bom |
Guice BOM | com.google.inject:guice-bom |
HK2 bridge | org.glassfish.hk2:guice-bridge |
System rules (required for StartupErrorRule) | com.github.stefanbirkner:system-rules |
Spock | org.spockframework:spock-core |
Usage¶
Full source of example application is published here
Register guice bundle:
public class SampleApplication extends Application<Configuration> {
public static void main(String[] args) throws Exception {
new SampleApplication().run(args);
}
@Override
public void initialize(Bootstrap<Configuration> bootstrap) {
bootstrap.addBundle(GuiceBundle.builder()
.enableAutoConfig(getClass().getPackage().getName())
.build());
}
@Override
public void run(Configuration configuration, Environment environment) throws Exception {
}
}
Tip
Bundle builder contains shortcuts for all available features, so required function may be found only by looking at available methods (and reading javadoc).
Auto configuration (activated with enableAutoConfig
) means that guicey will search for extensions in
application package and subpackages. Extension classes are detected by "feature markers": for example,
resources has @Path
annotation, tasks extends Task
etc.
Tip
You can declare multiple packages for classpath scan:
.enableAutoConfig("com.mycompany.foo", "com.mycompany.bar")
Application could be launched by simply running main class (assume you will use IDE run command):
SampleApplication server
Note
config.yml is not passed as parameter because we don't need additional configuration now
Add resource¶
Creating custom rest resource:
@Path("/sample")
@Produces("application/json")
public class SampleResource {
@GET
@Path("/")
public Response ask() {
return Response.ok("ok").build();
}
}
Now, when you run application, you can see that resource was installed automatically:
INFO [2017-02-05 11:23:31,188] io.dropwizard.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:
GET /sample/ (ru.vyarus.dropwizard.guice.examples.rest.SampleResource)
Call http://localhost:8080/sample/
to make sure it works.
Tip
Rest context is mapped to root by default. To change it use configuration file:
server:
rootPath: '/rest/*'
Resource is a guice bean, so you can use guice injection inside it. To access request specific
objects like request, response, jersey javax.ws.rs.core.UriInfo
etc. use Provider
:
@Path("/sample")
@Produces("application/json")
public class SampleResource {
@Inject
private Provider<HttpServletRequest> requestProvider;
@GET
@Path("/")
public Response ask() {
final String ip = requestProvider.get().getRemoteAddr();
return Response.ok(ip).build();
}
}
Now resource will return caller IP.
Warning
Providers must be used instead of @Context
field injections
But @Context
can be used for method parameters
Note
By default, resources are forced to be singletons (when no scope annotation defined).
Add managed¶
Dropwizard managed objects are extremely useful for managing resources.
Create simple managed implementation:
@Singleton
public class SampleBootstrap implements Managed {
private final Logger logger = LoggerFactory.getLogger(SampleBootstrap.class);
@Override
public void start() throws Exception {
logger.info("Starting some resource");
}
@Override
public void stop() throws Exception {
logger.info("Shutting down some resource");
}
}
It will be automatically discovered and installed. Guicey always reports installed extensions (when they are not reported by dropwizard itself). So you can see in startup logs now:
INFO [2017-02-05 11:59:30,750] ru.vyarus.dropwizard.guice.module.installer.feature.ManagedInstaller: managed =
(ru.vyarus.dropwizard.guice.examples.service.SampleBootstrap)
Add filter¶
Note
Guice ServletModule may be used for servlets and filters definitions, but most of the time it's more convenient to use simple servlet annotations (@WebFilter, @WebServlet, @WebListener). Moreover, guice servlet module is not able to register async filters and servlets.
Add sample filter around rest methods:
@WebFilter(urlPatterns = "/*")
public class CustomHeaderFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if ("me".equals(request.getParameter("user"))) {
chain.doFilter(request, response);
} else {
((HttpServletResponse) response)
.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not authorized");
}
}
@Override
public void destroy() {
}
}
Filter will pass through only requests with user=me
request parameter. It is used just to show
how to register custom filters with annotations (implementation itself is not useful).
New lines in log will appear confirming filter installation:
INFO [2017-02-11 17:18:16,943] ru.vyarus.dropwizard.guice.module.installer.feature.web.WebFilterInstaller: filters =
/* (ru.vyarus.dropwizard.guice.examples.web.AuthFilter) .auth
Call http://localhost:8080/sample/
and http://localhost:8080/sample/?user=me
to make sure filter works.
Add guice module¶
Guice module registration:
bootstrap.addBundle(GuiceBundle.builder()
...
.modules(new SampleModule())
.build());
Multiple modules could be registered at once:
.modules(new SampleModule(), new Some3rdPatyModule())
Note
Registration above occur in dropwizard initialization phase, when neither Configuration
nor Environment
objects are available, but if you need them in module then either
register module in guicey bundle's run method or use marker interfaces
Manual mode¶
If you don't want to use classpath scan, then you will have to manually specify all extensions. Example above would look in manual mode like this:
bootstrap.addBundle(GuiceBundle.builder()
.modules(new SampleModule())
.extensions(
SampleResource.class,
SampleBootstrap.class,
CustomHeaderFilter.class
)
.build());
The only difference is the absence of classpath scan (but you'll have to manually declare all extensions).
Tip
Explicit extensions declaration could be used together with classpath scan: for example, classpath scan could not cover all packages with extensions (e.g. due to too much classes) and not covered extensions may be specified manually.
Note
Duplicate extensions are filtered. If some extension is registered manually and also found with auto scan then only one extension instance will be registered. Even if extension registered multiple times manually, only one extension will work.
Configuration from bindings¶
Guicey is also able to recognize extensions from declared guice bindings, so manual example above is equal to:
bootstrap.addBundle(GuiceBundle.builder()
.modules(new SampleModule())
.build());
public class SampleModule extends AbstractModule {
@Override
protected void configure() {
bind(SampleResource.class).in(Singleton.class);
bind(SampleBootstrap.class);
bind(CustomHeaderFilter.clas);
}
}
Guicey will recognize all (3) bindings and register extensions. The difference with classpath scan
or manual declaration is only that guicey will not declare default bindings for extensions
(by default, guicey creates untargetted bindings for all extensions: bind(Extension.class)
).
Tip
One extension may be found by classpath scan, declared manually and in binding, but it would still be considered as single registration (with existing binding).
Possible extensions¶
Guicey can recognize and install:
- Dropwizard tasks
- Dropwizard managed objects
- Dropwizard health checks
- REST resources
- REST extensions (exception mappers, message body readers etc.)
- Jersey features
- Filters, servlets, listeners
- Eager singletons, without direct guice registration
It can even simulate simple plugins.
Other extension types may appear with additional modules (e.g. jdbi adds support for jdbi mappers and repositories) or may be added by yourself. Any existing extension integration may be replaced, if it doesn't suite your needs.
Tip
If you'll feel confusing to understand what guicey use for it's configuration, just enable diagnostic logs:
GuiceBundle.builder()
.printDiagnosticInfo()
...
To see what extensions are supported you can always use:
GuiceBundle.builder()
.printAvailableInstallers()
And to see available guice bindings:
GuiceBundle.builder()
.printGuiceBindings()
Bundles¶
Guicey intended to extend dropwizard abilities (not limit). But to get access for these extended
abilities you'll need to use GuiceyBundle instead of dropwizard ConfiguredBundle
.
Bundles lifecycle and methods are the same, just guicey bundle provide more abilities.
Attention
This does not mean that dropwizard bundles can't be used! An opposite, guicey provides direct shortcuts for them in it's bundles:
public class MyBundle implements GuiceyBundle {
default void initialize(GuiceyBootstrap bootstrap) {
bootstrap.dropwizardBundles(new MyDropeizardBundle());
}
}
Additional features will be available for dropwizard bundles registered through guicey api and they also will appear in reports.
You can use dropwizard bundles as before if you don't need to register guice modules or use other guicey features from them. Usually dropwizard bundles used when required integration already implemented as dropwizard bundle (3rd parties).