2

I'm working on ratpack.io web app and using gradle as the build tool. Templates are rendered from template files in a src/main/thymeleaf directory, which works fine at runtime (just using gradle run).

$ ls ./src/main/thymeleaf
home.html

I'm running into issues when I'm creating the uber jar, where the template files aren't included. When I crack open the output jar file I see the thymeleaf directory is empty.

I know part of the shadow-jar process is merging all the dependencies into one jar, but I'm not sure what I need to do include the template files as well. I tried creating special rules to include the html files, but I ended up getting just html files in the jar and not even the ones from the thymeleaf directory.

  • what do I need to configure to get the template files included in this uber jar?
  • if I actually get the files included in the jar's template dir, do I need to update the template resolver to pull the files from the jar vs the current working directory?
Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
voodoogiant
  • 2,118
  • 6
  • 29
  • 49
  • I just tried using the groovy templates and got the same result, where they're not automatically included in the uber jar. I must be doing something really naive as I can't be the only person that would want to use templates in both the CLI build and the uberjar. – voodoogiant Jun 24 '18 at 05:14

1 Answers1

2

Is there any reason you keep your template files in src/main/thymeleaf? By default Thymeleaf templates should be stored in src/ratpack/thymeleaf directory.

ThymeleafModule class defines a folder name where all templates are stored. The default value is thymeleaf and when you create a shadowJar then you should find a folder thymeleaf right in the JAR archive. shadowJar copies src/ratpack/thymeleaf to this destination without any problem.

Java based Ratpack project is not aware of src/ratpack by default, but you can easily configure it by creating an empty file called .ratpack in src/ratpack and configuring server -> server.findBaseDir() (more detailed example below).

Here is a simple example:

build.gradle

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.ratpack:ratpack-gradle:1.5.4"
        classpath "com.github.jengelman.gradle.plugins:shadow:1.2.4"
    }
}

apply plugin: "io.ratpack.ratpack-java"
apply plugin: "com.github.johnrengelman.shadow"
apply plugin: "idea"
apply plugin: "eclipse"

mainClassName = 'app.RatpackApp'

repositories {
    jcenter()
}

dependencies {
    // Default SLF4J binding.  Note that this is a blocking implementation.
    // See here for a non blocking appender http://logging.apache.org/log4j/2.x/manual/async.html
    runtime 'org.slf4j:slf4j-simple:1.7.25'

    compile ratpack.dependency('thymeleaf')
    compile ratpack.dependency('guice')

    testCompile "org.spockframework:spock-core:1.0-groovy-2.4"
}

src/main/java/app/RatpackApp.java

package app;

import ratpack.guice.Guice;
import ratpack.server.BaseDir;
import ratpack.server.RatpackServer;
import ratpack.thymeleaf.ThymeleafModule;

import java.util.HashMap;

import static ratpack.thymeleaf.Template.thymeleafTemplate;

public final class RatpackApp {

    public static void main(String[] args) throws Exception {

        RatpackServer.start(server ->
                server.serverConfig(config -> config.findBaseDir())
                        .registry(Guice.registry(bindings -> bindings.module(ThymeleafModule.class)))
                        .handlers(chain -> chain.get(ctx -> ctx.render(thymeleafTemplate(new HashMap<String, Object>() {{
                            put("title", "Hello, Ratpack!");
                            put("header", "Hello, Ratpack!");
                            put("text", "This template got rendered using Thymeleaf");
                        }}, "home"))))
        );
    }
}

src/ratpack/thymeleaf/home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <title th:text="${title}" />
</head>
<body>
    <h1 th:text="${header}"></h1>
    <p th:text="${text}" />
</body>
</html>

Remember to create an empty file .ratpack in src/ratpack so Ratpack can discover this location as a files base dir.

Now after creating a final JAR with gradle shadowJar I can see the template file being copied correctly:

ratpack-thymeleaf-example [master●●] % unzip -l build/libs/ratpack-thymeleaf-example-all.jar | grep home
      232  06-24-2018 10:12   thymeleaf/home.html

Here you can find the full example - https://github.com/wololock/ratpack-thymeleaf-example

Szymon Stepniak
  • 40,216
  • 10
  • 104
  • 131
  • I have them in "src/main/thymeleaf" because that's where an example I saw (https://github.com/pac4j/ratpack-pac4j-demo/blob/master/src/main/java/org/pac4j/demo/ratpack/RatpackPac4jDemo.java) put them. I assumed that was correct because the template resolver was finding them correctly. I'm new to ratpack and I needed to set the base dir, so I set it to "src/main" to match the example. All the other examples online including yours are groovy examples where the base dir is not specified, so I don't know what I should set it to. – voodoogiant Jun 24 '18 at 15:10
  • Thanks @voodoogiant for pointing ratpack-java out. I have updated the examples to cover ratpack-java instead of ratpack-groovy. Github sample app updated as well. – Szymon Stepniak Jun 24 '18 at 16:21