users@jersey.java.net

Re: [Jersey] Jersey provider-detection fails under Tomcat?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 05 Jan 2009 11:42:35 +0100

On Dec 24, 2008, at 3:10 AM, Gili wrote:

>
> Here is what I found out:
>
> - The MultiPart provider fails to initialize because Javamail is
> missing.
> Glassfish bundles this dependency, whereas Tomcat does not.
> - If the MessageBodyReader omits @Provider then no error message
> shows up.
> The binding fails silently, causing Jersey to issue a confusing error
> message about the MessageBodyReader being missing when in fact it is
> not.

An error will be logged at the level of CONFIG. This will occur when
the class is attempted to be loaded. The reason for using CONFIG is
some what historical but also related to using jersey-bundle that may
contain many providers that are not needed but are instantiated and
errors will result because the dependencies are deliberately not
included.

Note that it is not necessary for all providers to be annotated with
@Provider. Infrastructure-based providers are registered using META-
INF/services, thus there is no need to class scan and instead
registration occurs because the jar is in the class path.


>
> - If the MessageBodyReader is annotated using @Provider the following
> exception shows up when the webapp is initialized:
>

Did you configure class scanning (file or package) to the multipart
providers? I presume you did.

I don't understand why the error occurs when the class is instantiated
rather than when the class is loaded. Namely the code to instantiate a
provider class registered via META-INF/services or annotated with
@Provider and scanned is the same.

It may be because the class scanning utilizes ClassLoader.loadClass
and the META-INF/services code uses Class.forName. I need to fix the
class loading in the former to use the correct class loading logic for
EE and OSGi compatibility and may be it make things more consistent
with errors logged to CONFIG. We can improve the error message when a
provider is not found with a hint about dependent jars in the classpath.

Paul.

