users@jersey.java.net

RE: [Jersey] adding a _at_Context annotated parameter using an InjectableProvider on WebSphere

From: Beech, Travis <Travis.Beech_at_ejgallo.com>
Date: Fri, 27 Aug 2010 11:17:52 -0700

I apologize in advance for the length of this post, and if I have posted incorrectly to this list. I hope the information contained in this email is coherent enough to follow, if any clarification is required please let me know.

We are having the same exact issue as Mark is having with a custom class that implements the InjectableProvider interface. I suspect that Mark is correct about the subtle difference in the classloader of WebSphere and Tomcat. However, I have been able to successfully get our application to work locally with RAD75 running a local WAS6.1.0.19 server, unfortunately our production, acceptance, and development server are running WAS6.1.0.9.

Even with the difference in WAS versions I am still seeing a difference in package scanning with Jersey 1.2 between the WAS 6.1.0.19 and the WAS 6.1.0.9.

Locally when I start my server this is what I see when the package scanning begins:
[8/27/10 10:50:38:046 PDT] 00000013 PackagesResou I Scanning for root resource and provider classes in the packages:
  com.ejgallo.finance
[8/27/10 10:50:40:089 PDT] 00000013 ScanningResou I Root resource classes found:
  class com.ejgallo.finance.accountspayable.payments.attachments.Attachments
  class com.ejgallo.finance.accountspayable.payments.mobile.Mobile
  class com.ejgallo.finance.accountspayable.payments.documents.ImageRequest
  class com.ejgallo.finance.accountspayable.payments.documents.DocumentRequest
  class com.ejgallo.finance.accountspayable.payments.admin.Reminders
  class com.ejgallo.finance.accountspayable.payments.workflow.WorkflowRequest
  class com.ejgallo.finance.accountspayable.payments.data.Data
  class com.ejgallo.finance.accountspayable.payments.invoice.HistoryRequest
  class com.ejgallo.finance.accountspayable.payments.invoice.PreferencesRequest
  class com.ejgallo.finance.accountspayable.payments.dialogs.Dialogs
  class com.ejgallo.finance.accountspayable.payments.invoice.InvoiceRequest
  class com.ejgallo.finance.accountspayable.payments.menu.inquiry.Inquiry
  class com.ejgallo.finance.accountspayable.payments.admin.Support
