Spring-boot: Spring Boot 2.1.0 RC1 + thymeleaf doesn't work with JPMS

Created on 19 Oct 2018  路  4Comments  路  Source: spring-projects/spring-boot

The last thymeleaf-spring5 release (3.0.10) introduced a bug when added the Automatic-Module-Name in the manifest. The names added are not JPMS compatible.

Now I can't run Spring Boot + Thymeleaf with JPMS anymore. (this was working in previous versions)

Error:

Error occurred during initialization of boot layer
java.lang.module.FindException: Unable to derive module descriptor for target/modules/thymeleaf-spring5-3.0.10.RELEASE.jar
Caused by: java.lang.module.FindException: Automatic-Module-Name: thymeleaf-spring5: Invalid module name: 'thymeleaf-spring5' is not a Java identifier

Created an issue for them:
https://github.com/thymeleaf/thymeleaf-spring/issues/195

external-project invalid

Most helpful comment

@panga This is now fixed in 3.0.11-SNAPSHOT, you should be able to use it by setting your thymeleaf.version to that version.

All 4 comments

Thanks for the report. The fix for this will have to be made in Thymeleaf. We鈥檒l pick up the new version in due course. In the meantime, you can use the thymeleaf.version property to override the version to one that meets your needs.

@wilkinsona Unfortunately this is not possible, the commit https://github.com/spring-projects/spring-boot/commit/56c1247bbbdbb20025f035b322b1e853e3e3e013 broke compatibility with previous versions. Please reopen this ticket, I'm completely blocked because of this.

Error using older releases:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'viewResolver' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration$ThymeleafWebMvcConfiguration$ThymeleafViewResolverConfiguration': Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'templateEngine' defined in class path resource [org/springframework/boot/autoconfigure/thymeleaf/ThymeleafAutoConfiguration$ThymeleafDefaultConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.thymeleaf.spring5.SpringTemplateEngine]: Factory method 'templateEngine' threw exception; nested exception is java.lang.NoSuchMethodError: org.thymeleaf.spring5.SpringTemplateEngine.setRenderHiddenMarkersBeforeCheckboxes(Z)V

Ah, sorry. I'd forgotten that we'd added those new properties in 2.1.0.RC1. You aren't completely blocked though. In addition to overriding the version, you'll need to declare a couple of beans yourself so that the auto-configuration of them backs off. Adding the following configuration will give you the same behaviour as the auto-configuration:

    @Configuration
    static class ThymeleafConfiguration {

        private final ThymeleafProperties properties;

        ThymeleafConfiguration(ThymeleafProperties properties) {
            this.properties = properties;
        }

        @Bean
        public SpringTemplateEngine templateEngine(
                ObjectProvider<ITemplateResolver> templateResolvers,
                ObjectProvider<IDialect> dialects) {
            SpringTemplateEngine engine = new SpringTemplateEngine();
            engine.setEnableSpringELCompiler(this.properties.isEnableSpringElCompiler());
            templateResolvers.orderedStream().forEach(engine::addTemplateResolver);
            dialects.orderedStream().forEach(engine::addDialect);
            return engine;
        }

        @Bean
        public ThymeleafViewResolver thymeleafViewResolver(
                SpringTemplateEngine templateEngine) {
            ThymeleafViewResolver resolver = new ThymeleafViewResolver();
            resolver.setTemplateEngine(templateEngine);
            resolver.setCharacterEncoding(this.properties.getEncoding().name());
            resolver.setContentType(
                    appendCharset(this.properties.getServlet().getContentType(),
                            resolver.getCharacterEncoding()));
            resolver.setExcludedViewNames(this.properties.getExcludedViewNames());
            resolver.setViewNames(this.properties.getViewNames());
            resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
            resolver.setCache(this.properties.isCache());
            return resolver;
        }

        private String appendCharset(MimeType type, String charset) {
            if (type.getCharset() != null) {
                return type.toString();
            }
            LinkedHashMap<String, String> parameters = new LinkedHashMap<>();
            parameters.put("charset", charset);
            parameters.putAll(type.getParameters());
            return new MimeType(type, parameters).toString();
        }

    }

Depending on your configuration, you may be able to simplify this further, for example by not requiring the appendCharset method.

@panga This is now fixed in 3.0.11-SNAPSHOT, you should be able to use it by setting your thymeleaf.version to that version.

Was this page helpful?
0 / 5 - 0 ratings