I get a file not found exception while loading a freemarker template even though the template is actually present in the path.
Update: This is running as a webservi
this work like a Charm ,
package tech.service.common;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Service
public class MailingService {
@Autowired
private JavaMailSender sender;
public MailResponseDto sendEmail(String mailTo,String Subject) {
MailResponseDto response = new MailResponseDto();
MimeMessage message = sender.createMimeMessage();
Configuration config = new Configuration(new Version(2, 3, 0));
try {
// set mediaType
MimeMessageHelper helper = new MimeMessageHelper(message, MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
TemplateLoader templateLoader = new FileTemplateLoader(new File("src/main/resources/template"));
config.setTemplateLoader(templateLoader);
// add attachment
helper.addAttachment("logo.png", new File("src/main/resources/static/images/spring.png"));
Template t = config.getTemplate("email_template_password.ftl");
Map<String, Object> model = new HashMap<>();
model.put("Name", "ELAMMARI Soufiane");
model.put("location", "Casablanca,Morocco");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(t, model);
helper.setTo("example@gmail.com");
helper.setText(html, true);
helper.setSubject(Subject);
sender.send(message);
response.setMessage("mail send to : " + mailTo);
response.setStatus(Boolean.TRUE);
} catch (MessagingException | IOException | TemplateException e) {
response.setMessage("Mail Sending failure : "+e.getMessage());
response.setStatus(Boolean.FALSE);
}
return response;
}
}
FreeMarker template paths are resolved by a TemplateLoader
object, which you should specify in the Configuration
object. The path that you specify as the template path is interpreted by the TemplateLoader
, and is usually relative to some kind of base directory (even if it starts with /
), that's also called the template root directory for this reason. In your example, you haven't specified any TemplateLoader
, so you are using the default TemplateLoader
, which is only there for backward-compatibility, and is nearly useless (and also dangerous). So, do something like this:
config.setDirectoryForTemplateLoading(new File(
"C:/Users/Jay/workspace/WebService/templates"));
and then:
config.getTemplate("fibplain.xml");
Note that the /template
prefix is not there now, as the template path is relative to C:/Users/Jay/workspace/WebService/templates
. (This also means that the template can't back out of it with ../
-s, which can be important for security.)
Instead of loading from a real directory, you can also load templates from a SerlvetContext
, from the "class path", etc. It all depends on what TemplateLoader
you are choosing.
See also: http://freemarker.org/docs/pgui_config_templateloading.html
Update: If you get FileNotFoundException
instead of TemplateNotFoundException
, it's time to upgrade FreeMarker to at least 2.3.22. It also gives better error messages, like if you do the typical mistake of using the default TemplateLoader
, it tells you that right in the error message. Less wasted developer time.
You can solve this problem like that.
public class HelloWorldFreeMarkerStyle {
public static void main(String[] args) {
Configuration configuration = new Configuration();
configuration.setClassForTemplateLoading(HelloWorldFreeMarkerStyle.class, "/");
FileTemplateLoader templateLoader = new FileTemplateLoader(new File("resources"));
configuration.setTemplateLoader(templateLoader);
Template helloTemp= configuration.getTemplate("hello.ftl");
StringWriter writer = new StringWriter();
Map<String,Object> helloMap = new HashMap<String,Object>();
helloMap.put("name","gokhan");
helloTemp.process(helloMap,writer);
System.out.println(writer);
}
}
The Java VM is not able to find you file /templates/fibplain.xml
in the specified location. This is an absolute path
and it is highly likely that you are confused with relative path
. To get this corrected use the complete (i.e absolute) path properly like /home/jaykumar/templates/fibplan.xml($TEMPLATE_HOME/fibplan.xml)
. Other possibility would be, if you do have such location as /templates/, you might not have placed fibplain.xml in the location. To me only these two are the most plausible reasons. I assumed it is one of the linux distribution because of the separator is /
Actually you're expected to specify absolute path (not relative) for dir where template is going to be place, see FreeMaker.Configuration:
setDirectoryForTemplateLoading(java.io.File dir)
Sets the file system directory from which to load templates.
Note that FreeMarker can load templates from non-file-system sources too. See setTemplateLoader(TemplateLoader) from more details.
For instance, this is how to get template from src/test/resources/freemarker:
private String final PATH = "src/test/resources/freemarker"
// getting singleton of Configuration
configuration.setDirectoryForTemplateLoading(new File(PATH))
// surrounded by try/catch