I have 2 projects. Project A is a Spring Boot application with a main focus on editing and updating information. Project B has the means to view the information and I'm trying to use this as a dependency for (A) to maximise code reuse and minimise efforts on fixing any bugs/making any improvements multiple times.
I hope to be able to have my controllers and templates correctly find the correct templates dynamically.
Project A is correctly making use of any services/daos etc housed within the Project B dependency but I'm having issues making the front end play nice. In the past I have had one project with no front end of its own use the templates defined in a second project. That was as simple as setting the correct TemplateLoaderPath
on a Freemarker @Bean
in my config. This time around I have a suspicion that once I call upon a template that's local to Project A it will assume any subsequant templates are also to be found on that context path and not look in Project B
It might be easier for me to display the structure of the project somewhat:
src/main/resources/
templates/
feature1/
f1page.ftl
feature2/
f2page.ftl
Maven Dependencies
projectB.jar
templates/
feature3/
f3page.ftl
feature4/
f4page.ftl
I was hoping that when I return new ModelAndView objects for my controllers like
return new ModelAndView("feature3/f3page.ftl");
and
return new ModelAndView("feature1/f1page.ftl");
it would work as both feature folders live within templates/
albiet different locations.
It's worth mentioning that there is a lot of template importing going on so finding the right templates will need to work here too. So if f1page.ftl
(in src/main/resources) has the following line:
<#import "feature3/f3page.ftl" as f3>
this would need to be found in the other location (within the dependency .jar).
Below is a sample of the current freemarker stack trace from this example. It seems to find f1page.ftl
upon returning: new ModelAndView("feature1/f1page.ftl");
but fails to find feature3/f3page.ftl
which is an import on line 2.
Template importing failed (for parameter value "/feature3/f3page.ftl"): Template not found for name "/feature3/f3page.ftl". The name was interpreted by this TemplateLoader: MultiTemplateLoader(loader1 = FileTemplateLoader(baseDir="C:\Users\Becxxxa\Projects\ProjectA\target\classes\templates", canonicalBasePath="C:\Users\Becxxxa\Projects\ProjectA\target\classes\templates\"), loader2 = ClassTemplateLoader(resourceLoaderClass=org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer, basePackagePath="" /* relatively to resourceLoaderClass pkg */)). ---- FTL stack trace ("~" means nesting-related): - Failed at: #import "/feature3/f3page.ftl" as f3 [in template "feature1/f1page.ftl" at line 2, column 1]
Here is my @Bean
as you can see I have applied setPreferFileSystemAccess
to false
(as it has been suggested here) but to no avail.
@Bean
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() {
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
bean.setTemplateLoaderPath("classpath:/templates/");
bean.setPreferFileSystemAccess(false);
return bean;
}
It's possible that I'm asking too much of Freemarker and that this is actually impossible. But if not I am in need of aid in correctly configuring my project/freemarker to work dynamically with both sources of templates. I feel I'm probably missing something obvious regarding template loading.
Thanks to @Taylor O'Connor although it's not the solution I thought I was looking for its a simple solution to what appears to be a complex problem.
I ended up using the maven-dependency-plugin
to unpack the templates I require from the dependency into the parent projects `src/main/resources/templates' folder. This meets my requirement of not having to maintain multiple sources of the same code.
This is the plugin I added to my pom:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>uk.co.company</groupId>
<artifactId>projectA</artifactId>
<outputDirectory>src/main/resources/</outputDirectory>
<includes>templates/feature3/**</includes>
<excludes>*/feature4/*</excludes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
This puts the folder of feature3
into my templates
folder. I had to exclude feature4
as it matched the name of a folder already in my templates folder and for me this was for the best as the templates have had to differ slightly as this contains my 'layout.ftl' which does differ slightly between the applications.