Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MP apps receiving OPTIONS request triggers failure in Jersey #1684

Closed
tjquinno opened this issue Apr 23, 2020 · 7 comments
Closed

MP apps receiving OPTIONS request triggers failure in Jersey #1684

tjquinno opened this issue Apr 23, 2020 · 7 comments
Assignees
Labels
1.x Issues for 1.x version branch 2.x Issues for 2.x version branch bug Something isn't working MP webserver

Comments

@tjquinno
Copy link
Member

tjquinno commented Apr 23, 2020

Environment Details

  • Helidon Version: 2.0.0-M2
  • Helidon MP
  • JDK version: n/a
  • OS: n/a
  • Docker version (if applicable): n/a

Under certain circumstances, Jersey needs to load JAX-B classes at runtime. For example, neither the generated quickstart pom nor the MP bundle it depends on includes dependencies to satisfy the look-up so Jersey complains and the HTTP request fails.

Inspired by the reproducer described in #1562, here is a simpler one:

  1. Use the archetype to generate the MP quickstart project: https://helidon.io/docs/latest/#/guides/03_quickstart-mp
  2. Build and start the MP quickstart app.
  3. Run this curl command or its equivalent:
curl -X OPTIONS http://localhost:8080/greet/greeting

and the quickstart app creates a long stack trace. (See below.)

Adding both of these dependencies to the quickstart pom:

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <scope>runtime</scope>
        </dependency>

resolves the problem and your client shows XML WADL output describing the endpoint, which explains why Jersey was looking for the JAX-B classes.

This problem is not unique to the MP quickstart app. Any MP app could have the same problem when sent an OPTIONS request.

2020.04.23 16:57:32 WARNING io.helidon.webserver.RequestRouting Thread[helidon-4,5,server]: Default error handler: Unhandled exception encountered.
java.util.concurrent.ExecutionException: Unhandled 'cause' of this exception encountered.
	at io.helidon.webserver.RequestRouting$RoutedRequest.defaultHandler(RequestRouting.java:385)
	at io.helidon.webserver.RequestRouting$RoutedRequest.nextNoCheck(RequestRouting.java:365)
	at io.helidon.webserver.RequestRouting$RoutedRequest.next(RequestRouting.java:408)
	at io.helidon.webserver.jersey.ResponseWriter.failure(ResponseWriter.java:174)
	at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:436)
	at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:261)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
	at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
	at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
	at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
	at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:232)
	at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:680)
	at io.helidon.webserver.jersey.JerseySupport$JerseyHandler.lambda$doAccept$3(JerseySupport.java:293)
	at io.helidon.common.context.Contexts.runInContext(Contexts.java:98)
	at io.helidon.common.context.ContextAwareExecutorImpl.lambda$wrap$1(ContextAwareExecutorImpl.java:129)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: A MultiException has 4 exceptions.  They are:
1. javax.ws.rs.ProcessingException: Error creating a JAXBContext for wadl processing.
2. java.lang.IllegalStateException: Unable to perform operation: create on org.glassfish.jersey.server.wadl.internal.WadlApplicationContextImpl
3. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of org.glassfish.jersey.server.wadl.processor.WadlModelProcessor$OptionsHandler errors were found
4. java.lang.IllegalStateException: Unable to perform operation: resolve on org.glassfish.jersey.server.wadl.processor.WadlModelProcessor$OptionsHandler

	at org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:65)
	at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:226)
	at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:334)
	at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:463)
	at org.glassfish.jersey.inject.hk2.RequestContext.findOrCreate(RequestContext.java:59)
	at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2102)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:758)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:721)
	at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:691)
	at org.glassfish.jersey.inject.hk2.AbstractHk2InjectionManager.getInstance(AbstractHk2InjectionManager.java:160)
	at org.glassfish.jersey.inject.hk2.ImmediateHk2InjectionManager.getInstance(ImmediateHk2InjectionManager.java:30)
	at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:105)
	at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:260)
	at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:51)
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:86)
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:89)
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:89)
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:89)
	at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:89)
	at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:69)
	at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:38)
	at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
	at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:245)
	... 14 more
