GML Feature encoding can NPE under heavy load

Description

See GetFeatureTest#testConcurretGet, with high enough values or threads and repeats for the system at hand,
with the following trace:

java.lang.NullPointerException
at java.xml/com.sun.org.apache.xerces.internal.dom.ParentNode.nodeListGetLength(ParentNode.java:697)
at java.xml/com.sun.org.apache.xerces.internal.dom.ParentNode.getLength(ParentNode.java:725)
at org.geotools.xsd.impl.BindingPropertyExtractor.getSequenceElement(BindingPropertyExtractor.java:397)
at org.geotools.xsd.impl.BindingPropertyExtractor.isUnboundedSequence(BindingPropertyExtractor.java:363)
at org.geotools.xsd.impl.BindingPropertyExtractor.properties(BindingPropertyExtractor.java:82)
at org.geotools.xsd.Encoder.encode(Encoder.java:990)
at org.geotools.xsd.Encoder.encode(Encoder.java:552)
at org.geoserver.wfs.xml.GML32OutputFormat.encode(GML32OutputFormat.java:151)
at org.geoserver.wfs.xml.GML3OutputFormat.write(GML3OutputFormat.java:312)
at org.geoserver.wfs.WFSGetFeatureOutputFormat.write(WFSGetFeatureOutputFormat.java:198)
at org.geoserver.ows.Dispatcher.response(Dispatcher.java:1031)
at org.geoserver.ows.Dispatcher.handleRequestInternal(Dispatcher.java:269)
at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:998)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:890)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:875)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.geoserver.test.GeoServerSystemTestSupport$2.service(GeoServerSystemTestSupport.java:1654)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
at org.geoserver.test.GeoServerSystemTestSupport.dispatch(GeoServerSystemTestSupport.java:1683)
at org.geoserver.test.GeoServerSystemTestSupport.dispatch(GeoServerSystemTestSupport.java:1594)
at org.geoserver.test.GeoServerSystemTestSupport.getAsServletResponse(GeoServerSystemTestSupport.java:1049)
at org.geoserver.test.GeoServerSystemTestSupport.getAsServletResponse(GeoServerSystemTestSupport.java:1032)
at org.geoserver.test.GeoServerSystemTestSupport.get(GeoServerSystemTestSupport.java:992)
at org.geoserver.test.GeoServerSystemTestSupport.getAsDOM(GeoServerSystemTestSupport.java:1426)
at org.geoserver.test.GeoServerSystemTestSupport.getAsDOM(GeoServerSystemTestSupport.java:1274)
at org.geoserver.wfs.v2_0.GetFeatureTest.testGetFifteenAll(GetFeatureTest.java:233)
at org.geoserver.wfs.v2_0.GetFeatureTest.lambda$testConcurrentGet$0(GetFeatureTest.java:130)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
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)

 

Hypothesis: despite the synchronizations, the FeatureTypeSchemaBuilder is adding imports of various schemas into the schema for the output... and those changes in XSD are bilateral. However, we cannot really stop and wait for the entire encoding of one GML document to be finished before setting up schemas for the others. I don't see an immediate solution for this, looks like we'd have to scrap XSD and the gt-xsd encoder, and use something else that can support concurrent access...

 

Another possible approach could be not to build the encoding schemas over and over, for each encoding, but cache the results for a given list of feature types… to be evaluated…

Environment

None

Assignee

Andrea Aime

Reporter

Andrea Aime

Triage

None

Fix versions

None

Affects versions

None

Priority

Medium
Configure