FileNotFoundException при загрузке шаблона freemarker в java

Я получаю исключение, не найденное в файле, при загрузке шаблона freemarker, даже если шаблон действительно присутствует в пути.

Обновление: это работает как веб-сервис. Он вернет xml клиенту на основе поискового запроса. Шаблон загружается успешно, когда я вызываю его из другой java-программы (из статического основного). Но когда клиент запрашивает xml, возникает FileNotFoundException.

ОС: Windows 7 Абсолютный путь файла: C:/Users/Jay/workspace/WebService/templates/

Вот мой код:

private String templatizeQuestion(QuestionResponse qr) throws Exception
{
    SimpleHash context = new SimpleHash();
    Configuration config = new Configuration();

    StringWriter out = new StringWriter();

    Template _template = null;

    if(condition1)
    {           
        _template = config.getTemplate("/templates/fibplain.xml");
    } 
    else if(condition2)
    {
        _template = config.getTemplate("/templates/mcq.xml");
    }
    context.put("questionResponse", qr);
    _template.process(context, out);

    return out.toString();
 }

Полный стек ошибок:

 java.io.FileNotFoundException: Template /templates/fibplain.xml not found.
at freemarker.template.Configuration.getTemplate(Configuration.java:495)
at freemarker.template.Configuration.getTemplate(Configuration.java:458)
at com.hm.newAge.services.Curriculum.templatizeQuestion(Curriculum.java:251)
at com.hm.newAge.services.Curriculum.processQuestion(Curriculum.java:228)
at com.hm.newAge.services.Curriculum.processQuestionList(Curriculum.java:210)
at com.hm.newAge.services.Curriculum.getTest(Curriculum.java:122)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.axis2.rpc.receivers.RPCUtil.invokeServiceClass(RPCUtil.java:212)
at org.apache.axis2.rpc.receivers.RPCMessageReceiver.invokeBusinessLogic(RPCMessageReceiver.java:117)
at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:114)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:181)
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:172)
at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:146)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)

Ответ 1

Пути шаблонов FreeMarker разрешаются объектом TemplateLoader, который вы должны указать в объекте Configuration. Путь, который вы указываете как путь к шаблону, интерпретируется TemplateLoader и обычно относится к некоторому базовому каталогу (даже если он начинается с /), который по этой причине также называется корневым каталогом шаблонов. В вашем примере вы не указали TemplateLoader, так что вы используете по умолчанию TemplateLoader, который существует только для обратной совместимости и почти бесполезен (а также опасен). Итак, сделайте что-нибудь вроде этого:

config.setDirectoryForTemplateLoading(new File(
    "C:/Users/Jay/workspace/WebService/templates"));

а затем:

config.getTemplate("fibplain.xml");

Обратите внимание, что префикс /template теперь отсутствует, поскольку путь к шаблону относительно C:/Users/Jay/workspace/WebService/templates. (Это также означает, что шаблон не может вернуться из него с помощью ../ -s, что может быть важно для безопасности.)

Вместо загрузки из реального каталога вы также можете загружать шаблоны из SerlvetContext, из "пути к классу" и т.д. Все зависит от того, какой TemplateLoader вы выбираете.

Смотрите также: http://freemarker.org/docs/pgui_config_templateloading.html

Обновление: если вы получаете FileNotFoundException вместо TemplateNotFoundException, время обновления FreeMarker должно быть не менее 2.3.22. Он также дает лучшие сообщения об ошибках, например, если вы делаете типичную ошибку при использовании значения по умолчанию TemplateLoader, он сообщает об этом прямо в сообщении об ошибке. Меньше потрачено впустую время разработки.

Ответ 2

Вы можете решить эту проблему таким образом.

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);


    }   
}

Ответ 3

Java VM не может найти файл /templates/fibplain.xml в указанном месте. Это an absolute path, и весьма вероятно, что вас путают с relative path. Чтобы получить это исправление, используйте полный (то есть абсолютный) путь, как /home/jaykumar/templates/fibplan.xml($TEMPLATE_HOME/fibplan.xml). Другая возможность была бы, если у вас есть такое местоположение как /templates/, возможно, вы не разместили fibplain.xml в этом месте. Для меня только эти два являются наиболее правдоподобными причинами. Я предположил, что это одно из дистрибутивов linux из-за разделителя /

Ответ 4

эта работа как Шарм,

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 tech.alphalupi.rhcore.dto.MailResponseDto;
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("[email protected]");
            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;
    }
}

Ответ 5

На самом деле вы должны указать абсолютный путь (не относительный) для каталога, в который будет помещен шаблон, см. FreeMaker.Конфигурация:

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.

Например, вот как получить шаблон из test/resources/freemaker:

private String final PATH = "src/test/resources/freemaker"
//getting singleton of Configuration
configuration.setDirectoryForTemplateLoading(new File(PATH)) //surrounded by try/catch