2016-11-15 151 views
0

我在關注migration guide,但我似乎沒有把握。Apache FOP:從1.1升級到2.1

在FOP 1.1我有這樣的工作代碼:

​​

我適應上面的代碼堅持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 
+0

它看起來正確的文件。似乎我們在從1.0變爲2.1時有配置更改。它可能是你的URI或解析器。什麼是您正在生成的URI的特定示例? –

+0

生成的baseUri是「servlet-context:///」。我正在使用Spring應用程序,無法提供絕對文件系統路徑作爲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()。另外,我們不得不刪除字體URI(在fop-config.xml中)和圖像URI(在任何XSL轉換文件或模板中)中的所有「servlet-context:」標記。

最後,我遇到了連字符問題:FOP找不到.hyp文件,因爲某些原因,使用baseUri而不是自定義上下文解析器(我不得不深入FOP的源文件中找出) 。所以,我不得不修改我的自定義解析器的getResource方法。我知道這是一個黑客,但它的工作原理,它是足夠的我,我已經花了在這個問題上3天):

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。這解決了我最後的問題。

我希望這可以節省一些人幾天的工作;)