users@jersey.java.net

Re: Jersey 0.6 and Spring

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 19 Feb 2008 10:47:17 +0100

Hi Tom,

When you run your application and issue a request are you seeing some
output like the following:

   Scanning for root resource and provider classes in the paths:
     <web app>/build/web/WEB-INF/lib
     <web app>/build/web/WEB-INF/classes
   Root resource classes found:
     class com.atlassian.crucible.spi.rpc.RestReviewService

? If so your ComponentProvider.getInstance method should be getting
called with Scope.WebApplication and the root resource Class shown
above. If not how are you configuring the web application ?


I have attempted to improve the JavaDoc in the latest build. Currently
the way it is implemented is Jersey will defer to the supplied
ComponentProvider for all instances of components it needs to create
(including infrastructure components). Note that root resource classes
are just one type of component in Jersey. From the perspective of the
ComponentProvider it does not care what the type of the component is but
should care what the requested scope is.

If the supplied ComponentProvider returns null (meaning that it does not
support the the component) then Jersey will instantiate the component
instead i.e. it is a sort of "keep on trucking" approach, which means
one can mix Spring and non-Spring managed root resource classes as well
as other types of component.

This is why the example SpringComponentProvider does the following:

         private String getBeanName(Class c) {
             // Look up the bean names
             String names[] = springContext.getBeanNamesForType(c);
             if (names.length == 0) {
                 // If not found return null
                 return null;
             } else if (names.length > 1) {
                 throw new RuntimeException(
                         "Multiple configured beans for "
                         + c.getName());
             }
             return names[0];
         }

         public Object getInstance(Scope scope, Class c)
                 throws InstantiationException, IllegalAccessException {

             // look up the bean name from the class
             String beanName = getBeanName(c);
             // Cannot find the beanName for the class
             // return null and let Jersey be responsible for
             // managing that component
             if (beanName == null) return null;

             ...
          }

I could restrict things such that the infrastructure components are
instantiated and managed by Jersey without deferring to the
ComponentProvider but application-defined components are deferred to the
supplied ComponentProvider. For example if one wants application-defined
message body readers/writers to be managed by Spring, then one could
have this class:

   @Provider
   public class MyReader implements MessageBodyReader<MyType> {
      // inject some Spring stuff here
      ...
   }

registered in the application context as a singleton. Jersey will defer
to the ComponentProvider to instantiate this class and will ask the
component provider that the life-cycle should be WebApplication
(equivalent to singleton in Spring).

I could probably better name the Scope enums, perhaps keep it the same
as in Spring would be clearer?

Hope this helps,
Paul.

Tom Davies wrote:
> Hi,
>
> I'm trying to follow these instructions
> http://blogs.sun.com/sandoz/entry/integrating_jersey_and_spring_take for
> using Jersey and Spring.
>
> I'm finding that my Spring bean is not getting picked up by the
> ComponentProvider.
>
> I'm suffering from a complete lack of understanding as to how the
> ComponentProvider works: looking in the debugger I see that the
> component provider is asked for beans implementing any of class
> com.sun.ws.rest.impl.provider.entity.StringProvider, class
> com.sun.ws.rest.impl.provider.entity.ByteArrayProvider, class
> com.sun.ws.rest.impl.provider.entity.FileProvider, class
> com.sun.ws.rest.impl.provider.entity.InputStreamProvider, class
> com.sun.ws.rest.impl.provider.entity.DataSourceProvider, class
> com.sun.ws.rest.impl.provider.entity.MimeMultipartProvider, class
> com.sun.ws.rest.impl.provider.entity.FormURLEncodedProvider, class
> com.sun.ws.rest.impl.provider.entity.XMLJAXBElementProvider.
>
> My bean class looks like:
>
> @Path("/review")
> @Singleton
> public class RestReviewService {
> @Autowired
> private ReviewService reviewService;
>
> @GET
> @Path("reviews")
> @ProduceMime("text/plain")
> public List<ReviewData> getAllReviews() {
> return reviewService.getAllReviews();
> }
> }
>
>
> and its spring declaration like:
> <bean id="restReviewService"
> class="com.atlassian.crucible.spi.rpc.RestReviewService"
> scope="singleton" autowire="autodetect"/>
>
> so I don't think it is going to implement any of those interfaces, and
> so won't be seen.
>
> Can someone help to clear up my misconceptions?
>
> Thanks,
> Tom
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109