Environment:
- AS: Wildfly-16.0.0.Final
- JVM: jdk-11.0.2
We are implementing a Bean to be used as a freemarker Template provider. The Bean *.java file is contained in the source folder of the application-services-ejb JAR module, which is packaged in the application-services-ear EAR module.
The Bean constructor initializes a freemarker.template.Configuration object. Afterwards, the class which uses the Bean can invoke a Bean.getCredentialCreationTemplate() method, which obtains the desired Template from the Configuration object.
The Configuration object requires the directory containing all the *.ftl files to be passed to the Configuration.setDirectoryForTemplateLoading(File) method.
The FTL template directory is retrieved with the usual getResources() approach:
String emailTemplateFolderPath = getClass().getClassLoader().getResource("emails").getFile();
File emailTemplateFolder = new File(emailTemplateFolderPath);
Here comes the quirk: the emailTemplateFolderPath contains a wrong path: C:\Users\myusername\Desktop\content\application-services-ear-VERSION.ear\org.company-application-services-ejb-VERSION.jar\emails
The wrong part is the one stressed in bold. Indeed, the part in italic matches both the expected and the actual path within the EAR (I inspected the archive manually). Instead, I have no idea of where the bold part comes from. The directory C:\Users\myusername\Desktop\content does not even exist on my workstation, neither it resembles the actual EAR location, which is in a completely different path in my filesystem.
The only connection with my Desktop is that my Wildfly startup script and my application redeploy script are located in C:\Users\myusername\Desktop.
Why is the classloader failing in correctly locating the EAR? How can I fix?
Here is my code:
@Stateless
public class FTLTemplateProviderImpl implements FTLTemplateProvider {
public enum FTLTemplate {
CREDENTIAL_CREATION("credential-creation.ftl");
private final String fileName;
private FTLTemplate(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return this.fileName;
}
}
private Configuration cfg = null;
public FTLTemplateProviderImpl() {
try {
cfg = new Configuration(Configuration.VERSION_2_3_28);
String emailTemplateFolderPath = getClass().getClassLoader().getResource("emails").getFile();
File emailTemplateFolder = new File(emailTemplateFolderPath);
cfg.setDirectoryForTemplateLoading(emailTemplateFolder); // <-- HERE IT BREAKS!
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setLogTemplateExceptions(false);
cfg.setWrapUncheckedExceptions(true);
cfg.setTemplateLoader(new FileTemplateLoader(emailTemplateFolder));
} catch (IOException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
@PermitAll
@Override
public Template getCredentialCreationTemplate() {
try {
return cfg.getTemplate(FTLTemplate.CREDENTIAL_CREATION.getFileName());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
Please take into account that we also tried to turn the @Stateless bean into a @Singleton, making all the necessary adjustment to make it loadable and injectable into the client bean. Although this, the content of emailTemplateFolderPath is exactly the same.