When using SO-Charts addon in Liferay Vaadin portlet NullPointerException is thrown. SO-Charts uses LitTemplate to add a component for the "echarts" Javascript library. NullPointerException is thrown when rendering the component.
Problem lays in how LitTemplate tries to get Vaadin Portlet external stats JSON.
1)LitTemplate is initialized in the ReflectionCache wrapper that clears session, and request (CurrentInstants) information for initialization.
LitTemplateInitializer:L87ReflectionCache:L78
2)Portlets use external stats JSON with URL configured as a relative path without the scheme, host, and port.
Scheme, host, and port are intended to get from VaadinRequest.getCurrent(), but there lies the problem as VaadinRequest is null because of the first point with ReflectionCache cleared session wrapper.
FrontendUtils:L574FrontendUtils:L753
The current Workaround for this is to include the host in external stats JSON configuration like this:
"externalStatsUrl": "http://localhost:8080/o/vaadin-portlet-static/VAADIN/config/stats.json"
Expected can create and use custom components using LitTemplate class
Actual cannot use custom components using LitTemplate class
Versions:
Vaadin Portlet version 1.0.0 (But will have the same issue in 2.X.X)
Flow version 14.8.8 (But will have the same issue in 23.X)
Portal (Liferay) version 7.3.10
Java version 11
Stacktrace:
ERROR com.vaadin.flow.portal.DefaultPortletErrorHandler - java.lang.NullPointerException java.lang.NullPointerException at com.vaadin.flow.server.frontend.FrontendUtils.getHostString(FrontendUtils.java:507) at com.vaadin.flow.server.frontend.FrontendUtils.getStatsFromExternalUrl(FrontendUtils.java:470) at com.vaadin.flow.server.frontend.FrontendUtils.getStatsContent(FrontendUtils.java:396) at com.vaadin.flow.component.littemplate.internal.LitTemplateParserImpl.getSourcesFromStats(LitTemplateParserImpl.java:209) at com.vaadin.flow.component.littemplate.internal.LitTemplateParserImpl.getTemplateContent(LitTemplateParserImpl.java:118) at com.vaadin.flow.component.littemplate.LitTemplateDataAnalyzer.parseTemplate(LitTemplateDataAnalyzer.java:75) at com.vaadin.flow.component.littemplate.LitTemplateInitializer.lambda$null$561a9683$1(LitTemplateInitializer.java:91) at com.vaadin.flow.internal.ReflectionCache.lambda$wrapValueProvider$d0062d93$1(ReflectionCache.java:93) at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) at com.vaadin.flow.internal.ReflectionCache.get(ReflectionCache.java:110) at com.vaadin.flow.component.littemplate.LitTemplateInitializer.<init>(LitTemplateInitializer.java:92) at com.vaadin.flow.component.littemplate.LitTemplate.<init>(LitTemplate.java:93) at com.vaadin.flow.component.littemplate.LitTemplate.<init>(LitTemplate.java:80) at com.storedobject.helper.LitComponent.<init>(LitComponent.java:45) at com.storedobject.chart.SOChart.<init>(SOChart.java:92) at de.unioninvestment.portal.sperrverwaltung.views.MainView.addChart(MainView.java:162) at de.unioninvestment.portal.sperrverwaltung.views.MainView.onAttach(MainView.java:133) at com.vaadin.flow.component.ComponentUtil.onComponentAttach(ComponentUtil.java:231) at com.vaadin.flow.internal.nodefeature.ComponentMapping.lambda$onAttach$0(ComponentMapping.java:104) at java.base/java.util.Optional.ifPresent(Optional.java:183) at com.vaadin.flow.internal.nodefeature.ComponentMapping.onAttach(ComponentMapping.java:103) at com.vaadin.flow.internal.StateNode.lambda$fireAttachListeners$8(StateNode.java:839) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) at com.vaadin.flow.internal.StateNode.forEachFeature(StateNode.java:351) at com.vaadin.flow.internal.StateNode.fireAttachListeners(StateNode.java:839) at com.vaadin.flow.internal.StateNode.onAttach(StateNode.java:326) at com.vaadin.flow.internal.StateNode.setParent(StateNode.java:278) at com.vaadin.flow.internal.nodefeature.NodeFeature.attachPotentialChild(NodeFeature.java:80) at com.vaadin.flow.internal.nodefeature.StateNodeNodeList.add(StateNodeNodeList.java:55) at com.vaadin.flow.internal.nodefeature.ElementChildrenList.add(ElementChildrenList.java:44) at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.insertChild(AbstractNodeStateProvider.java:104) at com.vaadin.flow.dom.Node.insertChild(Node.java:294) at com.vaadin.flow.dom.Node.appendChild(Node.java:141) at com.vaadin.flow.component.HasComponents.add(HasComponents.java:55) at de.unioninvestment.portal.sperrverwaltung.views.PortletMainView.addPageForMode(PortletMainView.java:44) at de.unioninvestment.portal.sperrverwaltung.views.PortletMainView.onAttach(PortletMainView.java:35) at com.vaadin.flow.component.ComponentUtil.onComponentAttach(ComponentUtil.java:231)
When using SO-Charts addon in Liferay Vaadin portlet NullPointerException is thrown. SO-Charts uses LitTemplate to add a component for the "echarts" Javascript library. NullPointerException is thrown when rendering the component.
Problem lays in how LitTemplate tries to get Vaadin Portlet external stats JSON.
1)LitTemplate is initialized in the ReflectionCache wrapper that clears session, and request (CurrentInstants) information for initialization. LitTemplateInitializer:L87 ReflectionCache:L78
2)Portlets use external stats JSON with URL configured as a relative path without the scheme, host, and port. Scheme, host, and port are intended to get from VaadinRequest.getCurrent(), but there lies the problem as VaadinRequest is null because of the first point with ReflectionCache cleared session wrapper. FrontendUtils:L574 FrontendUtils:L753
The current Workaround for this is to include the host in external stats JSON configuration like this:
"externalStatsUrl": "http://localhost:8080/o/vaadin-portlet-static/VAADIN/config/stats.json"
Minimal reproducible example
Expected and actual behavior:
Versions:
Stacktrace:
ERROR com.vaadin.flow.portal.DefaultPortletErrorHandler - java.lang.NullPointerException java.lang.NullPointerException at com.vaadin.flow.server.frontend.FrontendUtils.getHostString(FrontendUtils.java:507) at com.vaadin.flow.server.frontend.FrontendUtils.getStatsFromExternalUrl(FrontendUtils.java:470) at com.vaadin.flow.server.frontend.FrontendUtils.getStatsContent(FrontendUtils.java:396) at com.vaadin.flow.component.littemplate.internal.LitTemplateParserImpl.getSourcesFromStats(LitTemplateParserImpl.java:209) at com.vaadin.flow.component.littemplate.internal.LitTemplateParserImpl.getTemplateContent(LitTemplateParserImpl.java:118) at com.vaadin.flow.component.littemplate.LitTemplateDataAnalyzer.parseTemplate(LitTemplateDataAnalyzer.java:75) at com.vaadin.flow.component.littemplate.LitTemplateInitializer.lambda$null$561a9683$1(LitTemplateInitializer.java:91) at com.vaadin.flow.internal.ReflectionCache.lambda$wrapValueProvider$d0062d93$1(ReflectionCache.java:93) at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1705) at com.vaadin.flow.internal.ReflectionCache.get(ReflectionCache.java:110) at com.vaadin.flow.component.littemplate.LitTemplateInitializer.<init>(LitTemplateInitializer.java:92) at com.vaadin.flow.component.littemplate.LitTemplate.<init>(LitTemplate.java:93) at com.vaadin.flow.component.littemplate.LitTemplate.<init>(LitTemplate.java:80) at com.storedobject.helper.LitComponent.<init>(LitComponent.java:45) at com.storedobject.chart.SOChart.<init>(SOChart.java:92) at de.unioninvestment.portal.sperrverwaltung.views.MainView.addChart(MainView.java:162) at de.unioninvestment.portal.sperrverwaltung.views.MainView.onAttach(MainView.java:133) at com.vaadin.flow.component.ComponentUtil.onComponentAttach(ComponentUtil.java:231) at com.vaadin.flow.internal.nodefeature.ComponentMapping.lambda$onAttach$0(ComponentMapping.java:104) at java.base/java.util.Optional.ifPresent(Optional.java:183) at com.vaadin.flow.internal.nodefeature.ComponentMapping.onAttach(ComponentMapping.java:103) at com.vaadin.flow.internal.StateNode.lambda$fireAttachListeners$8(StateNode.java:839) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474) at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) at com.vaadin.flow.internal.StateNode.forEachFeature(StateNode.java:351) at com.vaadin.flow.internal.StateNode.fireAttachListeners(StateNode.java:839) at com.vaadin.flow.internal.StateNode.onAttach(StateNode.java:326) at com.vaadin.flow.internal.StateNode.setParent(StateNode.java:278) at com.vaadin.flow.internal.nodefeature.NodeFeature.attachPotentialChild(NodeFeature.java:80) at com.vaadin.flow.internal.nodefeature.StateNodeNodeList.add(StateNodeNodeList.java:55) at com.vaadin.flow.internal.nodefeature.ElementChildrenList.add(ElementChildrenList.java:44) at com.vaadin.flow.dom.impl.AbstractNodeStateProvider.insertChild(AbstractNodeStateProvider.java:104) at com.vaadin.flow.dom.Node.insertChild(Node.java:294) at com.vaadin.flow.dom.Node.appendChild(Node.java:141) at com.vaadin.flow.component.HasComponents.add(HasComponents.java:55) at de.unioninvestment.portal.sperrverwaltung.views.PortletMainView.addPageForMode(PortletMainView.java:44) at de.unioninvestment.portal.sperrverwaltung.views.PortletMainView.onAttach(PortletMainView.java:35) at com.vaadin.flow.component.ComponentUtil.onComponentAttach(ComponentUtil.java:231)