Practical advice on using Jersey and Guice for RESTful service
Asked Answered
H

11

64

From what I can find online, the state of the art for Guice + Jersey integration has stagnated since 2008 when it appears both teams reached an impasse. The crux of the issue is that JAX-RS annotations perform field and method injection and this doesn't play nicely with Guice's own dependency injection.

A few examples which I've found don't go far enough to elucidate:

  • Iqbalyusuf's post on Jersey + Guice on Google App Engine Java suffers from a lot of boilerplate (manually getting and calling the injector). I want binding and injection should happen behind the scenes via Guice annotations.

  • Jonathan Curran's article Creating a RESTful service with Jersey, Guice, and JSR-250 gave me hope because it's much more current (2010), but went no further than showing how to start up a Jersey service inside of a Guice ServletModule. However, there are no examples of doing any real dependency injection. I suppose that was left as an exercise for the reader. Curran's post may in fact be the correct first step towards wiring up Guice and Jersey and so I plan on starting with that.

  • tantalizingly James Strachan writes:

    JAX-RS works well with dependency injection frameworks such as Spring, Guice, GuiceyFruit or JBossMC - you can basically pick whichever one you prefer.

    But I see no evidence that is true from a practitioner's point of view.

What I find lacking are practical examples and explanations on how to combine JAX-RS and Guice annotations. For instance:

  • I believe I cannot use constructor injection with any resource as Jersey wants to control this
  • I'm uncertain whether I can combine @Inject with @PathParam, @QueryParam, et al.
  • How to use injection in a MessageBodyWriter implementation

Does anyone have examples, preferably with source, of non-trivial application which combines Jersey and Guice without sacrificing one or the other in the process? I'm keeping on this road regardless, but the bits and pieces on the Jersey and Guice lists makes me think I'm repeating the work of others who came before me.

Husky answered 19/4, 2010 at 18:44 Comment(1)
I cannot think of any use-case for combining "@Inject with @PathParam, @QueryParam" annotations. Could you provide one?Quillen
K
52

Guice integration with Jersey has not stagnated. The opposite is true. Thanks to Paul and his cohorts behind Jersey, the latest 1.7 release contains a special JerseyServletModule class to work with Guice-based servlets. Guice-based constructor injection into JAX-RS resource works! The issue is using JAX-RS annotations such as @QueryParam in the constructor of a JAX-RS resource. You don't need it! You use Guice for POJO injection all the way including singletons. Then JAX-RS is just icing on the cake for parsing HTTP-based RESTful APIs such as URL path, query parameters, content-type and etc. You don't need an "industrial strength" example either. Both Guice and Jersey are already battle tested. You just need a complete working example to see how it works. Then you can experiment advanced features on your own. Check out the following link for a complete example using Guice 3.0 and Jersey 1.7, which are all latest releases:
http://randomizedsort.blogspot.com/2011/05/using-guice-ified-jersey-in-embedded.html

Kleenex answered 30/5, 2011 at 5:9 Comment(6)
+1 searching on Google for jersey+guice brings up a lot of outdated posts, so it's difficult to see that the state is really good as of now. This is really good news!Bobbette
changing the accepted answer to this one. @sunny-gleason's is still good, but this one goes the farthest showing constructor injection managed by Guice. Thanks @KleenexHusky
See jersey.java.net/nonav/apidocs/1.11/contribs/jersey-guice/com/… for an overview of what goes into web.xml.Lasky
For anyone looking for a Dropwizard (0.6.1+) solution then see github.com/HubSpot/dropwizard-guice. It has a useful example project to get you started with request scoped Guice. Be aware that DW 0.6.1 doesn't call initialize() on the GuiceBundle so you need to do that yourself (not shown in the example which is for 0.6.2+)Plutonian
For anyone just landing on this, Guice injection into JAX-RS resources does not work with Jersey 2.x. Upvote this issue if you want to see it (already the most popular Jersey issue).Encrata
I do not believe this answer holds true when talking about (latest) Jersey2 + Guice 3. You need to use a GuiceIntoHK2Bridge. You cannot inject Guice managed objects into a Jersey resource without explicitly binding them!Manganese
M
20

I created a Guice/Jersey/Jetty/Jackson sample application here:

http://github.com/sunnygleason/j4-minimal

If you have any questions or suggestions for how to improve the example, feel free to message me via github. The goal is to make this a very accessible introduction to REST on the Java stack.

Hope this helps - have a great day!

-Sunny

Mccabe answered 21/7, 2010 at 5:13 Comment(3)
That example was great, and got me 99% of the way there, but from what i can tell it doesn't actually end up using jackson. You'll discover this if you end up trying to use jackson annotations to do things like hide fields (@JsonIgnore). To close the loop, you need to change 'serve("").with(GuiceContainer.class);' to something like 'serve("").with(GuiceContainer.class, ImmutableMap.of(JSONConfiguration.FEATURE_POJO_MAPPING, "true")'. You can also remove the JacksonJsonProvider bindings, since they don't seem to be @Inject-ed anywhere.Doorpost
Thanks for posting the sample code. Is it possible to eliminate the need for the EmptyServlet class? Perhaps using some newer functionality in Jersey or Guice (or jersey-guice)? :)Tendon
I found I didn't need the EmptyServlet when running the example inside Jersey Grizzly 2 TestContainer, the ServletContextListener and Filter were enoughFlapper
Z
9

