users@jersey.java.net

Re: [Jersey] ContainerRequestFilter as Spring component?

From: Mahesh Venkat <mhvenkat_at_gmail.com>
Date: Fri, 15 Oct 2010 19:32:02 -0700

Hi Paul,

I recently migrated from jersey-1.1.5 to jersey1.4 and I am facing similar
issue in ContainerRequestFilter.
I use the com.sun.jersey.spi.spring.container.servlet.SpringServlet.

Until I migrated to Jersey 1.4 my code that implements
ContainerRequestFilter was working fine. Now Isee the following error on the
first REST invocation:
*19:16:33,949 SEVERE [Errors] The following errors and warnings have been
detected with resource and/or provider classes:
  SEVERE: Missing dependency for field:
com.sun.jersey.spi.container.ContainerRequest
com.yodlee.rest.RestContainerRequestFilter.containerRequest*
19:16:33,949 SEVERE [SpringServlet] Exception occurred when intialization
com.sun.jersey.spi.inject.Errors$ErrorMessagesException
        at
com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170)
        at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:137)
        at
com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:203)
        at
com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:695)
        at
com.sun.jersey.spi.spring.container.servlet.SpringServlet.initiate(SpringServlet.java:117)
        at
com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:287)
        at
com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:587)
        at
com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:213)
        at
com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:342)
        at
com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:516)
        at javax.servlet.GenericServlet.init(GenericServlet.java:212)

The code snippet is ...
@Provider
public class RestContainerRequestFilter implements ContainerRequestFilter {

       private final static Logger logger =
Logger.getLogger(RestContainerRequestFilter.class.getName());

        /**
         * <p>The URI information for this request.</p>
        */
        @Context UriInfo uriInfo;
     * @Context ContainerRequest containerRequest;*
        @Context HttpServletRequest httpRequest; // these are Threadlocal
variables
        @Context HttpServletResponse httpResponse;

        public RestContainerRequestFilter() {}

