Skip to content

Setup

Getting started guide briefly shows the most commonly used features. Advanced descriptions of guicey concepts may be found in the concepts section.

Installation

Core guicey could be used directly:

Maven:

<dependency>
  <groupId>ru.vyarus</groupId>
  <artifactId>dropwizard-guicey</artifactId>
  <version>7.1.3</version>
</dependency>

Gradle:

implementation 'ru.vyarus:dropwizard-guicey:7.1.3'

BOM

But, it would be simpler to use it with BOM because of simplified versions management for guice, dropwizard and guicey modules:

Gradle:

dependencies {
    implementation platform('ru.vyarus:dropwizard-guicey:7.1.3')
    // uncomment to override dropwizard and its dependencies versions
//    implementation platform('io.dropwizard:dropwizard-dependencies:4.0.7')

    // no need to specify versions
    implementation 'ru.vyarus:dropwizard-guicey'

    // example modules without versions
    implementation 'io.dropwizard:dropwizard-auth'
    implementation 'com.google.inject:guice-assistedinject'

    testImplementation 'io.dropwizard:dropwizard-testing'
}

Maven:

<dependencyManagement>  
    <dependencies>
        <dependency>
            <groupId>ru.vyarus</groupId>
            <artifactId>dropwizard-guicey</artifactId>
            <version>7.1.3</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>4.0.7</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency> -->                 
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>ru.vyarus</groupId>
        <artifactId>dropwizard-guicey</artifactId>
    </dependency>
</dependencies>

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()
                .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 the javadoc).

Auto configuration (activated with enableAutoConfig) means that guicey will search for extensions in the application package and subpackages. Extension classes are detected by "feature markers": for example, resources has @Path annotation, tasks extends Task etc.

Tip

By default, auto configuration enabled for application package, but you can declare manually any packages for classpath scan:

 .enableAutoConfig("com.mycompany.foo", "com.mycompany.bar")

The application could be launched by running main class (assumes you will use an IDE run command):

SampleApplication server

Note

a config.yml is not passed as a parameter because we don't need additional configuration yet

Adding a Resource

Create a custom rest resource class:

@Path("/sample")
@Produces("application/json")
public class SampleResource {

    @GET
    @Path("/")
    public Response ask() {
        return Response.ok("ok").build();
    }
}

After creating your resource, when you run the application the 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 scoped objects like jakarta.servlet.http. HttpServletRequest, jakarta.servlet.http.HttpServletResponse, jakarta.ws.rs.core.UriInfo, org.glassfish.jersey.server. ContainerRequest, etc, you must wrap the desired objects in a 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();
    }
}

The example resource now obtains the caller's remote ip address and returns it in the response body.

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).

Adding a Managed Object

Dropwizard managed objects are extremely useful for managing resources.

Create a 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");
    }
}

The managed class will be automatically discovered and installed by Guicey. Guicey always reports installed extensions when they are not reported by dropwizard itself. In the start-up logs of the application, you can see:

INFO  [2017-02-05 11:59:30,750] ru.vyarus.dropwizard.guice.module.installer.feature.ManagedInstaller: managed =

    (ru.vyarus.dropwizard.guice.examples.service.SampleBootstrap)

Adding A 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 a 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() {
    }
}

The filter will only pass through requests with the user=me request parameter. It is used just to show how to register custom filters with annotations. The implementation itself is not useful.

Upon start-up, new logs will confirm successful 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.

Adding a Guice Module

Guice module registration:

bootstrap.addBundle(GuiceBundle.builder()
                ...
                .modules(new SampleModule())
                .build());

Multiple modules could be registered at once:

.modules(new SampleModule(), new Some3rdPartyModule())

Note

The above registration occurs in dropwizard initialization phase, when neither Configuration nor Environment objects are available. If you need either of them in a module, you may register a module in guicey bundle's run method or use marker interfaces.

Manual mode

If you don't want to use classpath scanning for extension discovery, 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 .enableAutoConfig() and the explicit declaration of desired extensions.

Tip

Explicit extension declaration could be used together with enableAutoConfig (classpath scan). For example, a classpath scan may only scan for extensions in your application's package and subpackages, while extensions outside of those packages may be specified separately. This avoids large class path scans and improves the startup time of your application.

Note

Only distinct extensions are registered. Duplicates are not registered. If some extension is registered manually and also found with auto config, then only one instance of that extension will be registered. If an extension is registered multiple times manually, the same rules apply and only one extension instance will be registered.

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.class);                        
    }   
}

Guicey will recognize all three bindings and register extensions. The difference with classpath scanning or manual declaration is only that guicey will not declare default bindings for extensions (by default, guicey creates untargeted bindings for all extensions: bind(Extension.class)).

Tip

An extension may be found three ways: by classpath scan, explicit extension declaration on the GuiceBundle, and by declaring a binding in a guice module. Even if all three were used, the extension would only be registered once.

Recognized Extensions

Guicey can recognize and install:

It can even simulate simple plugins.

Other extension types may be recognized with additional installed modules. For example, jdbi adds support for jdbi mappers and repositories. You may add others yourself. Any existing extension integration may be replaced, if it doesn't suit your needs.

Tip

If you are unsure or don't understand what guicey is using for its configuration, 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()    

Guicey Bundles

Guicey Bundles are intended to extend the functionality of Dropwizard Bundles, not limit them. To get access for these extended abilities you'll need to use GuiceyBundle instead of a dropwizard ConfiguredBundle.

The Guicey Bundle lifecycle and methods are the same as Dropwizard Bundles. Guicey Bundles simply provide more functionality.

Attention

This does not mean that dropwizard bundles can't be used! An opposite, Guicey provides direct shortcuts for them in its 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 always use vanilla Dropwizard Bundles if you don't need to register guice modules or use other guicey features. Usually Dropwizard Bundles used when the required integration has already implemented as a 3rd party Dropwizard Bundle.