我正在 Quarkus 框架中开发一个使用嵌入式 Camunda DMN 引擎的应用程序,但我在使用 GraalVM 进行本机编译时遇到问题。
问题是在运行时它无法找到 camunda 库未放置在资源文件夹中的一些 XSD 文件,它将它们放置在一个包中,如图所示。
我使用了该命令,以便在应用程序执行期间生成配置文件,以便能够在本机中编译。
$JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=native-config -jar target/quarkus-app/quarkus-run.jar
这在 resources-config.json 文件中生成了以下结构
{
"resources":{
"includes":[
{"pattern":"\\QMETA-INF/services/io.smallrye.config.ConfigSourceFactory\\E"},
{"pattern":"\\QMETA-INF/services/io.smallrye.config.SmallRyeConfigFactory\\E"},
{"pattern":"\\QMETA-INF/services/io.vertx.core.spi.BufferFactory\\E"},
{"pattern":"\\QMETA-INF/services/io.vertx.core.spi.FutureFactory\\E"},
{"pattern":"\\QMETA-INF/services/javax.script.ScriptEngineFactory\\E"},
{"pattern":"\\QMETA-INF/services/org.eclipse.microprofile.config.spi.ConfigSource\\E"},
{"pattern":"\\QMETA-INF/services/org.eclipse.microprofile.config.spi.Converter\\E"},
{"pattern":"\\Qapplication.properties\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN11.xsd\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN11_Alternative.xsd\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN12.xsd\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN13.xsd\\E"},
{"pattern":"\\Qorg/jboss/threads/Version.properties\\E"}
]},
"bundles":[{"name":"com.sun.org.apache.xerces.internal.impl.xpath.regex.message"}]
}
如您所见,对资源的访问是通过模式推断出来的"\\Qorg/camunda/bpm/model/dmn/schema/DMN13.xsd\\E"
。
我的资源配置文件看起来像这样
{
"bundles": [
{
"name": "com.sun.org.apache.xerces.internal.impl.msg.XMLSchemaMessages"
},
{
"name":"com.sun.org.apache.xerces.internal.impl.xpath.regex.message"
}
],
"resources": {
"includes": [
{"pattern":"\\QMETA-INF/services/io.smallrye.config.ConfigSourceFactory\\E"},
{"pattern":"\\QMETA-INF/services/io.smallrye.config.SmallRyeConfigFactory\\E"},
{"pattern":"\\QMETA-INF/services/io.vertx.core.spi.FutureFactory\\E"},
{"pattern":"\\QMETA-INF/services/javax.script.ScriptEngineFactory\\E"},
{"pattern":"\\QMETA-INF/services/org.eclipse.microprofile.config.spi.ConfigSource\\E"},
{"pattern":"\\QMETA-INF/services/org.eclipse.microprofile.config.spi.Converter\\E"},
{"pattern":"\\Qapplication.properties\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN11.xsd\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN11_Alternative.xsd\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN12.xsd\\E"},
{"pattern":"\\Qorg/camunda/bpm/model/dmn/schema/DMN13.xsd\\E"},
{"pattern":"\\Qorg/jboss/threads/Version.properties\\E"}
]
}
}
使用命令本地编译 quarkus 应用程序时./mvnw package -Pnative
。
这会生成本机可执行文件并很好地执行部署,但是当我发出使用 camunda 的请求时,它会生成错误
Caused by: org.camunda.bpm.model.dmn.DmnModelException: Unable to parse model
at org.camunda.bpm.model.dmn.impl.DmnParser.parseModelFromStream(DmnParser.java:79)
at org.camunda.bpm.model.dmn.Dmn.doReadModelFromInputStream(Dmn.java:245)
at org.camunda.bpm.model.dmn.Dmn.readModelFromStream(Dmn.java:158)
at org.camunda.bpm.dmn.engine.impl.transform.DefaultDmnTransform.setModelInstance(DefaultDmnTransform.java:111)
... 33 more
Caused by: org.camunda.bpm.model.xml.ModelParseException: SAXException while parsing input stream
at org.camunda.bpm.model.xml.impl.util.DomUtil.parseInputStream(DomUtil.java:245)
at org.camunda.bpm.model.xml.impl.parser.AbstractModelParser.parseModelFromStream(AbstractModelParser.java:131)
at org.camunda.bpm.model.dmn.impl.DmnParser.parseModelFromStream(DmnParser.java:76)
... 36 more
Caused by: org.xml.sax.SAXException: Error: URI=null Line=1: schema_reference.4: Failed to read schema document 'jar:file:/home/jonathanch/Documents/workspace/trabajo/servicio-motor/target/servicio-motor-1.0.0-SNAPSHOT-native-image-source-jar/lib/org.camunda.bpm.model.camunda-dmn-model-7.14.0.jar!/org/camunda/bpm/model/dmn/schema/DMN13.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
at org.camunda.bpm.model.xml.impl.util.DomUtil$DomErrorHandler.error(DomUtil.java:202)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:138)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:396)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:306)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4257)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4240)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument1(XSDHandler.java:2531)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getSchemaDocument(XSDHandler.java:2238)
at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:588)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.processJAXPSchemaSource(XMLSchemaLoader.java:844)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:606)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.findSchemaGrammar(XMLSchemaValidator.java:2710)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2069)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:829)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3063)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:836)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:534)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:246)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:339)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:122)
at org.camunda.bpm.model.xml.impl.util.DomUtil.parseInputStream(DomUtil.java:240)
检查文件的路径,我看到 jar 中有文件。错误是什么?在这里,我对 GraalVM 如何发现资源以及如何编写模式以在编译时包含资源感到困惑。
我也尝试过 pattern {"pattern":".*/DMN1.*xsd$"}
,但问题仍然存在。
注意:
这是使用命令执行应用程序时生成的对那些资源的访问跟踪$JAVA_HOME/bin/java -agentlib:native-image-agent=trace-output=native-config/trace-file.json -jar target/quarkus-app/quarkus-run.jar
[...{"caller_class":"java.util.Arrays", "result":true, "args":["[Ljava.lang.Class;"], "function":"newInstance", "tracer":"reflect", "class":"java.lang.reflect.Array"},
{"caller_class":"java.lang.invoke.InnerClassLambdaMetafactory", "result":true, "args":["get$Lambda",["java.io.File"]], "function":"findMethodHandle", "tracer":"reflect", "class":"jdk.xml.internal.SecuritySupport$$Lambda$258/0x0000000840325840"},
{"caller_class":"org.camunda.bpm.model.xml.impl.util.ReflectUtil", "result":true, "args":["org/camunda/bpm/model/dmn/schema/DMN13.xsd"], "function":"getResource", "tracer":"reflect", "class":"io.quarkus.bootstrap.runner.RunnerClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN13.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$AppClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN13.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"},
{"caller_class":"org.camunda.bpm.model.xml.impl.util.ReflectUtil", "result":true, "args":["org/camunda/bpm/model/dmn/schema/DMN12.xsd"], "function":"getResource", "tracer":"reflect", "class":"io.quarkus.bootstrap.runner.RunnerClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN12.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$AppClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN12.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"},
{"caller_class":"org.camunda.bpm.model.xml.impl.util.ReflectUtil", "result":true, "args":["org/camunda/bpm/model/dmn/schema/DMN11.xsd"], "function":"getResource", "tracer":"reflect", "class":"io.quarkus.bootstrap.runner.RunnerClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN11.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$AppClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN11.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"},
{"caller_class":"org.camunda.bpm.model.xml.impl.util.ReflectUtil", "result":true, "args":["org/camunda/bpm/model/dmn/schema/DMN11_Alternative.xsd"], "function":"getResource", "tracer":"reflect", "class":"io.quarkus.bootstrap.runner.RunnerClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN11_Alternative.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$AppClassLoader"},
{"caller_class":"java.lang.ClassLoader", "result":false, "args":["org/camunda/bpm/model/dmn/schema/DMN11_Alternative.xsd"], "function":"getResource", "tracer":"reflect", "class":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"},
{"caller_class":"java.util.Arrays", "result":true, "args":["[Ljava.lang.Class;"], "function":"newInstance", "tracer":"reflect", "class":"java.lang.reflect.Array"}...]
我澄清说 GraalVM 正在读取创建的配置文件,因为它需要“捆绑包”的配置。