users@jersey.java.net

AW: [Jersey] ContainerRequestFilter as Spring component?

From: Nico Rehwaldt <nico.rehwaldt_at_web.de>
Date: Thu, 23 Sep 2010 01:46:10 +0200

Hey Paul,

the filter is recognized via package scanning (not programmatically).
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);
            }
        }
    }

* 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