eclipse-osgi-technology / jakartarest-osgi

Glassfish Jersey based implementation of the OSGi Jakarta RESTful Web Services Whiteboard specification
https://projects.eclipse.org/projects/technology.osgi-technology
Eclipse Public License 2.0
3 stars 5 forks source link

Extension interfaces with generics are causing crashes #39

Closed fipro78 closed 8 months ago

fipro78 commented 9 months ago

I am trying to write a blog post about the usage of the Whiteboard Implementation for Jakarta RESTful Web Services. I want it to be similar to my old Build REST services with OSGi JAX-RS whiteboard.

I tried the example by using the Jetty 11 bundles directly instead of the Apache Felix Http Jetty bundle, and with the Apache Felix Http Jetty bundle. In both cases this works fine for a simple service. But when I try to add a converter for JSON, I get the following exception:

Jan. 30, 2024 4:15:27 PM org.glassfish.jersey.server.ServerRuntime$Responder process
WARNUNG: An exception mapping did not successfully produce and processed a response. Logging the exception propagated to the default exception mapper.
java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.jvnet.hk2.internal.ServiceLocatorImpl.checkState(ServiceLocatorImpl.java:2399)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:738)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:732)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:702)
    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.server.ApplicationHandler.lambda$initialize$4(ApplicationHandler.java:424)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:57)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:31)
    at org.glassfish.jersey.process.internal.Stages$LinkedStage.apply(Stages.java:284)
    at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
    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:240)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:697)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:357)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
    at org.eclipse.osgitech.rest.runtime.WhiteboardServletContainer.service(WhiteboardServletContainer.java:137)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:529)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1380)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1302)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.Server.handle(Server.java:563)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
    at java.base/java.lang.Thread.run(Thread.java:840)

Jan. 30, 2024 4:15:27 PM org.glassfish.jersey.server.ServerRuntime$Responder writeResponse
SCHWERWIEGEND: Error while closing the output stream in order to commit response.
org.glassfish.jersey.server.ContainerException: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.glassfish.jersey.servlet.internal.ResponseWriter.getResponseContext(ResponseWriter.java:278)
    at org.glassfish.jersey.servlet.internal.ResponseWriter.writeResponseStatusAndHeaders(ResponseWriter.java:128)
    at org.glassfish.jersey.server.ServerRuntime$Responder$1.getOutputStream(ServerRuntime.java:667)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:171)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.flushBuffer(CommittingOutputStream.java:276)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:232)
    at org.glassfish.jersey.message.internal.CommittingOutputStream.close(CommittingOutputStream.java:247)
    at org.glassfish.jersey.message.internal.OutboundMessageContext.close(OutboundMessageContext.java:865)
    at org.glassfish.jersey.server.ContainerResponse.close(ContainerResponse.java:403)
    at org.glassfish.jersey.server.ServerRuntime$Responder.writeResponse(ServerRuntime.java:749)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponse(ServerRuntime.java:385)
    at org.glassfish.jersey.server.ServerRuntime$Responder.processResponseWithDefaultExceptionMapper(ServerRuntime.java:633)
    at org.glassfish.jersey.server.ServerRuntime$Responder.process(ServerRuntime.java:458)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:269)
    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:240)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:697)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:357)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
    at org.eclipse.osgitech.rest.runtime.WhiteboardServletContainer.service(WhiteboardServletContainer.java:137)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:529)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1380)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1302)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.Server.handle(Server.java:563)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
    at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.util.concurrent.ExecutionException: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at java.base/java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:396)
    at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2073)
    at org.glassfish.jersey.servlet.internal.ResponseWriter.getResponseContext(ResponseWriter.java:276)
    ... 49 more
Caused by: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.jvnet.hk2.internal.ServiceLocatorImpl.checkState(ServiceLocatorImpl.java:2399)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:738)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:732)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:702)
    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.server.ApplicationHandler.lambda$initialize$4(ApplicationHandler.java:424)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:57)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:31)
    at org.glassfish.jersey.process.internal.Stages$LinkedStage.apply(Stages.java:284)
    at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
    ... 36 more

