Peter Varga created TOMEE-2352:
----------------------------------
Summary: TomEE does not handle app using its own JAX-RS stack
correctly
Key: TOMEE-2352
URL: https://issues.apache.org/jira/browse/TOMEE-2352
Project: TomEE
Issue Type: Bug
Components: TomEE Core Server
Affects Versions: 7.0.5
Reporter: Peter Varga
war files that rely on Jersey instead of Apache CXF package their own JAX-RS
related jars in the .war and can declare the following in their web.xml:
{code:xml}
<servlet>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.myapp.JaxRSApp</param-value>
</init-param>
</servlet>
{code}
TomEE has some logic to deal with apps that deploy their own JAX-RS as shown by
the following code in in the DiscoverAnnotatedBeans class in
AnnotationDeployer.java:
{code:java}
boolean restHandledByTheWebApp;
try {
restHandledByTheWebApp =
webModule.getClassLoader().loadClass(Application.class.getName()) !=
Application.class;
} catch (final Throwable e) { // ClassNotFoundException or NoClassDefFoundError
restHandledByTheWebApp = false;
}
{code}
However, to trigger that, one must set the following in system.properties:
{{openejb.classloader.forced-load = javax.ws.rs}}
So assume that's been set.
Deploying such an app then results in the following exception in catalina.log
on startup of the webapp:
{noformat}
09-Dec-2018 10:19:29.372 SEVERE [localhost-startStop-1]
org.apache.openejb.observer.ObserverManager$MethodInvocation.invoke error
invoking org.apache.tomee.webservices.TomeeJaxRsService@4f4c4b1a
org.apache.openejb.server.rest.OpenEJBRestRuntimeException: can't create class
com.myapp.JaxRSApp
at
org.apache.openejb.server.rest.RESTService.afterApplicationCreated(RESTService.java:165)
at
org.apache.tomee.webservices.TomeeJaxRsService.afterApplicationCreated(TomeeJaxRsService.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at
org.apache.openejb.observer.ObserverManager$MethodInvocation.invoke(ObserverManager.java:406)
at
org.apache.openejb.observer.ObserverManager$InvocationList.invoke(ObserverManager.java:521)
at
org.apache.openejb.observer.ObserverManager.doFire(ObserverManager.java:111)
at
org.apache.openejb.observer.ObserverManager.fireEvent(ObserverManager.java:100)
at
org.apache.openejb.loader.SystemInstance.fireEvent(SystemInstance.java:134)
at
org.apache.tomee.catalina.TomcatWebAppBuilder.afterStart(TomcatWebAppBuilder.java:1773)
at
org.apache.tomee.catalina.GlobalListenerSupport.lifecycleEvent(GlobalListenerSupport.java:116)
at
org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:94)
at
org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:395)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:160)
at
org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
at
org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at
org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:629)
at
org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1839)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassCastException: Cannot cast com.myapp.JaxRSApp to
javax.ws.rs.core.Application
at java.lang.Class.cast(Class.java:3369)
at
org.apache.openejb.server.rest.RESTService.afterApplicationCreated(RESTService.java:156)
... 25 more
{noformat}
With some limited debugging, this appears to be because
{{ProcessAnnotatedBeans}} class' {{public WebModule deploy(final WebModule
webModule)}} method processes servlets and handles javax.ws.rs.core.Application
declarations - but doesn't do the 'restHandledByTheWebApp' check as
DiscoverAnnotatedBeans does.
{code:java}
// if the servlet is a rest init servlet don't deploy rest classes automatically
for (final ParamValue param : servlet.getInitParam()) {
if (param.getParamName().equals(Application.class.getName()) ||
param.getParamName().equals("javax.ws.rs.Application")) {
webModule.getRestApplications().clear();
webModule.getRestApplications().add(param.getParamValue());
break;
}
}
{code}
Related to this - there is also the following in RESTService.java to let apps
opt-out of container's JAX-RS:
{code:java}
final AppInfo appInfo = event.getApp();
if ("false".equalsIgnoreCase(appInfo.properties.getProperty("openejb.jaxrs.on",
"true"))) {
return;
}
{code}
However, this is only checked in
{code:java}
public void afterApplicationCreated(@Observes final
AssemblerAfterApplicationCreated event)
{code}
but the other overload of this method does not check it:
{code:java}
public void afterApplicationCreated(final AppInfo appInfo, final WebAppInfo
webApp)
{code}
If it did, the exception would also be avoided.
--
This message was sent by Atlassian JIRA
(v7.6.3#76005)