> SEVERE: Exception starting filter warpServletFilter
> java.lang.NoClassDefFoundError: javax/mail/MessagingException
> at java.lang.Class.getDeclaredConstructors0(Native Method)
> at java.lang.Class.privateGetDeclaredConstructors(Class.java:
> 2389)
> at java.lang.Class.getDeclaredConstructors(Class.java:1836)
> at
> com
> .google
> .inject.spi.InjectionPoint.forConstructorOf(InjectionPoint.java:192)
> at
> com
> .google.inject.ConstructorInjector.<init>(ConstructorInjector.java:45)
> at com.google.inject.InjectorImpl$5.create(InjectorImpl.java:
> 728)
> at com.google.inject.InjectorImpl$5.create(InjectorImpl.java:
> 724)
> at
> com.google.inject.internal.FailableCache$1.create(FailableCache.java:
> 32)
> at
> com.google.inject.internal.ReferenceCache.create(ReferenceCache.java:
> 54)
> at
> com
> .google
> .inject
> .internal
> .AbstractReferenceCache.internalCreate(AbstractReferenceCache.java:59)
> at
> com
> .google
> .inject
> .internal.AbstractReferenceCache.get(AbstractReferenceCache.java:116)
> at
> com.google.inject.internal.ReferenceCache.get(ReferenceCache.java:28)
> at
> com.google.inject.internal.FailableCache.get(FailableCache.java:43)
> at
> com.google.inject.InjectorImpl
> $LateBoundConstructor.bind(InjectorImpl.java:431)
> at
> com.google.inject.ClassBindingImpl.initialize(ClassBindingImpl.java:
> 46)
> at
> com.google.inject.InjectorImpl.initializeBinding(InjectorImpl.java:
> 320)
> at
> com
> .google
> .inject.InjectorImpl.createJustInTimeBinding(InjectorImpl.java:615)
> at
> com
> .google
> .inject
> .InjectorImpl.createJustInTimeBindingRecursive(InjectorImpl.java:558)
> at
> com
> .google.inject.InjectorImpl.getJustInTimeBinding(InjectorImpl.java:
> 168)
> at
> com.google.inject.InjectorImpl.getBindingOrThrow(InjectorImpl.java:
> 128)
> at
> com.google.inject.InjectorImpl.getBinding(InjectorImpl.java:105)
> at
> com.google.inject.InjectorImpl.getBinding(InjectorImpl.java:60)
> at
> com
> .sun
> .jersey
> .spi
> .guice
> .container
> .GuiceComponentProviderFactory
> .getComponentProvider(GuiceComponentProviderFactory.java:98)
> at
> com
> .sun
> .jersey
> .spi
> .guice
> .container
> .GuiceComponentProviderFactory
> .getComponentProvider(GuiceComponentProviderFactory.java:87)
> at
> com
> .sun
> .jersey
> .core
> .spi
> .component
> .ioc
> .IoCProviderFactory._getComponentProvider(IoCProviderFactory.java:68)
> at
> com
> .sun
> .jersey
> .core
> .spi
> .component.ProviderFactory.getComponentProvider(ProviderFactory.java:
> 126)
> at
> com
> .sun
> .jersey
> .core
> .spi.component.ProviderServices.getComponent(ProviderServices.java:
> 163)
> at
> com
> .sun
> .jersey
> .core
> .spi
> .component
> .ProviderServices.getProvidersAndServices(ProviderServices.java:119)
> at
> com
> .sun
> .jersey
> .core
> .spi
> .factory.MessageBodyFactory.getProviderMap(MessageBodyFactory.java:
> 136)
> at
> com
> .sun
> .jersey
> .core
> .spi.factory.MessageBodyFactory.initReaders(MessageBodyFactory.java:
> 110)
> at
> com
> .sun
> .jersey
> .core.spi.factory.MessageBodyFactory.init(MessageBodyFactory.java:105)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application.WebApplicationImpl.initiate(WebApplicationImpl.java:462)
> at
> com
> .sun
> .jersey
> .spi.guice.container.servlet.GuiceServlet.initiate(GuiceServlet.java:
> 47)
> at
> com
> .sun
> .jersey
> .spi.container.servlet.ServletContainer.load(ServletContainer.java:
> 540)
> at
> com
> .sun
> .jersey
> .spi.container.servlet.ServletContainer.init(ServletContainer.java:
> 207)
> at
> com
> .wideplay.warp.servlet.ServletDefinition.init(ServletDefinition.java:
> 50)
> at
> com
> .wideplay
> .warp
> .servlet.ManagedServletPipeline.init(ManagedServletPipeline.java:31)
> at
> com
> .wideplay
> .warp
> .servlet
> .ManagedFilterPipeline.initPipeline(ManagedFilterPipeline.java:38)
> at com.wideplay.warp.servlet.WebFilter.init(WebFilter.java:70)
> at
> org
> .apache
> .catalina
> .core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:
> 275)
> at
> org
> .apache
> .catalina
> .core
> .ApplicationFilterConfig.setFilterDef(ApplicationFilterConfig.java:
> 397)
> at
> org
> .apache
> .catalina
> .core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:108)
> at
> org
> .apache
> .catalina.core.StandardContext.filterStart(StandardContext.java:3709)
> at
> org.apache.catalina.core.StandardContext.start(StandardContext.java:
> 4363)
> at
> org
> .apache
> .catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
> at
> org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:
> 771)
> at
> org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
> at
> org
> .apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:
> 627)
> at
> org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:511)
> at
> org.apache.catalina.startup.HostConfig.check(HostConfig.java:1231)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun
> .reflect
> .NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun
> .reflect
> .DelegatingMethodAccessorImpl
> .invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at
> org
> .apache
> .tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:297)
> at
> com
> .sun
> .jmx
> .interceptor
> .DefaultMBeanServerInterceptor
> .invoke(DefaultMBeanServerInterceptor.java:836)
> at
> com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761)
> at
> org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:
> 1471)
> at
> org
> .apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:
> 824)
> at
> org.apache.catalina.manager.ManagerServlet.doGet(ManagerServlet.java:
> 350)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
> at
> org
> .apache
> .catalina
> .core
> .ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:
> 290)
> at
> org
> .apache
> .catalina
> .core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> at
> org
> .apache
> .catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:
> 233)
> at
> org
> .apache
> .catalina.core.StandardContextValve.invoke(StandardContextValve.java:
> 191)
> at
> org
> .apache
> .catalina
> .authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
> at
> org
> .apache
> .catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
> at
> org
> .apache
> .catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
> at
> org
> .apache
> .catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:
> 109)
> at
> org
> .apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:
> 286)
> at
> org
> .apache.coyote.http11.Http11Processor.process(Http11Processor.java:
> 845)
> at
> org.apache.coyote.http11.Http11Protocol
> $Http11ConnectionHandler.process(Http11Protocol.java:583)
> at
> org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:
> 447)
> at java.lang.Thread.run(Thread.java:619)
> Caused by: java.lang.ClassNotFoundException:
> javax.mail.MessagingException
> at
> org
> .apache
> .catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:
> 1387)
> at
> org
> .apache
> .catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:
> 1233)
> at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:
> 320)
> ... 75 more
>
> I filed two bug reports:
> https://jersey.dev.java.net/issues/show_bug.cgi?id=171
> https://jersey.dev.java.net/issues/show_bug.cgi?id=172
>
> Gili
>
>
> Gili wrote:
>>
>> It's taking me forever to debug this, but in the process of
>> troubleshooting I noticed that MultiPartReader isn't annotated with
>> @Provider as required according to MessageBodyReader's
>> specification. The
>> Javadoc reads "To add a MessageBodyReader implementation, annotate
>> the
>> implementation class with @Provider". Could this be it? It still
>> doesn't
>> explain why this works under Glassfish without the annotation.
>>
>> Gili
>>
>>
>> Gili wrote:
>>>
>>> I took my existing webapp, moved from Glassfish v2 to Tomcat and
>>> all of a
>>> sudden I get:
>>>
>>> SEVERE: A message body reader for Java type, class
>>> com.sun.jersey.multipart.MultiPart, and MIME media type, multipart/
>>> mixed,
>>> was not found
>>>
>>> I'm guessing that Jersey provider scanning is failing under Tomcat
>>> for
>>> some reason...? Paul, Craig can you guys confirm this?
>>>
>>> Thanks,
>>> Gili
>>>
>>
>>
>
> --
> View this message in context: http://n2.nabble.com/Jersey-provider-detection-fails-under-Tomcat--tp1688690p1696750.html
> Sent from the Jersey mailing list archive at Nabble.com.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>