Skip to content

RESTEasy Guice Integration

RESTEasy Guice has some simple integration with Guice 7.0. RESTEasy Guice will scan the binding types for a Guice Module for @Path and @Provider annotations. It will register these bindings with RESTEasy.

@Path("hello")
public class HelloResource {
   @GET
   @Path("{name}")
   public String hello(@PathParam("name") final String name) {
      return "Hello " + name;
   }
}

First you start off by specifying a Jakarta REST resource class. The HelloResource is just that. Next you create a Guice Module class that defines all your bindings:

import com.google.inject.Module;
import com.google.inject.Binder;

public class HelloModule implements Module {
    public void configure(final Binder binder) {
       binder.bind(HelloResource.class);
    }
}

You put all these classes somewhere within your WAR WEB-INF/classes or in a JAR within WEB-INF/lib. Then you need to create your web.xml file. You need to use the GuiceResteasyBootstrapServletContextListener as follows

<web-app>
    <display-name>Guice Hello</display-name>

    <context-param>
        <param-name>resteasy.guice.modules</param-name>
        <param-value>dev.resteasy.examples.guice.hello.HelloModule</param-value>
    </context-param>

    <listener>
        <listener-class>
            dev.resteasy.guice.GuiceResteasyBootstrapServletContextListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher
        </servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

GuiceResteasyBootstrapServletContextListener is a subclass of ResteasyBootstrap, so you can use any other RESTEasy configuration option within your web.xml file. Also notice that there is a resteasy.guice.modules context-param. This can take a comma delimited list of class names that are Guice Modules.

1. Registering resources and providers

Guice does not scan the classpath, so RESTEasy Guice can only see what your modules explicitly bind. Every @Path root resource and every @Provider must be bound in one of your modules; an unbound resource is simply not registered and its endpoints return 404.

public class MyModule implements Module {
    @Override
    public void configure(final Binder binder) {
        binder.bind(HelloResource.class);              // a @Path resource
        binder.bind(MyExceptionMapper.class);          // an @Provider
        binder.bind(GreetingService.class).to(GreetingServiceImpl.class);
    }
}

Resources are instantiated by Guice, so constructor injection uses Guice bindings. This means the Jakarta REST @Context annotation cannot be used on a constructor parameter — RESTEasy performs @Context injection on fields and setters only, after Guice has created the instance. To inject the request-scoped context objects (UriInfo, HttpHeaders, etc.) through a constructor, install the RequestScopeModule (see below) and use a plain @Inject constructor.

2. Request Scope

Add the RequestScopeModule to your modules to make the Jakarta REST context objects injectable with a plain Guice @Inject, bound to the current HTTP request. The following types are bound: UriInfo, HttpHeaders, Request, SecurityContext, HttpServletRequest, and HttpServletResponse (ServletConfig and ServletContext are not bound).

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.UriInfo;

@Path("example")
public class ExampleResource {
    private final UriInfo uriInfo;

    @Inject
    public ExampleResource(final UriInfo uriInfo) {
        this.uriInfo = uriInfo;
    }

    @GET
    public String get() {
        return uriInfo.getRequestUri().toString();
    }
}

The scope is also available directly as the dev.resteasy.guice.RequestScoped annotation for binding your own request-scoped objects.

3. Binding Jakarta REST utilities

Add the JaxrsModule to bind the Jakarta REST utility factories so they can be injected: jakarta.ws.rs.ext.RuntimeDelegate, jakarta.ws.rs.core.Response.ResponseBuilder, jakarta.ws.rs.core.UriBuilder, and jakarta.ws.rs.core.Variant.VariantListBuilder.

4. Configuring Stage

You can configure the stage Guice uses to deploy your modules by specific a context param, resteasy.guice.stage. If this value is not specified, RESTEasy uses whatever Guice’s default is.

<web-app>
    <display-name>Guice Hello</display-name>

    <context-param>
        <param-name>resteasy.guice.modules</param-name>
        <param-value>dev.resteasy.examples.guice.hello.HelloModule</param-value>
    </context-param>

    <context-param>
        <param-name>resteasy.guice.stage</param-name>
        <param-value>PRODUCTION</param-value>
    </context-param>

    <listener>
        <listener-class>
            dev.resteasy.guice.GuiceResteasyBootstrapServletContextListener
        </listener-class>
    </listener>

    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>
            org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher
        </servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

5. Custom Injector creation

GuiceResteasyBootstrapServletContextListener can be extended to allow more flexibility in the way the Injector and Modules are created. Three methods can be overridden: getModules(), withInjector() and getStage(). Register your subclass as the listener in the web.xml.

Override getModules() when you need to pass arguments to your modules' constructor or perform more complex operations.

Override withInjector(Injector) when you need to interact with the Injector after it has been created.

Override getStage(ServletContext) to set the Stage yourself.

<web-app>
    <!-- other tags omitted -->
    <listener>
      <listener-class>
         dev.resteasy.guice.GuiceResteasyBootstrapServletContextListener
      </listener-class>
    </listener>
</web-app>
public class MyServletContextListener extends GuiceResteasyBootstrapServletContextListener {

    @Override
    protected List<? extends Module> getModules(ServletContext context) {
        return List.of(new JpaPersistModule("consulting_hours"), new MyModule());
    }

    @Override
    public void withInjector(Injector injector) {
        injector.getInstance(PersistService.class).start();
    }
}

6. Migrating from prior editions of RESTEasy Guice

The group name and package name have both changed. If you are migrating from prior editions of RESTEasy Guice, you will need to update your dependencies and imports.

The new group name is 'dev.resteasy.guice' and the new package name is 'dev.resteasy.guice'.

6.1. Dependencies

6.2. Imports

Bulleted
  • Previous package name: org.jboss.resteasy.plugins.guice.

  • Current package name: dev.resteasy.guice

This update may be as simple as searching for org.jboss.resteasy.plugins.guice and replacing it with dev.resteasy.guice.

For most projects, that will be either changing the entry in web.xml to:

    <listener>
        <listener-class>
            dev.resteasy.guice.GuiceResteasyBootstrapServletContextListener
        </listener-class>
    </listener>

Or changing the import statement in a custom listener to:

import dev.resteasy.guice.GuiceResteasyBootstrapServletContextListener;

7. Releasing

Releasing the project requires permission to deploy to Maven Central see Maven Central Release Requirements. Once everything is setup, you simply need to run the ./release.sh script. There are two required parameters:

  1. -r or --release which is the version you want to release

  2. -d or --development which is the next development version.

By default the release version cannot contain SNAPSHOT and the development version, must container SNAPSHOT.

Example Command
./release -r 1.0.0.Final -d 1.0.1.Final-SNAPSHOT

7.1. Supported Arguments

Argument Requires Value Description

-d, --development

Yes

The next version for the development cycle.

-f, --force

No

Forces to allow a SNAPSHOT suffix in release version and not require one for the development version.

-h, --help

N/A

Displays this help

--notes-start-tag

Unused

Passes the --notes-from-tag and the argument to the gh create release command.

-p, --prerelease

Unused

Passes the --prerelease to the gh create release command.

-r, --release

Yes

The version to be released. Also used for the tag.

--dry-run

No

Executes the release in as a dry-run. Nothing will be updated or pushed.

--no-push

No

Executes the release in, but doesn’t actually push the changes to GitHub or publish the release on Maven Central.

-v, --verbose

No

Prints verbose output.

Any additional arguments are considered arguments for the Maven command.

About

RESTEasy integration with Google Guice

Resources

Code of conduct

Contributing

Security policy

Stars

7 stars

Watchers

6 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages