我们正在使用 Thymeleaf 视图和布局方言运行 Micronaut(我们通过覆盖 Micronaut 的
ThymeleafFactory
来手动添加它)。以下是依赖项(Micronaut 版本为 3.2.7):
implementation 'io.micronaut.views:micronaut-views-core:3.1.2'
implementation 'io.micronaut.views:micronaut-views-thymeleaf:3.1.2'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.0.0'
有问题的代码是这样的:
<html layout:decorate="~{/layout-top}">
使用
./gradlew run
运行时似乎工作正常,但使用 java -jar ...
从胖(阴影)罐子运行时会崩溃。这将指向类路径问题,但我们无法弄清楚这些问题是什么。
运行shadow jar时的错误消息如下:
Caused by: groovy.lang.MissingMethodException: No signature of method: io.micronaut.views.thymeleaf.WebEngineContext.getOrCreate() is applicable for argument types: (String, nz.net.ultraq.thymeleaf.layoutdialect.context.extensions.IContextExtensions$_getPrefixForDialect_closure1) values: [DialectPrefix::org.thymeleaf.standard.StandardDialect, nz.net.ultraq.thymeleaf.layoutdialect.context.extensions.IContextExtensions$_getPrefixForDialect_closure1@26b0c4d0]
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:70)
at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:46)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at nz.net.ultraq.thymeleaf.layoutdialect.context.extensions.IContextExtensions.getPrefixForDialect(IContextExtensions.groovy:54)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:54)
at org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod.invoke(NewInstanceMetaMethod.java:54)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:247)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
at nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.IProcessableElementTagExtensions.equalsIgnoreXmlnsAndWith(IProcessableElementTagExtensions.groovy:60)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod.invoke(ReflectionMetaMethod.java:54)
at org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod.invoke(NewInstanceMetaMethod.java:54)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:247)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at nz.net.ultraq.thymeleaf.layoutdialect.decorators.DecorateProcessor.doProcess(DecorateProcessor.groovy:103)
at org.thymeleaf.processor.element.AbstractAttributeModelProcessor.doProcess(AbstractAttributeModelProcessor.java:77)
我们对此进行了调试并隔离了
nz.net.ultraq.thymeleaf.layoutdialect.context.extensions.IContextExtensions
中的失败代码:
static String getPrefixForDialect(IContext self, Class<IProcessorDialect> dialectClass) {
return self.getOrCreate(DIALECT_PREFIX_PREFIX + dialectClass.name) { ->
def dialectConfiguration = self.configuration.dialectConfigurations.find { dialectConfig ->
return dialectClass.isInstance(dialectConfig.dialect)
}
return dialectConfiguration?.prefixSpecified ?
dialectConfiguration?.prefix :
dialectConfiguration?.dialect?.prefix
}
}
似乎
IContext
的说法并不是应该的,但我们无法真正找到其根本原因。也不知道为什么运行相同代码的两种不同方法会有不同的行为。
经过进一步调查,我们发现这与shadow jar插件中的这个错误有关:https://github.com/johnrengelman/shadow/issues/490
图书馆
thymeleaf-layout-dialect
正在使用nz.net.ultraq.extensions:groovy-extensions:1.1.0
反过来,它通过 META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
注册一些 Groovy 扩展
shadow jar 插件不能正确处理这些(它只处理
META-INF/groovy/...
路径)。
根据此处的票证评论https://github.com/johnrengelman/shadow/issues/490,有一个解决方法,但它非常令人不快。
我通过升级 Gradle 版本修复了它
./gradlew wrapper --gradle-version 7.6.4
(您可能需要 7.6.4 以外的版本,但对我来说这是最可行的)
使用 Thymeleaf 布局方言时,我收到“没有方法签名:org.thymeleaf.context.EngineContext.getOrCreate”。我试图使用 Maven 程序集插件将项目的所有类打包到一个可执行的 jar 中。我最终不得不放弃,而是生产了 2 罐。一个是一个带有我的非百里香布局依赖项的罐子。另一个是百里香布局方言罐子。我将两个 jar 添加到我的类路径中并指定了我的主类,它开始工作