How do I access style sheets in a library JAR file from a Thymeleaf template?

Viewed 919

I have a set of Spring-based, Java web applications and a common framework library made available to them all via a JAR file. I'm using Thymeleaf for the views.

I have a common Thymeleaf template that is used by several of the web applications. The template HTML file and its associated style sheet are both in the library JAR file. When a web application displays a view based on the framework template, the template is found and processed by Thymeleaf.

My problem is that I cannot figure out how to import the style sheet such that it is loaded and passed back to the browser. The end result is un-styled (albeit correct) HTML.

I'm using Gradle as my build tool.

Here's my relevant project structure for the framework:

common-framework/src/main
    ../java                        - contains the framework code
    ../resources                   - contains the framework resources
       ../static
           ../css
               example.css         - Style sheet for use in templates
       ../templates
           ../fwk
               example.html        - Thymeleaf template

Here's my relevant project structure for an example app:

app/src/main
    ../java                        - contains the application code
    ../resources                   - contains the application resources
       ../templates
           ../app
               start.html          - Thymeleaf template
    ../webapp
        ../resources
            ../css
               app.css             - Style sheet for use in the app

Here's the ViewResolver bean that is used by both the app and the framework for locating templates:

@Bean
public ViewResolver viewResolver()
{
    ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
    templateResolver.setTemplateMode("HTML5");
    templateResolver.setPrefix("templates/");
    templateResolver.setSuffix(".html");
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(1);

    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setTemplateResolver(templateResolver);

    ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
    viewResolver.setTemplateEngine(engine);
    viewResolver.setCharacterEncoding("UTF-8");
    viewResolver.setOrder(1);

    return viewResolver;
}

Here's my resource handler configuration (from my WebMvcConfigurerAdapter):

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
    registry.addResourceHandler("/resources/**")
            .addResourceLocations("/resources/");
}

Here's the framework Thymeleaf template (fwk/example.html)

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="utf-8" />
    <title th:text="${title}"></title>
    <link rel="stylesheet" type="text/css" th:href="@{/resources/static/css/framework.css}" />   <!-- *** PROBLEM IS HERE *** -->
</head>
<body>
    ...
</body>
</html>

Here's an application Thymeleaf template (app/start.html)

<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="utf-8" />
    <title th:text="${title}"></title>
    <link rel="stylesheet" type="text/css" th:href="@{/resources/css/app.css}" />   <!-- *** This works correctly. *** -->
</head>
<body>
    ...
</body>
</html>

Here's a sample controller from a web application. Note: this a separate project that depends on the framework library.

@Controller
public class ExampleController
{
    @GetMapping(path = "/start")
    public String start(Model model, HttpServletRequest request)
    {
        ...
        return "app/start"; // Uses an application template
    }

    @GetMapping(path = "/example")
    public String example(Model model)
    {
        ...
        return "fwk/example"; // Uses a framework template
    }
}

The web application runs under Tomcat and the framework library JAR file is available to it. When I test the controller URLs, both are loaded correctly. That is, in both cases, the template is found, loaded and displayed.

However, as I noted above, the framework template (triggered by the /example URL) is un-styled as its framework CSS file is not found and passed on to the browser. How do I achieve this?

(Is my framework structure okay? Is my ViewResolver configured correctly? Is my resource handling configured correctly? What href path should I use in the framework template to refer to a stylesheet in the same JAR?)

1 Answers

In example.html try replacing:

<link rel="stylesheet" type="text/css" th:href="@{/resources/static/css/framework.css}" />

By:

 <link rel="stylesheet" type="text/css" th:href="@{/css/framework.css}"/>
Related