Closed tbee closed 1 week ago
This project is written in Groovy, which allows extension methods to be written for existing classes, and is how it's able to call an Model.first()
without one existing in Thymeleaf. It does this with a little configuration data that normally lives in a the /META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
file in a JAR, which I make sure to ship when publishing this project.
This issue sounds very similar to some others in the past (#220, #223) where the tool used to create a fat/uber JAR needs to be configured to retain this information so that extension methods can continue to work. In the case of Shadow, the following configuration is required: https://imperceptiblethoughts.com/shadow/configuration/merging/#merging-groovy-extension-modules
If you're also using Shadow, then that link should help create the correct JAR for your project. If not, then I hope this info helps point you in the right direction for what's needed so that the layout dialect can continue to work when rebundled like this.
Ah, that explains. I've setup Thymeleaf in a Quakus server and the default UberJar packaging probably leaves that out. I'll see if that can be tuned.
It appears the services files contains two configurations. Need to figure out where those come from.
moduleName = thymeleaf-layout-dialect-extensions
moduleVersion = 3.3.0
extensionClasses = nz.net.ultraq.thymeleaf.layoutdialect.context.extensions.IContextExtensions, nz.net.ultraq.thymeleaf.layoutdialect.fragments.extensions.FragmentExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.IAttributeExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.ICloseElementTagExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.IModelExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.IProcessableElementTagExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.IStandaloneElementTagExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.ITemplateEventExtensions, nz.net.ultraq.thymeleaf.layoutdialect.models.extensions.ITextExtensions
#
# Copyright 2020, Emanuel Rabina (http://www.ultraq.net.nz/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
moduleName = groovy-extensions
moduleVersion = 2.1.0
extensionClasses = nz.net.ultraq.groovy.extensions.BlockingQueueExtensions, nz.net.ultraq.groovy.extensions.ByteArrayExtensions, nz.net.ultraq.groovy.extensions.ByteBufferExtensions, nz.net.ultraq.groovy.extensions.ExecutorServiceExtensions, nz.net.ultraq.groovy.extensions.FutureExtensions, nz.net.ultraq.groovy.extensions.MapExtensions, nz.net.ultraq.groovy.extensions.ObjectExtensions, nz.net.ultraq.groovy.extensions.SemaphoreExtensions, nz.net.ultraq.groovy.extensions.ShortBufferExtensions
staticExtensionClasses = nz.net.ultraq.groovy.extensions.ByteBufferStaticExtensions, nz.net.ultraq.groovy.extensions.MathStaticExtensions, nz.net.ultraq.groovy.extensions.ObjectStaticExtensions
Took a different approach and switched to spring boot's jar. That solves the duplicate services files conflict. Better.
Addendum; for some reason the spring bootable jar included jars in a folder on the file system in its classpath target/quarkus-app/quarkus
to be exact, and found some generated code. This is not included in the bootable jar itself, so once you deploy that, the jar won't run. So back to resolving the uber-jar conflicts.
I ended up moving the quarkus build to prepare-package and then immediately an unzip of the generated jars into classes. The maven-jar-plugin then included all of them in the spring bootable jar. So for now we're testing with the bootable jar.
Bootable jar did not give the results I needed, so back to the uber-jar. By replacing the layout with thymeleaf's own fragment expressions (looks complexer than they are) this groovy related issue disappeared.
I'm using thymeleaf-layout-dialect 3.3.0 and thymeleaf 3.1.2.RELEASE, AFAIK is exactly the version of thymeleaf that this version of thymeleaf-layout-dialect expects. The application runs fine from the IDE, but in an UberJar I get:
This seems to me thymeleaf-layout-dialect is assuming a first() method exists in Thymeleaf's Model class. It does not. My code does not invoke any 'first' method, so I assume it is something internal. I'm unclear in why it works from the IDE and not from the UberJar; there is only one Thymeleaf dependency in the tree (see the at the bottom).