javaspringspring-bootthymeleafdandelion

Spring Boot + Thymeleaf + Dandelion configuration not working


I'm using Spring Boot with Thymeleaf and now I want to add Dandelion datatables, but it doesn't work.

Here is my maven dependencies:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.1.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

<!-- Dandelion -->
<dependency>
    <groupId>com.github.dandelion</groupId>
    <artifactId>datatables-thymeleaf</artifactId>
    <version>0.10.1</version>
</dependency>

I'm following this guide http://dandelion.github.io/dandelion/docs/installation/thymeleaf.html and configured the following beans:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public FilterRegistrationBean dandelion() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new DandelionFilter());
        registrationBean.addUrlPatterns("/*");
        return registrationBean;
    }

    @Bean
    public ServletRegistrationBean dandelionServlet() {
        ServletRegistrationBean registrationBean = new ServletRegistrationBean();
        registrationBean.setServlet(new DandelionServlet());
        registrationBean.addUrlMappings("/dandelion/*");
        return registrationBean;
    }

    @Bean
    public ServletContextTemplateResolver defaultTemplateResolver() {
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
        resolver.setTemplateMode("HTML5");
        resolver.setPrefix("/WEB-INF/templates/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("UTF-8");
        resolver.setCacheable(false);

        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(resolver);
        engine.addDialect(new DataTablesDialect());

        return resolver;
    }

}

I have made this HTML for testing:

<!doctype html>
<html 
	xmlns:th="http://www.thymeleaf.org" 
	xmlns:ddl="http://github.com/dandelion">
<head>
	<link type="text/css" href="/stylesheets/dataTables.css" media="screen" rel="stylesheet" />
	<script src="/javascripts/vendor/jquery191.js" type="text/javascript"></script>
	<script src="/javascripts/vendor/dataTables.js" type="text/javascript"></script>
</head>
<body>
	<br/>
	<table id="myTableId" ddl:table="true" ddl:url="@{/clientes}">
	   <thead>
	      <tr>
	         <th ddl:property="telefone">Telefone</th>
	         <th ddl:property="nome">Nome</th>
	      </tr>
	   </thead>
	</table>
</body>
</html>

I think Dandelion's servlet is not called. The namespace is not processed. enter image description here


Solution

  • There are several mistakes. Most of them are just same as what I did when i first used dandelion data tables. :)

    I'm writing the full simple examples for each of the code below for anyone's reference in future. So make sure you add only the missing ones to your project

    First add both these dependencies to your maven. (You already have the first. So add the later.)

    <dependency>
        <groupId>com.github.dandelion</groupId>
        <artifactId>datatables-thymeleaf</artifactId>
        <version>0.10.1</version>
    </dependency>
    <dependency>
        <groupId>com.github.dandelion</groupId>
        <artifactId>datatables-spring3</artifactId>
        <version>0.10.1</version>
    </dependency>
    

    Then add these configurations. You have to create Beans for the dialects. I think you missed it..

    @Configuration
    public class DandelionConfig {
    
        @Bean
        public DandelionDialect dandelionDialect() {
            return new DandelionDialect();
        }
    
        @Bean
        public DataTablesDialect dataTablesDialect(){
            return new DataTablesDialect();
        }
    
        @Bean
        public Filter dandelionFilter() {
            return new DandelionFilter();
        }
    
        @Bean
        public ServletRegistrationBean dandelionServletRegistrationBean() {
            return new ServletRegistrationBean(new DandelionServlet(), "/dandelion-assets/*");
        }
    }
    

    And the view can be something like this

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:ddl="http://www.thymeleaf.org/dandelion"
          xmlns:dt="http://www.thymeleaf.org/dandelion/datatables">
    <head lang="en"></head>
    <body>
        <table id="myTableId"
            dt:table="true"
            dt:url="@{/clientes}"
            dt:serverside="true"
            dt:processing="true">
              <thead>
                <tr>
                  <th dt:property="telefone">Telefone</th>
                  <th dt:property="nome">Nome</th>
                </tr>
              </thead>
         </table>
    </body>
    </html>
    

    Here you are using server-side processing. This requires your controller to have a mapping on /clientes which returns DatatablesResponse

    @Override
    @RequestMapping(value = "/clientes")
    @ResponseBody
    public DatatablesResponse<MyObject> data(HttpServletRequest request){
        List<MyObject> myObjectList = ... //logic to fetch a list of objects
    
        DatatablesCriterias criterias = DatatablesCriterias.getFromRequest(request);
        DataSet<MyObject> dataSet = new DataSet<>(myObjectList, (long)myObjectList.size(), (long)myObjectList.size());
        return DatatablesResponse.build(dataSet, criterias);
    }
    

    MyObject is the object you are passing to dandelion data tables

    public class MyObject {
        private String telefone;
        private String nome;
    
        public String getTelefone() {
            return telefone;
        }
    
        public void setTelefone(String telefone) {
            this.telefone = telefone;
        }
    
        public String getNome() {
            return nome;
        }
    
        public void setNome(String nome) {
            this.nome = nome;
        }
    }