I am reading the Thymeleaf + Spring 3 Tutorial and also trying to build a modular application. My goal is to be able to load thymeleaf templates from Jars in the classpath.
For this I have configured a SpringTemplateEngine in the next xml:
<bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
<property name="templateResolvers">
<util:set>
<ref bean="servletContextTemplateResolver" />
<ref bean="classpathPluginTemplateResolver" />
</util:set>
</property>
</bean>
<bean id="classpathPluginTemplateResolver"
class="org.mael.codex.arcana.web.thymeleaf.templates.ClasspathPluginTemplateResolver">
<property name="prefix" value="/META-INF/codexarcana/plugin/views" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
</bean>
And the ClasspathPluginTemplateResolver code:
public class ClasspathPluginTemplateResolver extends TemplateResolver {
public ClasspathPluginTemplateResolver() {
super();
super.setResourceResolver(new ClasspathTemplateResolver());
}
@Override
public void setResourceResolver(IResourceResolver resourceResolver) {
throw new ConfigurationException("Cannot set a resource resolver on "
+ this.getClass().getName() + ". If "
+ "you want to set your own resource resolver, use "
+ TemplateResolver.class.getName() + "instead");
}
}
And the ClasspathTemplateResolver:
public class ClasspathTemplateResolver implements IResourceResolver {
@Override
public String getName() {
return this.getClass().getSimpleName();
}
@Override
public InputStream getResourceAsStream(
TemplateProcessingParameters templateProcessingParameters,
String resourceName) {
if (resourceName == null || resourceName.isEmpty()) {
throw new IllegalArgumentException("Resource name cannot be null");
}
try {
return new ClassPathResource(resourceName).getInputStream();
} catch (IOException e) {
throw new RuntimeException("Cannot open resource '" + resourceName
+ "'", e);
}
}
}
How can I avoid name conflicts in the templates resolved by the ClasspathPluginTemplateResolver?
Example:
Let’s suppose I have 2 plugins with this directory structure:
codexarcana-poll-plugin.jar
----/META-INF/codexarcana/plugin/views/wizard.html
and
codexarcana-gravatar-plugin.jar
----/META-INF/codexarcana/plugin/views/wizard.html
In this case I believe that the ClasspathTemplateResolver will return a wrong view or will have conflicts resolving such thing.
Implementations of the
ITemplateResolverinterface that extend the baseorg.thymeleaf.templateresolver.AbstractTemplateResolverclass (like all out-of-the-box implementations do) have aresolvablePatternsproperty that allows you to specify a series of patterns that will be applied for determining which views will be considered resolvable by that specific template engine. This should help you avoid collisions.There you can specify wildcarded patterns like
admin/*,user/*/create, etc.Have in mind that these patterns apply on the view name, and not on the template file name itself. For example, if your template is
/WEB-INF/templates/index.htmland your view resolver adds prefix/WEB-INF/templates/and suffix.html, your view name isindex, and so a resolvable pattern like*.htmlwould never match.Also, there is an
orderproperty that establishes the order in which template resolvers will be asked to resolve a view.Disclaimer, as required by StackOverflow rules: I’m the author of Thymeleaf.