            // -------override ContainerRequestFilter Methods
-------------------------------
            @Override
           * public ContainerRequest filter(@Context ContainerRequest
containerRequest) {*
            ...
            }

Any clues?

Appreciate your help.

--Mahesh


On Thu, Oct 14, 2010 at 6:10 AM, Nico Rehwaldt <nico.rehwaldt_at_web.de> wrote:

> I attached a new test case. Don’t know, what happened to the last one but
> the point cut was incorrect.
> This one should work. I am using Glassfish to deploy it but Tomcat will do
> it as well.
>
> Nico
>
> -----Ursprüngliche Nachricht-----
> Von: Paul Sandoz [mailto:Paul.Sandoz_at_oracle.com]
> Gesendet: Donnerstag, 14. Oktober 2010 11:40
> An: users_at_jersey.dev.java.net
> Betreff: Re: AW: AW: AW: [Jersey] ContainerRequestFilter as Spring
> component?
>
>
> On Oct 13, 2010, at 11:54 PM, Nico Rehwaldt wrote:
>
> > Hey Paul,
> >
> > Part 6.6 "Proxying mechanisms" in the spring reference documentation
> > ([1])
> > states
> > "Spring AOP uses either JDK dynamic proxies or CGLIB to create the
> > proxy for a given target object. (JDK dynamic proxies are preferred
> > whenever you have a choice)."
> >
> > "Having a choice" could mean that spring uses the proxy if the
> > interface mirrows the api of a class (which is the case for MyFilter
> > in my test setup).
> >
>
> Thanks, understand better now.
>
>
> > Jersey itself (as I understood it) uses the Spring component provider
> > factory to get an instance of the filter class from spring which
> > returns the java.lang.Proxy. However it cannot be handled by the
> > SpringComponentProviderFactory (which returns null then) and the
> > Filter will be instantiated for a second time (without injection
> > taking place).
> >
>
> Jersey will call the following to get an instance of the filter,
> passing in the (unproxied) Class of the filter:
>
> public IoCComponentProvider getComponentProvider(ComponentContext
> cc, Class c) {
> final Autowire autowire = (Autowire)
> c.getAnnotation(Autowire.class);
> if (autowire != null) {
> if (LOGGER.isLoggable(Level.FINEST)) {
> LOGGER.finest("Creating resource class " +
> c.getSimpleName() +
> " annotated with @" +
> Autowire.class.getSimpleName() +
> " as spring bean.");
> }
> return new SpringInstantiatedComponentProvider(c,
> autowire);
> }
>
> final String beanName = getBeanName(cc, c, springContext);
> if (beanName == null) {
> return null;
> }
>
> final String scope = findBeanDefinition(beanName).getScope();
> return new
> SpringManagedComponentProvider(getComponentScope(scope), beanName, c);
> }
>
>
> > That is the only reasonable answer for me at the moment.
> > Could you reproduce my findings with the supplied test case?
> >
>
> No. It worked for <aop:aspectj-autoproxy /> and <aop:aspectj-autoproxy
> proxy-target-class="true" />.
>
> I don't think the proxying is occurring. The following is not printed
> out in the logs:
>
> Filter executed!
>
> by the MyAspect. Is there something config missing from your attached
> app?
>
> I am using Tomcat 6.0 to deploy. What are you using?
>
> Paul.
>
> > Nico
> >
> > [1]:
> >
>
> http://static.springsource.org/spring/docs/2.5.x/reference/aop.html#aop-auto
> > proxy-force-CGLIB
> >
> > -----Ursprüngliche Nachricht-----
> > Von: Paul Sandoz [mailto:Paul.Sandoz_at_oracle.com]
> > Gesendet: Mittwoch, 13. Oktober 2010 15:19
> > An: users_at_jersey.dev.java.net
> > Betreff: Re: AW: AW: [Jersey] ContainerRequestFilter as Spring
> > component?
> >
> > Hi Nico,
> >
> > I cannot reproduce. The sample you attach works for me if i:
> >
> > 1) <aop:aspectj-autoproxy/> and/or
> >
> > 2) comment out the cglib dependency from the pom.
> >
> > I don't understand why a call to the Jersey Spring
> > SpringComponentProviderFactory.getComponentProvider would pass in a
> > class
> > that is of java.lang.Proxy. Since the resource filter class name is
> > registered is in the web.xml that is the class name that will be
> > used to
> > load the class and that class will be passed to the
> > pringComponentProviderFactory.getComponentProvider method. Only the
> > instance
> > looked up should be of a proxyied class.
> >
> > java.lang.Proxy only works for interfaces, so presumably it is
> > applied to
> > interfaces that are implemented by MyFilter?
> >
> > Paul.
> >
> > On Sep 24, 2010, at 10:58 AM, Nico Rehwaldt wrote:
> >
> >> Hey Paul,
> >>
> >> I confused the filter registration with the registration of resource
> >> classes, of course I register them programmatically (via
> >> com.sun.jersey.spi.container.ContainerRequestFilters init parameter
> >> in
> >> web.xml).
> >>
> >> You are right, the filter does not have to be registered as a
> >> resource
> >> class to make it work as a spring bean. The only thing which has to
> >> be
> >> changed is, that IF spring creates a proxy for a registered bean, in
> >> our case the filter, THEN it must be a CGLib proxy.
> >>
> >> In my case this happens, because I annotated the filter method with
> >> the @Transactional annotation to safely perform some database access
> >> on it.
> >> Thus, spring will create a proxy around it.
> >>
> >> I attached a test case for the problem. It contains a filter
> >> (test.MyFilter), a resource class which is injected into the filter
> >> (test.MyResource) and an Aspect which contains a pointcut on the
> >> filter method. The least is needed to force spring to create a proxy
> >> of the filter instance.
> >>
> >> If you jump into the spring configuration in src/main/resources/
> >> spring.xml you can enable usage of CGLib proxies (instead of java
> >> ones) for <aop:aspect-autoproxy /> (see [1]). With CGLib proxies used
> >> the filter works as expected, without it fails with a null pointer
> >> exception.
> >>
> >> The problem originates in the fact, that com .sun
> >> .jersey.spi.spring.container.SpringComponentProviderFactory#getBeanNa
> >> me returns null for instances of java.lang.reflect.Proxy and that
> >> therefore no IoCComponentProvider is returned for the proxy instance.
> >>
> >> Hope this helps!
> >>
> >> Nico
> >>
> >> [1]:
> >> http://static.springsource.org/spring/docs/2.5.x/reference/aop.html
> >>
> >> -----Ursprüngliche Nachricht-----
> >> Von: Paul Sandoz [mailto:Paul.Sandoz_at_oracle.com]
> >> Gesendet: Donnerstag, 23. September 2010 19:23
> >> An: users_at_jersey.dev.java.net
> >> Betreff: Re: AW: [Jersey] ContainerRequestFilter as Spring component?
> >>
> >>
> >> On Sep 22, 2010, at 4:46 PM, Nico Rehwaldt wrote:
> >>
> >>> Hey Paul,
> >>>
> >>> the filter is recognized via package scanning (not
> >>> programmatically).
> >>
> >> Filters need to be explicitly registered, as described here:
> >>
> >>
> >> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/
> >> jersey
> >> /api/c
> >> ontainer/filter/package-summary.html
> >>
> >> because ordering of filters is important. It should not be necessary
> >> for the filter to be registered in the set of classes of the resource
> >> config. So i am not sure what is going on exactly.
> >>
> >> If it is possible to wrap something up in a simple reproducible test
> >> case that would help a lot.
> >>
> >>
> >>
> >>> As the filter is annotated (and instantiated) as a spring bean, I
> >>> wondered, why it does not have any fields injected.
> >>>
> >>> However, I did some research and found out, what the problem is: The
> >>> filter gets instantiated as a spring bean and has all fields
> >>> injected.
> >>> When Jersey wants to "use it" it will try to obtain it using the
> >>> SpringComponentProviderFactory which is registered in the
> >>> SpringServlet.
> >>> This fails and Jersey will instantiate the class (again), but on its
> >>> own and with no injection taking place. I found two reasons for this
> >>> behavior.
> >>>
> >>> * At first, the filter class is not registered as a ResourceClass in
> >>> the Jersey app (I think this should happen in
> >>> SpringComponentProviderFactory#register but it only registers
> >>> provider and root resource classes). I changed the method to
> >>> accomplish this:
> >>>
> >>> private void register(ResourceConfig rc,
> >>> ConfigurableApplicationContext
> >>> springContext) {
> >>> String[] names =
> >>> BeanFactoryUtils.beanNamesIncludingAncestors(springContext);
> >>>
> >>> for (String name : names) {
> >>> Class<?> type =
> >>> ClassUtils.getUserClass(springContext.getType(name));
> >>> if (ResourceConfig.isProviderClass(type)) {
> >>> LOGGER.info("Registering Spring bean, " + name +
> >>> ", of type " + type.getName() +
> >>> " as a provider class");
> >>> rc.getClasses().add(type);
> >>> } else if (ResourceConfig.isRootResourceClass(type)) {
> >>> LOGGER.info("Registering Spring bean, " + name +
> >>> ", of type " + type.getName() +
> >>> " as a root resource class");
> >>> rc.getClasses().add(type);
> >>> } else if
> >>> (ContainerRequestFilter.class.isAssignableFrom(type))
> >>> {
> >>> LOGGER.info("Registering Spring bean, " + name +
> >>> ", of type " + type.getName() +
> >>> " as a filter class");
> >>> rc.getClasses().add(type);
> >>> }
> >>> }
> >>> }
> >>>
> >>
> >> Instead of modifying the above annotate your filter with @Provider.
> >>
> >> Paul.
> >>
> >>> * As a second problem, the filter was an instance of
> >>> java.lang.reflect.Proxy (the class name was something like $Proxy..
> >>> $).
> >>> As I read somewhere it is due to the fact, that spring uses the java
> >>> proxies in favor of the CGLib ones, if the class has an interface
> >>> present (and the filter has). A java.lang.reflect.Proxy isn't
> >>> recognized as a bean in SpringComponentProviderFactory
> >>> #getComponentProvider(ComponentContext cc, Class c), as its bean
> >>> name
> >>> will be null. Therefore null instead of an injection provider is
> >>> returned and jersey creates the filter on its own (again).
> >>>
> >>> Everything works fine now after I forced spring to use CGLib proxies
> >>> and made the above changes to the SpringComponentProviderFactory.
> >>>
> >>> Nico.
> >>>
> >>> -----Ursprüngliche Nachricht-----
> >>> Von: Paul Sandoz [mailto:Paul.Sandoz_at_ORACLE.COM]
> >>> Gesendet: Donnerstag, 23. September 2010 00:37
> >>> An: users_at_jersey.dev.java.net
> >>> Betreff: Re: [Jersey] ContainerRequestFilter as Spring component?
> >>>
> >>> Hi Nico,
> >>>
> >>> How are you registering the SecurityFilter with Jersey? are you
> >>> instantiating it yourself and programatically registering it?
> >>>
> >>> Paul.
> >>>
> >>> On Sep 20, 2010, at 1:16 AM, Nico Rehwaldt wrote:
> >>>
> >>>> Hi,
> >>>>
> >>>> I am using Jersey 1.4 ea together with Spring 3.0 and the jersey-
> >>>> spring integration. Integrating Jersey and Spring works fine for
> >>>> resource classes. However I created an instance of
> >>>> ContainerRequestFilter to do some pre-processing of requests. The
> >>>> filter should be a spring component and should handle setting up
> >>>> the
> >>>> security context.
> >>>>
> >>>> Basically I want to have access to the database (the ORM-Layer) and
> >>>> I tried to accomplish this in two ways:
> >>>>
> >>>> @Component
> >>>> public class SecurityFilter implements ContainerRequestFilter {
> >>>>
> >>>> // UserManager is a declared spring component
> >>>> // Injecting it should work somehow
> >>>> @Autowired
> >>>> private UserManager userManager;
> >>>>
> >>>> // Entity Manager would help, too
> >>>> @PersistenceContext
> >>>> private EntityManager em;
> >>>>
> >>>> @Override
> >>>> public ContainerRequest filter(ContainerRequest request) {
> >>>> System.out.println(userManager);
> >>>> // prints out null on request
> >>>> }
> >>>> }
> >>>>
> >>>> I registered the Filter as a Spring compontent, but it does not
> >>>> seem
> >>>> as if it is recognized as such.
> >>>> Both injection of EntityManager and UserManager (a Spring bean as
> >>>> well) do not work.
> >>>>
> >>>> Any suggestions what I might be doing wrong?
> >>>>
> >>>> Greetings
> >>>> Nico
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> >>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >>>
> >>>
> >>> ---------------------------------------------------------------------
> >>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> >>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >>>
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> >> For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >> <jersey-containerrequestfilter-
> >> testcase
> >> .zip
> >>> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> >> For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> > For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> > For additional commands, e-mail: users-help_at_jersey.dev.java.net
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>



-- 
Regards
--Mahesh