thymeleaf / thymeleaf-spring

Thymeleaf integration module for Spring
http://www.thymeleaf.org
Apache License 2.0
434 stars 156 forks source link

thymeleaf-spring5 ClassNotFoundException ognl/PropertyProcessor #203

Open tcuje opened 5 years ago

tcuje commented 5 years ago

I tried to use thymeleaf in my project, but get the following exception: java.lang.NoClassDefFoundError: ognl/PropertyAccessor

My versions copied from mvn dependency:tree

org.thymeleaf:thymeleaf-spring5:jar:3.0.11.RELEASE:compile
  \- org.thymeleaf:thymeleaf:jar:3.0.11.RELEASE:compile
     +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile
     \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile

I think the issue here is that ognl is excluded by thymeleaf-spring5/pom.xml, see https://github.com/thymeleaf/thymeleaf-spring/blob/3.0-master/thymeleaf-spring5/pom.xml#L318

Unfortunately the relevant commits do not state why it was excluded, see b6a4911 and 896a147

ultraq commented 5 years ago

OGNL is excluded when Thymeleaf is in a Spring project (when including the thymeleaf-spring module) so that the Spring Expression Language (SpEL) is used over OGNL in your templates.

If you've got a Spring Boot project, then this should be taken care of automatically if you import the right starter modules and so no use of OGNL will come up and no ClassNotFoundException should be thrown. If you're using Spring Framework and manually configuring your app to use Thymeleaf, then the setup/configuration is a bit more involved but is described in the Thymeleaf + Spring Tutorial doc which you can find here: https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html#the-springstandard-dialect

tcuje commented 5 years ago

Im using the following package for the project:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

It's the only reference to thymeleaf I have in my pom.xml

mermetbt commented 5 years ago

I had the same issue as you, and adding this solve the problem for me:

        <dependency>
            <groupId>ognl</groupId>
            <artifactId>ognl</artifactId>
            <version>3.1.12</version>
        </dependency>
lurodrig commented 5 years ago

Hello there,

In my case I am using it in a junit test:

import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.thymeleaf.TemplateEngine;

/**
 *
 * @author lurodrig
 */
@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties
@SpringBootTest(classes = {MessageFactoryServiceImpl.class,TemplateEngine.class})
public class MessageFactoryServiceTest {

    @Value("${test.emailAddress}")
    private String emailAddress;

    @Value("${test.barcodeText}")
    private String barcodeText;

    @Value("${test.registrationLink}")
    private String registrationLink;

    @Value("${test.barcodeBase64}")
    private String barcodeBase64;

    @Autowired
    private MessageFactoryService messageFactoryService;

    @Test
    public void test_A_emailTextIsRightlyProcessed() {
        Map<String, Object> messageVariables = new HashMap<>();
        messageVariables.put(TemplateConstants.EMAIL_ADDRESS, emailAddress);
        messageVariables.put(TemplateConstants.BARCODE_BASE_64, barcodeBase64);
        messageVariables.put(TemplateConstants.BARCODE_TEXT, barcodeText);
        messageVariables.put(TemplateConstants.REGISTRATION_LINK, registrationLink);
        String message = messageFactoryService.buildVerificationMessage(messageVariables);
        System.out.println(message);
    }
}

The trick of @mermetbt worked for me...

        <dependency>
            <groupId>ognl</groupId>
            <artifactId>ognl</artifactId>
            <version>3.2.10</version>
            <scope>test</scope>
        </dependency>

But now I am facing the issue (yet another :) of spring not taking into account the configuration from src/test/resources/application.properties for thymeleaf :(

Thanks,

Luis

amanbhole commented 3 years ago

After lot of experimentation, following line makes the issue OGNL issue disappear for both Spring and Spring boot: TemplateEngine templateEngine = new SpringTemplateEngine();

Further, for spring boot to work properly, I had to configure engine as below: @Bean @Primary public TemplateEngine textTemplateEngine() { TemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver()); return templateEngine; }

As my use case is about simple string replacement in text templates, following is template resolver configuration: private ITemplateResolver templateResolver() { StringTemplateResolver templateResolver = new StringTemplateResolver(); templateResolver.setTemplateMode(TemplateMode.TEXT); return templateResolver; }

tcuje commented 2 years ago

I can confirm that replacing TemplateEngine templateEngine = new TemplateEngine(); with TemplateEngine templateEngine = new SpringTemplateEngine(); as suggested by @amanbhole worked for us, too. Much thanks!

AlperMulayim commented 1 year ago

Hello Everyone, @tcuje's solution worked for me. TemplateEngine templateEngine = new SpringTemplateEngine(); SpringBoot version: 2.7.11-SNAPSHOT Thanks.