Vishwas Upadhyay
Vishwas Upadhyay

Reputation: 322

Thymeleaf template is not able to find related JS, CSS and i18n files

I am working on spring boot 2 + thymeleaf web application. I want to render a template and it's static resources from a jar file. I am getting a 404 error for js, CSS, and message.properties file whereas template is rendering on the browser but related js, css not. To render a template from the jar file, I have configured ClassLoaderTemplateResolver as mentioned below :

  @Bean
public ClassLoaderTemplateResolver secondaryTemplateResolver() throws IOException {
    
    ClassLoaderTemplateResolver secondaryTemplateResolver = new 
     ClassLoaderTemplateResolver(getCustomeClassLoader());
    secondaryTemplateResolver.setPrefix("mytemplates/");
    secondaryTemplateResolver.setSuffix(".html");
    secondaryTemplateResolver.setTemplateMode(TemplateMode.HTML);
    secondaryTemplateResolver.setCharacterEncoding("UTF-8");
    secondaryTemplateResolver.setOrder(2);
    secondaryTemplateResolver.setCheckExistence(true);
    
    return secondaryTemplateResolver;
}

Where getCustomClassloader() will return the URLclassloader instance which loads my test.jar file (current class' classloader is passed as parent classloader). This jar file has all my templates (html file) + static files (JS,CSS,Properties). Below is the structure of jar file:

test.jar
 |
 |- mytemplates -> myhtml.html
 |- static
      |- js ->my.js
      |- css ->my.js
 |- i18N -> message.properties

It looks like spring boot or thymeleaf is not able to find resources from the Classloader/jar file where it can find the template. Could you please help me to fix this problem? How I can tell spring boot + thymeleaf to look into a specific classloader to find static resouces?

I have already tried setting up ClassLoaderTemplateResource but it invain.

@Bean
public ClassLoaderTemplateResource secondaryResouceResolver() throws IOException
{
    ClassLoaderTemplateResource secondaryResoucreResolver = new ClassLoaderTemplateResource(getCustomeClassLoader(),
        "static/", "UTF-8");

    return secondaryResoucreResolver;
}

Thanks in advance for your help!

Upvotes: 0

Views: 633

Answers (2)

riddle_me_this
riddle_me_this

Reputation: 9155

If I understand your requirements correctly, you shouldn’t need to write this code. Just go to start.spring.io and have the tool create your build file (maven or gradle) and select the JAR type. Drop your files in the associated folders created by the tool. Then launch it from your IDE.

Upvotes: 0

Vishwas Upadhyay
Vishwas Upadhyay

Reputation: 322

I wasn't able to find any mechanism where I can use a jar file or classloader to point external static resources. Therefore, in order to point static resource (Js/css) and message files from jar files which are not in the classpath you need override some spring boot default configurations. First, you need to extract the jar file in some folder and then you need to override addResourceHandlers() method of WebMvcConfigurer interface like below :

 @Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
    registry
      .addResourceHandler("js/**") /*This must be relative request url for js*/
      .addResourceLocations("file:/C:/MyStuff/jarfolder/js/")
      .setCachePeriod(3600)
      .resourceChain(true)
      .addResolver(new PathResourceResolver());
    
    registry
    .addResourceHandler("css/**")/*This must be relative request url for css*/
    .addResourceLocations("file:/C:/MyStuff/jarfolder/css/")
    .setCachePeriod(3600)
    .resourceChain(true)
    .addResolver(new PathResourceResolver());
}

In order to refer message source from jar file, not in the classpath. you need to extract it and then provide it's path as given below :

 @Bean
public MessageSource messageSource() throws IOException
{
    ReloadableResourceBundleMessageSource messageSource = 
        new ReloadableResourceBundleMessageSource();
   
    
    messageSource.setDefaultEncoding("UTF-8");
    messageSource.setUseCodeAsDefaultMessage(true);
    messageSource.addBasenames("classpath:i18n/messages");
  messageSource.addBasenames("file:/C:/MyStuff/jarfolder/messages");
    return messageSource;
}

This will serve the purpose to get static resources and message sources from external sources. If anyone knows a better solution so please leave your comment here.

Upvotes: 0

Related Questions