Caused by: javax.ws.rs.ProcessingException: Error creating a JAXBContext for wadl processing.
	at org.glassfish.jersey.server.wadl.internal.WadlApplicationContextImpl.<init>(WadlApplicationContextImpl.java:120)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at org.glassfish.hk2.utilities.reflection.ReflectionHelper.makeMe(ReflectionHelper.java:1356)
	at org.jvnet.hk2.internal.ClazzCreator.createMe(ClazzCreator.java:248)
	at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:342)
	at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:463)
	at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:59)
	at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:47)
	at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:74)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:131)
	at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:176)
	at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:98)
	at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2102)
	at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:93)
	at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:67)
	at org.glassfish.jersey.inject.hk2.ContextInjectionResolverImpl.resolve(ContextInjectionResolverImpl.java:103)
	at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:188)
	at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:211)
	... 35 more
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
 - with linked exception:
[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]
	at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:131)
	at javax.xml.bind.ContextFinder.find(ContextFinder.java:318)
	at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:478)
	at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:435)
	at org.glassfish.jersey.server.wadl.internal.WadlApplicationContextImpl.<init>(WadlApplicationContextImpl.java:112)
	... 56 more
Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:92)
	at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:125)
	at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128)
	... 60 more
@tjquinno tjquinno added bug Something isn't working MP examples 2.x Issues for 2.x version branch labels Apr 23, 2020
@tjquinno tjquinno changed the title MP quickstart needs additional runtime dependencies - sometimes MP quickstart needs additional runtime dependencies Apr 24, 2020
@tjquinno tjquinno changed the title MP quickstart needs additional runtime dependencies MP apps need additional runtime dependencies Apr 24, 2020
@tjquinno
Copy link
Member Author

Santiago and I chatted with Jan about this. He is looking into whether Jersey could defer trying to locate the JAX-B implementation even later, so in our use case it would not be needed at all. That would resolve the original use case, in which our CORS handling, not Jersey's WADL endpoint, responds to the OPTIONS request.

But separately/in the meantime we need to decide what we want to do about general MP apps. Currently any OPTIONS request sent to any MP app will cause this problem.

Jan mentioned that setting ServerProperties.WADL_FEATURE_DISABLE could help with this, for example if Helidon set that as part of its set-up of Jersey.

We might need a way for users to override Helidon's disabling of that feature if they wanted the out-of-the-box Jersey behavior. At least that way, if they turned this on, they'd have taken an explicit action and could reasonably be held responsible for also making sure a JAX-B implementation is available.

@tjquinno tjquinno changed the title MP apps need additional runtime dependencies MP apps receiving OPTIONS request triggers failure in Jersey Apr 24, 2020
@tjquinno
Copy link
Member Author

Jan suggested that Helidon could do the same attempted class look-up that the Jersey WADL code does. If Helidon does not find the class then it could set the server property mentioned above. That avoids the need for an explicit way for users to override any change inside Helidon: If the user puts a JAX-B implementation on the class path then Helidon will let Jersey use it.

@tjquinno tjquinno added the 1.x Issues for 1.x version branch label Apr 24, 2020
@tjquinno tjquinno self-assigned this Apr 26, 2020
@tjquinno
Copy link
Member Author

It looks as if the trouble starts if the client sends the OPTIONS request without specifying an Accept: header. Jersey seems to default to application/vnd.sun.wadl+xml for OPTIONS in that case. Specifying just about anything else in Accept: seems to short-circuit. Even text/xml works.

@tjquinno
Copy link
Member Author

Jan has a Jersey PR to fix this: eclipse-ee4j/jersey#4450

If a new Jersey release will be out soon we might as well adopt it and avoid making any changes to Helidon code.

@tjquinno
Copy link
Member Author

Jan reports that Jersey is anticipating releasing 2.31 (which will contain this fix) around May 8-11.

@tjquinno
Copy link
Member Author

See also #1887

@tjquinno
Copy link
Member Author

With #1887 merged, I rebuilt the MP Quickstart example. Gratifyingly, server start-up logs this new message:

2020.05.28 15:26:24 WARNING org.glassfish.jersey.server.wadl.WadlFeature Thread[main,5,main]:
 JAXBContext implementation could not be found. WADL feature is disabled.

and sending the same OPTIONS request listed above which used to trigger an exception instead returns

HTTP/1.1 200 OK
Allow: OPTIONS,PUT
Content-Type: text/plain
Date: Thu, 28 May 2020 15:28:51 -0500
connection: keep-alive
content-length: 12

OPTIONS, PUT

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.x Issues for 1.x version branch 2.x Issues for 2.x version branch bug Something isn't working MP webserver
Projects
Archived in project
Development

No branches or pull requests

1 participant