[qtp631911774-76] WARN org.eclipse.jetty.server.HttpChannel - /modify/schnulli
jakarta.servlet.ServletException: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:409)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:357)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
    at org.eclipse.osgitech.rest.runtime.WhiteboardServletContainer.service(WhiteboardServletContainer.java:137)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:529)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1380)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1302)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.Server.handle(Server.java:563)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
    at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.jvnet.hk2.internal.ServiceLocatorImpl.checkState(ServiceLocatorImpl.java:2399)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:738)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:732)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:702)
    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.server.ApplicationHandler.lambda$initialize$4(ApplicationHandler.java:424)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:57)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:31)
    at org.glassfish.jersey.process.internal.Stages$LinkedStage.apply(Stages.java:284)
    at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
    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:240)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:697)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
    ... 27 more
[qtp631911774-76] WARN org.eclipse.jetty.server.HttpChannelState - unhandled due to prior sendError
jakarta.servlet.ServletException: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:409)
    at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:346)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:357)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:311)
    at org.eclipse.osgitech.rest.runtime.WhiteboardServletContainer.service(WhiteboardServletContainer.java:137)
    at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:205)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:529)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1380)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1302)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
    at org.eclipse.jetty.server.Server.handle(Server.java:563)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$0(HttpChannel.java:505)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:762)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:497)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:282)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
    at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:934)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1078)
    at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.lang.IllegalStateException: ServiceLocatorImpl(__HK2_Generated_1,1,822606505) has been shut down
    at org.jvnet.hk2.internal.ServiceLocatorImpl.checkState(ServiceLocatorImpl.java:2399)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:738)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:732)
    at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:702)
    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.server.ApplicationHandler.lambda$initialize$4(ApplicationHandler.java:424)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:57)
    at org.glassfish.jersey.server.internal.process.ReferencesInitializer.apply(ReferencesInitializer.java:31)
    at org.glassfish.jersey.process.internal.Stages$LinkedStage.apply(Stages.java:284)
    at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:253)
    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:240)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:697)
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:394)
    ... 27 more

I tried various configurations, added bundles explicitly, but nothing works.

On the one side I noticed that Eclipse Parsson is still used in version 1.1.2, but from the changelog it seems that several OSGi related issues were resolved in the meantime. Not sure if this is related, but I opened PR #38 to update the dependency.

Another thing I noticed is that there are many configuration reload executions. At least two of them look strange codewise.

In JerseyServiceRuntime line 514 a reload is triggered if JerseyApplicationProvider#isChanged(Application) returns true. The interesting thing is, that method always returns true. And that method is not overriding a parent class method, and even the javadoc looks weird. I wonder if this is intended. But of course I am also not sure if this is the cause for the issue.

My example is available in GitHub: https://github.com/fipro78/osgi-jakartars

The main branch contains the working example with the simple service setup. The json branch contains the extension with the JSON handling, which shows the error on requesting the resource in a browser.

Once the app is started via the app.bndrun file, you can try to access the resource via http://localhost:8080/modify/fubar, which shows the error in the console.

juergen-albert commented 9 months ago

I've just given it a try and it seems to work on my machine. Not sure what I doe different to you.

juergen-albert commented 9 months ago

sorry, a rebuild now shows the error.

juergen-albert commented 9 months ago

@timothyjward This seems to be an issue with the class you needed to conjure for the extensions issue with bytebuddy.

I found an Exception that is thrown deep in the bowls of java, when HK2 tries to figure out the advertised Types.

The message from the Exception reads as:

java.lang.reflect.GenericSignatureFormatError: Signature Parse error: Expected Field Type Signature
    Remaining input: >;>;Ljakarta/ws/rs/ext/MessageBodyWriter<>;;;

The String it tries to parse is: Ljava/lang/Object;Ljakarta/ws/rs/ext/MessageBodyReader<>;>;Ljakarta/ws/rs/ext/MessageBodyWriter<>;;;

It seems it does not like the <> here, as it complains about index 55.

The full Stacktrace is:

