users@jersey.java.net

Re: AW: [Jersey] ContainerRequestFilter as Spring component?

From: Paul Sandoz <Paul.Sandoz_at_oracle.com>
Date: Thu, 23 Sep 2010 10:23:06 -0700

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/container/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
>