users@jersey.java.net

Re: [Jersey] Spring, _at_Singleton resources and thread-safety

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 13 Oct 2008 09:47:54 +0200

Hi Jeff,

On Oct 12, 2008, at 9:49 PM, Jeff Schmidt wrote:

> Hello:
>
> I'm still going through all of the JSR 311 and Jersey documentation,
> various blog posts, sample code etc. The main things I need to nail
> down in a hurry is understanding resource life cycles and
> integration with Spring. A further possible complication is the
> project I'm working on is stuck with Spring 1.2 for the time being
> (running in Tomcat 6.0.14). My understanding is that there is more
> direct Spring integration for Jersey for Spring 2.0 and 2.5. But,
> that won't help me. :)
>

You might have to write your own ComponentProvider if you need to
support Spring 1.2 and the 2.0 support does not work for you.


> There are numerous DAOs, services, data providers and whatnot
> defined in the Spring application context. My JAX-RS resource
> classes need to make use of these beans. It seems I need to create
> singleton resources and configure them via Spring (again v 1.2).
> This appears to have been done successfully for a small REST API
> implemented using Jersey 0.6ea and the JerseySpringServlet class
> defined a while back by Paul Sandoz at http://blogs.sun.com/sandoz/entry/integrating_jersey_and_spring_take
> .
>
> There is only one root resource class, and it has the @Singleton
> annotation. This class is configured via Spring, and things seems to
> work okay. But, this API needs to be expanded significantly, and I
> would like to incorporate sub-resource locators to make the
> implementation more modular. In doing so, the sub-resource locator
> classes will have their own Spring injected collaborators etc. I
> would like to avoid defining all of the collaborators in the root
> resource and provide them as constructor arguments to the sub-
> resource locator classes. This way, the sub-locator classes can be
> developed more independently.
>

You can inject ResourceContext:

     @Path("{id}")
     public SubResource getSubResource(@Context ResourceContext rc) {
         return rc.getResource(SubResource.class);
     }

Or you can do:

     @Path("{id}")
     public Class<SubResource> getSubResource(@Context ResourceContext
rc) {
         return SubResource.class;
     }

If you just obtain the Spring injected reference to SubResource then
Jersey will not perform injection onto the fields.


> In Paul's blog post, the difference between using Spring prototype
> and singleton beans was demonstrated; but only as root resources.
> How about as sub-resource locator classes? All of the examples I've
> seen thus far show the root resource (singleton or not) returning a
> newly constructed sub-resource locator instance, providing already
> JAX-RS injected information via the constructor arguments. I want to
> (Spring) inject my root resources with one or more Spring configured
> sub-resource locator classes, and return that instance rather than
> construct a new one per request.
>
> For singletons, the methods need to be thread-safe. Looking at
> "Rules of Injection" at http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features
> , it seems I can inject the request related information in the
> individual methods of the sub-resource locator singleton, rather
> than use field level injection, or pass that information via
> constructor arguments.
>

Fields can be used on singletons as well for @Context related
injection, but not for parameters.

Parameters on constructors are problematic because in such cases
Spring wants construct rather than Jersey. So in such cases avoid
Jersey-specific stuff in constructors.


> A simple example, using Jersey 0.8 in Netbeans 6.1.
>
> @Singleton
> @Path("/exroot")
> public class RootResource {
>
> //TODO: Inject via Spring
> protected SubResource subResource = new SubResource();
>
> public RootResource() {
> }
>
> @GET
> @ProduceMime("text/plain")
> public String getXml(
> @Context UriInfo uriInfo,
> @QueryParam("param") String param) {
>
> return "root, param: " + param;
> }
>
> @Path("{id}")
> public SubResource getSubResource() {
> return subResource;
> }
> }
>
> @Singleton
> public class SubResource {
>
> //TODO: Inject via Spring
> protected String someSpringProperty = "propertyValue";
>
> public SubResource() {
> }
>
> @GET
> @ProduceMime("text/plain")
> public String getXml(
> @Context UriInfo uriInfo,
> @PathParam("id") String id,
> @QueryParam("param") String param) {
>
> return "sub-root, id: " + id + ", param: " + param;
> }
> }
>
> This example works as I'd expect in Netbeans, though I'm not yet
> defining these beans in a Spring application context. But as far as
> thread safety goes, does this make sense?

Yes, again you can use @Context UriInfo on fields as well, Jersey will
ensure the injected instance is thread safe.


> By not using field level injection of request related information,
> and instead assigning it to the methods of the resource or and sub-
> resource locator classes, is thread safety ensured? Also, does
> SubResource need the @Singleton annotation?
>

In your case, yes, as this synchronizes Jersey with the Spring scope.

Paul.

> Thanks!
>
> Jeff
> --
> Jeff Schmidt
> 535 Consulting
> jas_at_535consulting.com
> (408) 205-7697
>
>
>
>