2016-11-15 7 views
0

Я следую за migration guide, но, похоже, я не понимаю.Apache FOP: обновление с 1.1 до 2.1

В ФОП 1.1 У меня есть этот рабочий код:

public class XsltFactory { 
    private static final String FO_CONFIG_FILE = "/path/to/fop-config.xml"; 

    private static FopFactory fopFactory; 

    private static synchronized void initFopFactory(final ServletContext context) throws Exception { 
     Configuration cfg = new DefaultConfigurationBuilder().build(XsltFactory.class.getResourceAsStream(FO_CONFIG_FILE)); 
     fopFactory = FopFactory.newInstance(); 
     fopFactory.setURIResolver(new ServletContextURIResolver(context)); 
     fopFactory.setUserConfig(cfg); 
    } 
} 

Я приспособил код выше, чтобы придерживаться ФОП 2.1:

public class XsltFactory { 
    private static final String FO_CONFIG_FILE = "/path/to/fop-config.xml"; 

    private static FopFactory fopFactory; 

    private static synchronized void initFopFactory(final ServletContext context) throws Exception { 
     Configuration cfg = new DefaultConfigurationBuilder().build(XsltFactory.class.getResourceAsStream(FO_CONFIG_FILE)); 

     FopFactoryBuilder fopFactoryBuilder = new FopFactoryBuilder(
      new URI(ServletContextURIResolver.SERVLET_CONTEXT_PROTOCOL), 
      new URIResolverAdapter(new ServletContextURIResolver(context)) 
     ); 

     fopFactoryBuilder.setConfiguration(cfg); 
     fopFactory = fopFactoryBuilder.build(); 
    } 
} 

Но я получаю следующее сообщение об ошибке:

java.lang.Exception: Fail to create PDF 
    at ....web.controller.PrintPdfController.renderPdf(PrintPdfController.java:181) 
    [...] 
    at weblogic.work.ExecuteThread.run(ExecuteThread.java:263) 
Caused by: java.net.URISyntaxException: Expected scheme-specific part at index 16: servlet-context: 
    at java.net.URI$Parser.fail(URI.java:2829) 
    at java.net.URI$Parser.failExpecting(URI.java:2835) 
    at java.net.URI$Parser.parse(URI.java:3038) 
    at java.net.URI.<init>(URI.java:595) 
    [...] 
    ... 42 common frames omitted 

PDF не загружается, поскольку он не удалось создать.

EDIT:

После добавления + "///" после SERVLET_CONTEXT_PROTOCOL контекста, теперь я получаю:

Caused by: java.net.MalformedURLException: unknown protocol: servlet-context 
    at java.net.URL.<init>(URL.java:592) 
    at java.net.URL.<init>(URL.java:482) 
    at java.net.URL.<init>(URL.java:431) 
    at java.net.URI.toURL(URI.java:1096) 
    at org.apache.fop.fonts.FontDetectorFactory$DefaultFontDetector.detect(FontDetectorFactory.java:94) 
    ... 59 common frames omitted 
+0

Он выглядит правильно из документации. Похоже, что у нас были изменения конфигурации, когда мы перешли от 1.0 к 2.1. Это может быть ваш URI или resolver. Какой конкретный пример URI, который вы генерируете? –

+0

Созданный baseUri - это «servlet-context: ///». Я работаю с весенним приложением и не могу обеспечить абсолютные пути файловой системы как baseUri. –

ответ

0

После нескольких дней расследования, миграция, наконец, было сделано успешно. Проблема исходила от решения URI, и устранение этой проблемы создавало новые проблемы, которые я решил впоследствии.

Руководство по эксплуатации https://xmlgraphics.apache.org/fop/2.1/upgrading.html имеет относительно ограниченную помощь.

Ядро проблемы - это распознаватель URI. Теперь вы должны определить пользовательский распознаватель, но не как в примере, приведенном на сайте: https://xmlgraphics.apache.org/fop/2.0/servlets.html

ResourceResolver resolver = new ResourceResolver() { 
public OutputStream getOutputStream(URI uri) throws IOException { 
    URL url = getServletContext().getResource(uri.toASCIIString()); 
    return url.openConnection().getOutputStream(); 
} 

public Resource getResource(URI uri) throws IOException { 
    return new Resource(getServletContext().getResourceAsStream(uri.toASCIIString())); 
} 
}; 

Правильный способ сделать это:

ResourceResolver resolver = new ResourceResolver() { 
public OutputStream getOutputStream(URI uri) throws IOException { 
    URL url = context.getResource(uri.getPath()); 
    return url.openConnection().getOutputStream(); 
} 
public Resource getResource(URI uri) throws IOException { 
    return new Resource(context.getResourceAsStream(uri.getPath())); 
} 
}; 

Вместо uri.toASCIIString(), правильный синтаксис uri.getPath().

Кроме того, нам пришлось удалить все разметки «servlet-context:» в URI шрифтов (в fop-config.xml) и URI изображений (в любом файле или шаблоне преобразования XSL).

Наконец-то у меня возникла проблема с переносом: FOP больше не смог найти файлы .hyp, потому что по какой-то причине вместо настраиваемого контекстного распознавателя использовался baseUri (мне приходилось искать исходные файлы FOP, чтобы узнать) , Итак, мне пришлось изменить метод getResource моего настраиваемого распознавателя. Я знаю, что это хак, но это работает, и это достаточно для меня, как я уже провел три дня по этой проблеме):

public OutputStream getOutputStream(URI uri) throws IOException { 
    URL url = context.getResource(uri.getPath()); 
    return url.openConnection().getOutputStream(); 
} 
public Resource getResource(URI uri) throws IOException { 
    InputStream stream = null; 
    /* 
    * For some reason, in FOP 2.x, the hyphenator does not use the 
    * classpath fop-hyph.jar. 
    * 
    * This causes trouble as FOP tries to find "none.hyp" in the 
    * war directory. Setting 
    * <hyphenation-base>/WEB-INF/hyph</hyphenation-base> in the 
    * fop-config.xml file does not solve the issue. The only 
    * solution I could find is to programmatically detect when a 
    * .hyp file is trying to be loaded. When this occurs, I modify 
    * the path so that the resolver gets the right resource. 
    * 
    * This is a hack, but after spending three days on it, I just 
    * went straight to the point and got a workaround. 
    */ 
    if (uri.getPath().endsWith('.hyp')) { 
    String relUri = uri.getPath().substring(uri.getPath().indexOf(baseUri.getPath()) + baseUri.getPath().length()); 
    stream = context.getResourceAsStream(FopManager.HYPH_DIR + relUri); 
    } else { 
    stream = context.getResourceAsStream(uri.getPath()); 
    } 
    Resource res = new Resource(stream); 
    return res; 
} 
}; 

Обратите внимание, что я должен был создать файл none.hyp вручную, так как он не существуют в файлах .hyp, предоставленных OFFO. Я только что скопировал en.hyp и переименовал его none.hyp. Это решило мою последнюю проблему.

Надеюсь, это сэкономит кому-то несколько дней работы;)

Смежные вопросы