SignatureParser.parseFieldTypeSignature(boolean) line: 291  
SignatureParser.parseFieldTypeSignature() line: 277 
SignatureParser.parseTypeArgument() line: 420   
SignatureParser.parseTypeArguments() line: 380  
SignatureParser.parsePackageNameAndSimpleClassTypeSignature() line: 335 
SignatureParser.parseClassTypeSignature() line: 304 
SignatureParser.parseSuperInterfaces() line: 544    
SignatureParser.parseClassSignature() line: 214 
SignatureParser.parseClassSig(String) line: 156 
ClassRepository.parse(String) line: 57  
ClassRepository.parse(String) line: 41  
ClassRepository(AbstractRepository<T>).<init>(String, GenericsFactory) line: 74 
ClassRepository(GenericDeclRepository<S>).<init>(String, GenericsFactory) line: 49  
ClassRepository.<init>(String, GenericsFactory) line: 53    
ClassRepository.make(String, GenericsFactory) line: 70  
Class<T>.getGenericInfo() line: 3263    
Class<T>.getGenericSuperclass() line: 1016  
ReflectionHelper.getAdvertisedTypesFromClass(Type, Class<Annotation>) line: 582 
ReflectionHelper.getAdvertisedTypesFromObject(Object, Class<Annotation>) line: 636  
BuilderHelper.createConstantDescriptor(T) line: 420 
Hk2Helper.translateToActiveDescriptor(InstanceBinding<?>, Type...) line: 312    
Hk2Helper.bindBinding(ServiceLocator, DynamicConfiguration, Binding<?,?>) line: 130 
Hk2Helper.bind(ServiceLocator, Iterable<Binding>) line: 88  
Hk2Helper.bind(AbstractHk2InjectionManager, Binder) line: 66    
ImmediateHk2InjectionManager.register(Binder) line: 58  
ProviderBinder.bindProvider(Object, ContractProvider, InjectionManager) line: 159   
ResourceModelConfigurator.bindProvidersAndResources(InjectionManager, ServerBootstrapBag, ComponentBag, Collection<Class<?>>, Collection<Object>, ResourceConfig) line: 185 
ResourceModelConfigurator.init(InjectionManager, BootstrapBag) line: 63 
ApplicationHandler.initialize(InjectionManager, List<BootstrapConfigurator>, ServerBootstrapBag) line: 359  
ApplicationHandler.lambda$initialize$1(InjectionManager, List, ServerBootstrapBag) line: 310    
0x0000000800f06b40.call() line: not available   
Errors.process(Callable<T>, boolean) line: 292  
Errors.process(Producer<T>, boolean) line: 274  
Errors.processWithException(Producer<T>) line: 232  
ApplicationHandler.initialize(ApplicationConfigurator, InjectionManager, Binder) line: 309  
ApplicationHandler.<init>(Application, Binder, Object) line: 274    
WebComponent.<init>(WebConfig, ResourceConfig) line: 311    
WhiteboardServletContainer(ServletContainer).reload(ResourceConfig) line: 650   
WhiteboardServletContainer.reload(ResourceConfig) line: 108 
JerseyServiceRuntime<C>.doDispatch(Map<String,Object>, List<JerseyApplicationProvider>, List<JerseyExtensionProvider>, List<JerseyResourceProvider>) line: 514  
JerseyServiceRuntime<C>.doInternalUpdate() line: 373    
JerseyServiceRuntime<C>.lambda$scheduleUpdate$0() line: 338 
0x0000000800daf9a8.run() line: not available    
Executors$RunnableAdapter<T>.call() line: 539   
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>(FutureTask<V>).run() line: 264   
ScheduledThreadPoolExecutor$ScheduledFutureTask<V>.run() line: 304  
ScheduledThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1136 
ThreadPoolExecutor$Worker.run() line: 635   
Thread.run() line: 833  
juergen-albert commented 9 months ago

BTW: In my case, the whole setup runs with java17 here and the class it currently tries to handle is called: org.eclipse.osgitech.rest.proxy.Extension_7fffffff_000000000000003c and is the wrapper around the JacksonJsonConverter of @fipro78 .

juergen-albert commented 9 months ago