[8/27/10 10:50:40:091 PDT] 00000013 ScanningResou I Provider classes found:
  class com.ejgallo.finance.common.jaxrs.GenericProvider
  class com.ejgallo.finance.accountspayable.payments.errors.ThrowableExceptionMapper
  class com.ejgallo.finance.accountspayable.payments.errors.ApplicationExceptionMapper
  class com.ejgallo.finance.common.jaxrs.BinaryContentProvider
  class com.ejgallo.finance.accountspayable.payments.errors.NotFoundExceptionMapper
  class com.ejgallo.finance.common.jaxrs.W3CDocumentProvider
  class com.ejgallo.finance.accountspayable.web.WebSessionInjector (This is our custom class that implements InjectableProvider
  class com.ejgallo.finance.common.jaxrs.TemplateProvider

However, when deployed to the development server, the package scanning looks like this on server startup:
[8/27/10 10:33:46:198 PDT] 00000027 PackagesResou I Scanning for root resource and provider classes in the packages:
  com.ejgallo.finance
[8/27/10 10:33:46:490 PDT] 00000027 ScanningResou I Root resource classes found:
  class com.ejgallo.finance.accountspayable.payments.invoice.PreferencesRequest
  class com.ejgallo.finance.accountspayable.payments.documents.ImageRequest
  class com.ejgallo.finance.accountspayable.payments.data.Data
  class com.ejgallo.finance.accountspayable.payments.mobile.Mobile
  class com.ejgallo.finance.accountspayable.payments.documents.DocumentRequest
  class com.ejgallo.finance.accountspayable.payments.admin.Reminders
  class com.ejgallo.finance.accountspayable.payments.admin.Support
  class com.ejgallo.finance.accountspayable.payments.invoice.HistoryRequest
  class com.ejgallo.finance.accountspayable.payments.menu.inquiry.Inquiry
  class com.ejgallo.finance.accountspayable.payments.invoice.InvoiceRequest
  class com.ejgallo.finance.accountspayable.payments.attachments.Attachments
  class com.ejgallo.finance.accountspayable.payments.dialogs.Dialogs
  class com.ejgallo.finance.accountspayable.payments.workflow.WorkflowRequest
[8/27/10 10:33:46:492 PDT] 00000027 ScanningResou I Provider classes found:
  class com.ejgallo.finance.accountspayable.payments.errors.NotFoundExceptionMapper
  class com.ejgallo.finance.accountspayable.payments.errors.ThrowableExceptionMapper
  class com.ejgallo.finance.accountspayable.payments.errors.ApplicationExceptionMapper

The main difference here is that when deployed to the development server, the package scanning is limited in scope to the packages within the web application.

The following packages are contained in two separate libraries that exist in a common library folder and is bound to the application through a shared library reference in WAS.
com.ejgallo.finance.common.jaxrs (This package contains other custom providers)
com.ejgallo.finance.accountspayable.web (This package contains the WebSessionInjector class)

When working locally these additional projects are bound to the web application as Java EE Module dependencies, so they look as if they exist in the WEB-INF/lib folder (This, I believe is the fundamental difference between our local development environments and our development server).

I believe a work around that might work, which I have yet to attempt, is to move the WebSessionInjector class into a package within our web application because otherwise the package scanning just isn't registering the WebSessionInjector class on startup.

As a side note related to this, one of the main differences I have noticed between start up of Tomcat and WebSphere is in this method:

@Override
protected void initiate(com.sun.jersey.api.core.ResourceConfig rc, com.sun.jersey.spi.container.WebApplication wa)
{
  try
  {
    super.initiate( rc, wa );
  }
  catch( Throwable t )
  {
    t.printStackTrace();
  }
};

We are using a class that is a Servlet\Filter, so it extends ServletContainer and implements Filter, and when I override this method I notice that in Tomcat this initiate method is called twice on startup and succeeds both times whereas in WebSphere it is called once on start up and once when the Servlet\Filter is accessed for the first time. In WebSphere the first call (on start up) succeeds and the second call (on first access) fails with the following error:

com.sun.jersey.api.container.ContainerException: Method, public org.w3c.dom.Document com.ejgallo.finance.accountspayable.payments.documents.DocumentRequest.getDocumentFoldersData(com.ejgallo.finance.accountspayable.web.WebSession), annotated with GET of resource, class com.ejgallo.finance.accountspayable.payments.documents.DocumentRequest, is not recognized as valid Java method annotated with @HttpMethod.

And the method that it is complaining about is declared as follows, note this method contains "@Context WebSession" which is supposed to be handled by our custom WebSessionInjector class. I will get the same error in WebSphere for every method that contains "@Context WebSession".

@GET
@Path( "/folders/documentfolders" )
@Produces( MediaType.TEXT_XML )
public Document getDocumentFoldersData( @Context WebSession session )
{...}

Travis Beech | Programmer Analyst |E&J Gallo Winery | 209-341-6108


-----Original Message-----
From: Paul Sandoz [mailto:Paul.Sandoz_at_oracle.com]
Sent: Thursday, August 26, 2010 7:23 AM
To: users_at_jersey.dev.java.net
Subject: Re: [Jersey] adding a @Context annotated parameter using an InjectableProvider on Websphere


On Aug 26, 2010, at 3:43 PM, Mark Birenbaum wrote:

> Oops, missed that detail. We're using the @Provider annotation.
>
> @Provider
> public class LocaleProvider
> implements InjectableProvider<Context, Type> {
> ...
>
> I figure it's probably some classloader issue and the LocaleProvider
> isn't being seen in the same context as jersey for some reason,
> although since we have it all as one big war file, I can't imagine
> what the issue would be. If it was broken in both environments I'd
> assume our configuration was messed up, but only broken in websphere
> makes me think there's some subtly to the way jersey looks for
> providers that I need to be concerned with.
>

I cannot recall exactly which version of Jersey but i do recall there
were some issues with scanning on WebSphere. They may have been
similar to those for WebLogic which were fixed in Jersey 1.1.5 and
Jersey 1.2).

What is your web.xml?

Paul.

>
>> From: Paul Sandoz <Paul.Sandoz_at_oracle.com>
>> To: users_at_jersey.dev.java.net
>> Date: Thu, 26 Aug 2010 10:31:52 +0200
>> Subject: Re: [Jersey] adding a @Context annotated parameter using
>> an InjectableProvider on Websphere
>> Hi Mark,
>>
>> How are you deploying and registering your LocaleProvider on
>> WebSphere?
>>
>> I suspect when you deploy on WebSphere the LocaleProvider is not
>> getting registered.
>>
>> Paul.
>>
>> On Aug 25, 2010, at 10:47 PM, Mark Birenbaum wrote:
>>
>>> We've added an InjectableProvider to our system to allow the
>>> addition
>>> of Locale to resource methods. Our provider looks like this:
>>>
>>>
>>>
>>> public class LocaleProvider
>>> implements InjectableProvider<Context, Type> {
>>>
>>> ...
>>> public Injectable<Locale> getInjectable(ComponentContext
>>> ic, Context
>>> a, Type c) { ...
>>>
>>>
>>> And our use of it looks like this:
>>>
>>> @GET
>>> @Produces(APPLICATION_JSON)
>>> public JSONArray getTasksAsJsonArray(@Context UriInfo
>>> uriInfo,
>>> @QueryParam("template") boolean isTemplate,
>>> @Context Locale locale)
>>> throws JSONException { ...
>>>
>>>
>>>
>>>
>>> Works great in tomcat. Blows up in websphere like this:
>>>
>>> Exception:
>>> com.sun.jersey.api.container.ContainerException: Method, public
>>> javax.ws.rs.core.Response
>>> com.bps.iproject.jersey.resources.TasksResource. getTasksAsJsonArray
>>> (javax.ws.rs.core.UriInfo,boolean,java.util.Locale), annotated with
>>> GET of resource, class
>>> com.bps.iproject.jersey.resources.TasksResource, is not recognized
>>> as
>>> valid Java method annotated with @HttpMethod.
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .model.method.ResourceHttpMethod.<init>(ResourceHttpMethod.java:92)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .model.method.ResourceHttpMethod.<init>(ResourceHttpMethod.java:69)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .model.ResourceClass.processSubResourceMethods(ResourceClass.java:
>>> 258)
>>> at
>>> com
>>> .sun
>>> .jersey.server.impl.model.ResourceClass.<init>(ResourceClass.java:
>>> 128)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .application
>>> .WebApplicationImpl.newResourceClass(WebApplicationImpl.java:348)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .application
>>> .WebApplicationImpl.getResourceClass(WebApplicationImpl.java:321)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .application
>>> .WebApplicationImpl.processRootResources(WebApplicationImpl.java:
>>> 807)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .server
>>> .impl
>>> .application.WebApplicationImpl.initiate(WebApplicationImpl.java:
>>> 590)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .spi
>>> .spring
>>> .container.servlet.SpringServlet.initiate(SpringServlet.java:78)
>>> at com.sun.jersey.spi.container.servlet.ServletContainer
>>> $InternalWebComponent.initiate(ServletContainer.java:242)
>>> at
>>> com
>>> .sun
>>> .jersey.spi.container.servlet.WebComponent.load(WebComponent.java:
>>> 449)
>>> at
>>> com
>>> .sun
>>> .jersey.spi.container.servlet.WebComponent.init(WebComponent.java:
>>> 169)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .spi.container.servlet.ServletContainer.init(ServletContainer.java:
>>> 281)
>>> at
>>> com
>>> .sun
>>> .jersey
>>> .spi.container.servlet.ServletContainer.init(ServletContainer.java:
>>> 442)
>>> at javax.servlet.GenericServlet.init(GenericServlet.java:256)
>>> at
>>> com
>>> .ibm
>>> .ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:
>>> 227)
>>>
>>>
>>>
>>> If I change the Locale to one of the standard @Context options
>>> (i.e.,
>>> HttpServletRequest) I have no issues. So to work around this I'm
>>> changing all our methods that take Locale to take the request
>>> instead.
>>> But I would like to know what I'm doing wrong,.
>>>
>>> We're using spring and Jersey 1.0.3.
>>>
>>> Any thoughts?
>>>
>>> ---------------------------------------------------------------------
>>> 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
>