【问题标题】:Apache FOP: upgrading from 1.1 to 2.1Apache FOP:从 1.1 升级到 2.1
【发布时间】:2016-11-15 12:53:38
【问题描述】:

我正在关注migration guide,但我似乎没听对。

在 FOP 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);
    }
}

我修改了上面的代码以坚持使用 FOP 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 无法加载,因为创建失败。

编辑:

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

【问题讨论】:

  • 从文档中看是正确的。当我们从 1.0 升级到 2.1 时,似乎我们进行了配置更改。它可能是您的 URI 或解析器。您正在生成的 URI 的具体示例是什么?
  • 生成的baseUri是“servlet-context:///”。我正在使用 Spring 应用程序,无法提供绝对文件系统路径作为 baseUri。

标签: upgrade apache-fop


【解决方案1】:

经过几天的调查,终于成功完成了迁移。问题来自 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()

此外,我们必须删除字体 URI(在 fop-config.xml 中)和图像 URI(在任何 XSL 转换文件或模板中)中的所有“servlet-context:”标记。

最后,我遇到了连字符问题:FOP 无法再找到 .hyp 文件,因为出于某种原因,正在使用 baseUri 而不是自定义上下文解析器(我不得不深入研究 FOP 的源文件以找出)。所以,我不得不修改我的自定义解析器的getResource 方法。我知道这是一个 hack,但它有效,对我来说已经足够了,因为我已经花了三天时间解决这个问题):

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 文件,因为它在OFFO 提供的.hyp 文件中不存在。我刚刚复制了en.hyp 并将其重命名为none.hyp。这解决了我的最后一个问题。

我希望这可以为某人节省几天的工作时间;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 2012-03-18
    • 2012-10-28
    相关资源
    最近更新 更多