@timothyjward I took the liberty of assigning this to you for now.

fipro78 commented 9 months ago

After some more testing I noticed that the issue is related to the usage of generics in the extension service interfaces.

The following class declaration fails with the above exception:

public class JacksonJsonConverter<T> implements MessageBodyReader<T>, MessageBodyWriter<T>

If I remove the generics like in the following class declaration, everything works as intended:

public class JacksonJsonConverter implements MessageBodyReader, MessageBodyWriter

The issue also comes up with other supported extension interfaces. I tested with an ExceptionMapper for verification. ContextResolver, ExceptionMapper, MessageBodyReader and MessageBodyWriter are supported extension interfaces with generics. And everyone of them causes an exception if the generic is used in the class definition.

timothyjward commented 9 months ago

The following is not valid:

public class JacksonJsonConverter<T> implements MessageBodyReader<T>, MessageBodyWriter<T>

You need it to be reified, for example:

public class JacksonJsonConverter implements MessageBodyReader<Object>, MessageBodyWriter<Object>

You can see this is done in the official specification examples

fipro78 commented 9 months ago

Well, I don't see where it explicitly says that the usage of generics like I did would be invalid. And it worked this way with the old Aries JAX-RS Whiteboard implementation. So I am not sure if the statement "is not valid" is really correct.

But you are right, changing it to the signature you showed resolves the issue.

timothyjward commented 9 months ago

So I am not sure if the statement "is not valid" is really correct.

Jakarta EE specifications are notoriously woolly, and allow quite divergent behaviours to be considered valid. In this case Jersey (the reference implementation) has a strict requirement to be able to reify the type parameter of an extension to an exact type. Other implementations may be looser, but Jersey sets the standard here (why they can't write these things down I will never know...)

This part of the constructor is for the "holder" of a MessageBodyReader/Writer:

https://github.com/eclipse-ee4j/jersey/blob/ab9953f87ab3ca043cec9c863e9a5aba1006628a/core-common/src/main/java/org/glassfish/jersey/message/AbstractEntityProviderModel.java#L56

and it calls this part, which requires reification of the type

https://github.com/eclipse-ee4j/jersey/blob/ab9953f87ab3ca043cec9c863e9a5aba1006628a/core-common/src/main/java/org/glassfish/jersey/message/AbstractEntityProviderModel.java#L96-L102

fipro78 commented 9 months ago

The interesting thing is, that if I register my converter with the "invalid" class definition via a Jakarta RS Feature, it works.

But anyhow, thanks for your explanations and your time. I will try to include this in my upcoming tutorial about the Jakarta RS Whiteboard.

Feel free to close this issue. I understand that the issue is on the user side. Although it is very unfortunate that the exception is not pointing in the right direction. Or would it be possible to add some checks to provide a better error message that could help a user to solve the issue?

timothyjward commented 9 months ago

Thinking further about this, one thing did come to mind. When an extension is published to the whiteboard we create a dynamic class for it. This is to allow us to register multiple services even if they are of the same type (which is normally disallowed).

It's possible that in this situation the class we're creating is a valid class, but with generics data that can't be parsed by Jersey.

This is the generic signature we use:

https://github.com/osgi/jakartarest-osgi/blob/eec93df23b98fdd0c392117e5e530c95e6e206fe/org.eclipse.osgitech.rest/src/main/java/org/eclipse/osgitech/rest/proxy/ExtensionProxyFactory.java#L63

We will need a unit test to be sure...

timothyjward commented 8 months ago

@fipro78 @juergen-albert @maho7791 - please look at Pull Request #41

I've done my best to think of all possible cases, but generics aren't trivial so if you have other examples to add to the tests then please add them!

fipro78 commented 7 months ago

@timothyjward Sorry for the late feedback. As you already mentioned, the generics processing is quite complicated, so I only half understood your code you added to fix the issue. But I did some tests with a locally build version from the main branch, and the issues I had before are resolved now. The converter with the following signature is resolved and does not cause the initially reported exception anymore

public class JacksonJsonConverter<T> implements MessageBodyReader<T>, MessageBodyWriter<T>