Flow: TemplateModelProxyHandler using wrong ClassLoader in OSGi Setup

Created on 17 Jan 2020  路  7Comments  路  Source: vaadin/flow

Hi Folks,

I set up a minimal working Vaadin / OSGi (Karaf) Example. Everything works fine util I use the PolymerTemplate (e.g. when Using a Custom Style for my Page).
Now, I get the following exception:

There was an exception while trying to navigate to '' with the exception message 'Unable to create an instance of 'org.pragmaticindustries.cockpit.DesktopTemplate'. The constructor threw an exception.'

java.lang.IllegalArgumentException: Unable to create an instance of 'org.pragmaticindustries.cockpit.DesktopTemplate'. The constructor threw an exception.
    at com.vaadin.flow.internal.ReflectTools.createProxyInstance(ReflectTools.java:510)
    at com.vaadin.flow.internal.ReflectTools.createInstance(ReflectTools.java:447)
    at com.vaadin.flow.di.DefaultInstantiator.getOrCreate(DefaultInstantiator.java:65)
    at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:158)
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget$1(AbstractNavigationStateRenderer.java:121)
    at java.util.Optional.orElseGet(Optional.java:267)
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:120)
    at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:178)
    at com.vaadin.flow.router.Router.handleNavigation(Router.java:219)
    at com.vaadin.flow.router.Router.navigate(Router.java:190)
    at com.vaadin.flow.router.Router.initializeUI(Router.java:92)
    at com.vaadin.flow.server.BootstrapHandler.createAndInitUI(BootstrapHandler.java:1117)
    at com.vaadin.flow.server.BootstrapHandler.synchronizedHandleRequest(BootstrapHandler.java:396)
    at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
    at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1507)
    at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:242)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:852)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
    at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1591)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:542)
    at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1581)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1307)
    at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:293)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:482)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1549)
    at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1204)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:494)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:374)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:268)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at com.vaadin.flow.internal.ReflectTools.createProxyInstance(ReflectTools.java:479)
    ... 52 more
Caused by: java.lang.NoClassDefFoundError: Lcom/vaadin/flow/internal/StateNode;
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2583)
    at java.lang.Class.getDeclaredField(Class.java:2068)
    at net.bytebuddy.implementation.LoadedTypeInitializer$ForStaticField.onLoad(LoadedTypeInitializer.java:120)
    at net.bytebuddy.implementation.LoadedTypeInitializer$Compound.onLoad(LoadedTypeInitializer.java:187)
    at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:102)
    at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:5623)
    at com.vaadin.flow.templatemodel.TemplateModelProxyHandler.createProxyConstructor(TemplateModelProxyHandler.java:247)
    at com.vaadin.flow.templatemodel.TemplateModelProxyHandler.createInterfaceConstructor(TemplateModelProxyHandler.java:213)
    at com.vaadin.flow.templatemodel.TemplateModelProxyHandler.createProxyConstructor(TemplateModelProxyHandler.java:202)
    at com.vaadin.flow.internal.ReflectionCache.lambda$wrapValueProvider$d0062d93$1(ReflectionCache.java:84)
    at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
    at com.vaadin.flow.internal.ReflectionCache.get(ReflectionCache.java:101)
    at com.vaadin.flow.templatemodel.TemplateModelProxyHandler.createModelProxy(TemplateModelProxyHandler.java:193)
    at com.vaadin.flow.component.polymertemplate.PolymerTemplate.createTemplateModelInstance(PolymerTemplate.java:205)
    at com.vaadin.flow.component.polymertemplate.PolymerTemplate.getModel(PolymerTemplate.java:197)
    at com.vaadin.flow.component.polymertemplate.PolymerTemplate.initModel(PolymerTemplate.java:228)
    at com.vaadin.flow.component.polymertemplate.PolymerTemplate.<init>(PolymerTemplate.java:114)
    at com.vaadin.flow.component.polymertemplate.PolymerTemplate.<init>(PolymerTemplate.java:122)
    at org.pragmaticindustries.cockpit.DesktopTemplate.<init>(DesktopTemplate.java:55)
    ... 57 more
Caused by: java.lang.ClassNotFoundException: com.vaadin.flow.internal.StateNode
    at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:347)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 77 more

I did some research and all my Classloading and OSGi Setup seems valid.
When going through the Code I saw that the TemplateModelProxy handler uses ByteBuddy in the createProxyConstructor(ClassLoader classLoader, Builder<?> proxyBuilder, String classFqn) Method.
Here make() (TemplateModelProxyHandler:246) is called with no parameters which leads ByteBuddy to use an Implemementation with the "default" parameters make(typeResolutionStrategy, TypePool.ClassLoading.ofSystemLoader()) (in SubclassDynamicTypeBuilder:189).

This then messes everything up, as the SystemClassloader is of course pretty empty in OSGi Setup.

So I guess givin the proper parameters to the make() call could / should fix this issue. Until then, no usage of Polymertemplates on OSGi should be possible, sadly.

Low OSGi Major bug

Most helpful comment

@mehdi-vaadin sorry for no update in that long time. I did not test yet, but if it works I will submit a PR asap and hope that it gets merged : )

All 7 comments

I think changing L248 in TemplateModelProxyHandler to .name(proxyClassName).make(TypeResolutionStrategy.Passive.INSTANCE, TypePool.ClassLoading.of(classLoader)) (was .name(proxyClassName).make()) should do the trick, will try to validate that though.

@JulianFeinauer thank you very much for reporting this issue. Did you have any progress with validating the fix you had suggested? Would you like to create a PR based on that?

@mehdi-vaadin sorry for no update in that long time. I did not test yet, but if it works I will submit a PR asap and hope that it gets merged : )

@JulianFeinauer no worries. Thanks :)

@mehdi-vaadin I checked my suggested simple solution and it does not work, as straightforward, yet. I opened a question on SO (https://stackoverflow.com/questions/60140921/fix-classloading-issue-with-bytebuddy-and-vaadin-in-osgi-setup). I hope to get some help from ByteBuddy experts there...

@mehdi-vaadin it seems like I found a solution now with the help of SO.
From a first quick check it looks like the fix in my branch https://github.com/JulianFeinauer/flow/tree/bugfix/7377-fix-template-in-osgi works.
I will try to confirm it this week and then create a PR.

@JulianFeinauer that's great news. Thanks.

Was this page helpful?
0 / 5 - 0 ratings