Inspired by Sunnys sample application I've created a similar sample project that uses standard WAR files for deployment, e.g. in Apache Tomcat. You can find the project here:

https://github.com/danbim/template-guice-jersey-tomcat

Have fun! Daniel

Zenda answered 20/12, 2010 at 13:47 Comment(1)
Daniel thanks for this example it really helped me. I've menage to get it going but when I want to return a bit complex object with List<POJO> as a field the List just isnt there in the JSON. Can you shed some light on this?Disqualification
Q
3

I believe I cannot use constructor injection with any resource as Jersey wants to control this

You cannot use guice's constructor injection because creation of resource is managed by jersey. In this case you can use jersey's @Inject annotation before constructor parameter you want to get injected:

public NewsResource(@Inject NewsService service)
Quillen answered 21/4, 2010 at 13:4 Comment(0)
A
3

I was having similar problems initially trying to use Guice to do constructor injection on my Jersey annotated classes, but eventually got it working, albeit with a fairly trivial application.

I followed the instructions here: jersey-guice javadoc

The trick in my case was that I needed to remove the standard Jersey configuration from my web.xml (like the Jersey ServletContainer) and keep only the Guice listener and Guice filter. Once I did that Guice was being called to create my JAX-RS annotated object, and Jersey was injecting my JAX-RS annotated methods (like @GET, etc.) as expected.

Acton answered 18/11, 2010 at 22:28 Comment(1)
the link above is broken. does anyone have an updated reference?Shaquitashara
R
3

Although Sunny Gleason's example is great, it is a bit outdated now.

So, after struggling a lot today trying to make Guice and Jersey play nice with each other, I created the following sample project to get you started:

https://github.com/MaliciousMustard/gradle-guice-jersey-jetty

This project is using the following technologies:

  1. Guice for DI
  2. Jersey for the RESTful API
  3. Jackson for POJO to JSON mapping
  4. Jetty for the web-server
  5. Gradle

I guess the most important thing is that you don't have to explicitly specify every new resource class you're adding. As long as you're adding them to the package that is being scanned (look at malicious.mustard.modules.JerseyModule), they will be found automatically!

Remains answered 29/2, 2016 at 0:5 Comment(0)
A
2

GWizard includes a module that gives you out-of-the-box integration between Jersey2 and Guice. Here's an example of a complete JAX-RS service:

public class Main {
    @Path("/hello")
    public static class HelloResource {
        @GET
        public String hello() {
            return "hello, world";
        }
    }

    public static class MyModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(HelloResource.class);
        }
    }

    public static void main(String[] args) throws Exception {
        Guice.createInjector(new MyModule(), new JerseyModule()).getInstance(Run.class).start();
    }
}

Note that this is based on the Squarespace jersey2-guice adapter, which may not function properly with future point releases of Jersey. GWizard also offers a RESTEasy JAX-RS module, which is preferred.

Here is a blog entry about this that might help: http://blorn.com/post/107397841765/guice-and-jersey-2-the-easy-way

Alyce answered 7/1, 2015 at 10:31 Comment(0)
T
1

These examples were all great starts for me, but I wanted a full MVC stack using Jersey-Guice at it's core. I've been working on refining that for sometime. As of this week this MVC stack is fully deployed to Maven Central repository as an archetype. This means you can now create a new Jersey-Guice stack with one Maven command:

mvn archetype:generate \
    -DarchetypeGroupId=org.duelengine \
    -DarchetypeArtifactId=duel-mvc-archetype \
    -DarchetypeVersion=0.2.1

This automatically generates your own project with you specified package naming so you don't have to manually edit a template project.

See the project Readme.md for more details: https://bitbucket.org/mckamey/duel-mvc

Details on the dual-side views (client-side template & server-side views) I use are here: https://bitbucket.org/mckamey/duel but you could replace with whatever you use.

Tantalic answered 23/7, 2011 at 16:50 Comment(0)
L
1

The Jersey-Guice plugin Javadoc provides a pretty good description:

http://jersey.java.net/nonav/apidocs/1.1.5/contribs/jersey-guice/com/sun/jersey/guice/spi/container/servlet/package-summary.html

Lasky answered 8/3, 2012 at 5:20 Comment(1)
could you please check my question #32699920 i need help and thank u very mcuhDemean
M
0

I found an interesting project for lightweight Jetty+Guice+Jackson web services: https://github.com/talis/jersey-common/

Mallee answered 10/3, 2012 at 12:27 Comment(0)
E
0

I created a Guice 4.2, Jetty 9.4 and Jersey 2.7 sample application:

https://github.com/bnsd55/jetty-jersey-guice-starter-kit

As Sunny said:

If you have any questions or suggestions for how to improve the example, feel free to message me via github. The goal is to make this a very accessible introduction to REST on the Java stack.

Exodontist answered 25/9, 2018 at 5:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.