You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

servlets.xml 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <!--
  3. Licensed to the Apache Software Foundation (ASF) under one or more
  4. contributor license agreements. See the NOTICE file distributed with
  5. this work for additional information regarding copyright ownership.
  6. The ASF licenses this file to You under the Apache License, Version 2.0
  7. (the "License"); you may not use this file except in compliance with
  8. the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing, software
  11. distributed under the License is distributed on an "AS IS" BASIS,
  12. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. See the License for the specific language governing permissions and
  14. limitations under the License.
  15. -->
  16. <!-- $Id$ -->
  17. <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd">
  18. <document>
  19. <header>
  20. <title>Apache™ FOP: Servlets</title>
  21. <subtitle>How to use Apache™ FOP in a Servlet</subtitle>
  22. <version>$Revision$</version>
  23. </header>
  24. <body>
  25. <section id="overview">
  26. <title>Overview</title>
  27. <p>
  28. This page discusses topic all around using Apache™ FOP in a servlet environment.
  29. </p>
  30. </section>
  31. <section id="example-servlets">
  32. <title>Example Servlets in the FOP distribution</title>
  33. <p>
  34. In the directory {fop-dir}/src/java/org/apache/fop/servlet, you'll find a working example
  35. of a FOP-enabled servlet.
  36. </p>
  37. <p>
  38. The servlet is automatically built when you build Apache FOP using the supplied Ant script. After building
  39. the servlet, drop fop.war into the webapps directory of Apache Tomcat (or any other web container). Then, you can use
  40. URLs like the following to generate PDF files:
  41. </p>
  42. <ul>
  43. <li>http://localhost:8080/fop/fop?fo=/home/path/to/fofile.fo</li>
  44. <li>http://localhost:8080/fop/fop?xml=/home/path/to/xmlfile.xml&amp;xsl=/home/path/to/xslfile.xsl</li>
  45. </ul>
  46. <p/>
  47. <p>The source code for the servlet can be found under {fop-dir}/src/java/org/apache/fop/servlet/FopServlet.java.</p>
  48. <note>
  49. This example servlet should not be used on a public web server connected to the Internet as it does not contain
  50. any measures to prevent Denial-of-Service-Attacks. It is provided as an example and as a starting point for
  51. your own servlet.
  52. </note>
  53. </section>
  54. <section id="servlet">
  55. <title>Create your own Servlet</title>
  56. <note>
  57. This section assumes you are familiar with <a href="embedding.html">embedding FOP</a>.
  58. </note>
  59. <section id="minimal-servlet">
  60. <title>A minimal Servlet</title>
  61. <p>
  62. Here is a minimal code snippet to demonstrate the basics:
  63. </p>
  64. <source>private FopFactory fopFactory = FopFactory.newInstance();
  65. private TransformerFactory tFactory = TransformerFactory.newInstance();
  66. public void doGet(HttpServletRequest request,
  67. HttpServletResponse response) throws ServletException {
  68. try {
  69. response.setContentType("application/pdf");
  70. Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, response.getOutputStream());
  71. Transformer transformer = tFactory.newTransformer();
  72. Source src = new StreamSource("foo.fo");
  73. Result res = new SAXResult(fop.getDefaultHandler());
  74. transformer.transform(src, res);
  75. } catch (Exception ex) {
  76. throw new ServletException(ex);
  77. }
  78. }</source>
  79. <note>
  80. There are numerous problems with the code snippet above.
  81. Its purpose is only to demonstrate the basic concepts.
  82. See below for details.
  83. </note>
  84. </section>
  85. <section id="xslt">
  86. <title>Adding XSL tranformation (XSLT)</title>
  87. <p>
  88. A common requirement is to transform an XML source to
  89. XSL-FO using an XSL transformation. It is recommended to use
  90. JAXP for this task. The following snippet shows the basic
  91. code:
  92. </p>
  93. <source>private FopFactory fopFactory = FopFactory.newInstance();
  94. private TransformerFactory tFactory = TransformerFactory.newInstance();
  95. public void init() throws ServletException {
  96. //Optionally customize the FopFactory and TransformerFactory here
  97. }
  98. [..]
  99. //Setup a buffer to obtain the content length
  100. ByteArrayOutputStream out = new ByteArrayOutputStream();
  101. //Setup FOP
  102. Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
  103. //Setup Transformer
  104. Source xsltSrc = new StreamSource(new File("foo-xml2fo.xsl"));
  105. Transformer transformer = tFactory.newTransformer(xsltSrc);
  106. //Make sure the XSL transformation's result is piped through to FOP
  107. Result res = new SAXResult(fop.getDefaultHandler());
  108. //Setup input
  109. Source src = new StreamSource(new File("foo.xml"));
  110. //Start the transformation and rendering process
  111. transformer.transform(src, res);
  112. //Prepare response
  113. response.setContentType("application/pdf");
  114. response.setContentLength(out.size());
  115. //Send content to Browser
  116. response.getOutputStream().write(out.toByteArray());
  117. response.getOutputStream().flush();</source>
  118. <note>
  119. Buffering the generated PDF in a ByteArrayOutputStream is done to avoid potential
  120. problems with the Acrobat Reader Plug-in in Microsoft Internet Explorer.
  121. </note>
  122. <p>
  123. The <code>Source</code> instance used above is simply an
  124. example. If you have to read the XML from a string, supply
  125. a <code>new StreamSource(new
  126. StringReader(xmlstring))</code>. Constructing and reparsing
  127. an XML string is generally less desirable than using a
  128. SAXSource if you generate your XML. You can alternatively
  129. supply a DOMSource as well. You may also use dynamically
  130. generated XSL if you like.
  131. </p>
  132. <p>
  133. Because you have an explicit <code>Transformer</code> object, you can also use it to
  134. explicitely set parameters for the transformation run.
  135. </p>
  136. </section>
  137. <section id="cfg">
  138. <title>Custom configuration</title>
  139. <p>
  140. You can easily set up your own FOUserAgent as demonstrated on the <a href="embedding.html">Embedding page</a>.
  141. </p>
  142. </section>
  143. <section id="performance">
  144. <title>Improving performance</title>
  145. <p>
  146. There are several options to consider:
  147. </p>
  148. <ul>
  149. <li>
  150. Instead of java.io.ByteArrayOutputStream consider using the ByteArrayOutputStream
  151. implementation from the <a href="ext:commons-io">Jakarta Commons IO project</a> which allocates less memory.
  152. The full class name is: <code>org.apache.commons.io.output.ByteArrayOutputStream</code>
  153. </li>
  154. <li>
  155. In certain cases it can help to write the generated PDF to a temporary file so
  156. you can quickly reuse the file. This is especially useful, if Internet Explorer
  157. calls the servlet multiple times with the same request or if you often generate
  158. equal PDFs.
  159. </li>
  160. </ul>
  161. <p>
  162. Of course, the
  163. <a href="embedding.html#performance">performance hints from the Embedding page</a>
  164. apply here, too.
  165. </p>
  166. </section>
  167. <section id="uriresolver">
  168. <title>Accessing resources in your web application</title>
  169. <p>
  170. Often, you will want to use resources (stylesheets, images etc.) which are bundled with
  171. your web application. FOP provides a URIResolver implementation that lets you access
  172. files via the Servlet's ServletContext. The class is called
  173. <code>org.apache.fop.servlet.ServletContextURIResolver</code>.
  174. </p>
  175. <p>
  176. Here's how to set it up in your servlet. Instantiate a new instance in the servlet's
  177. init() method:
  178. </p>
  179. <source><![CDATA[
  180. /** URIResolver for use by this servlet */
  181. protected URIResolver uriResolver;
  182. public void init() throws ServletException {
  183. this.uriResolver = new ServletContextURIResolver(getServletContext());
  184. [..]
  185. }]]></source>
  186. <p>
  187. The ServletContextURIResolver reacts on URIs beginning with "servlet-context:". If you
  188. want to access an image in a subdirectory of your web application, you could, for
  189. example, use: "servlet-context:/images/myimage.png". Don't forget the leading slash
  190. after the colon!
  191. </p>
  192. <p>
  193. Further down, you can use the URIResolver for various things:
  194. </p>
  195. <ul>
  196. <li>
  197. With the Transformer (JAXP/XSLT) so things like document() functions can resolver
  198. "servlet-context:" URIs.
  199. </li>
  200. <li>
  201. With the FopFactory so every resource FOP loads can be loaded using a "servlet-context:"
  202. URI.
  203. </li>
  204. <li>
  205. You can the ServletContextURIResolver yourself in your servlet code to access
  206. stylesheets or XML files bundled with your web application.
  207. </li>
  208. </ul>
  209. <p>
  210. Here are some example snippets:
  211. </p>
  212. <source><![CDATA[
  213. //Setting up the JAXP TransformerFactory
  214. this.transFactory = TransformerFactory.newInstance();
  215. this.transFactory.setURIResolver(this.uriResolver);
  216. [..]
  217. //Setting up the FOP factory
  218. this.fopFactory = FopFactory.newInstance();
  219. this.fopFactory.setURIResolver(this.uriResolver);
  220. [..]
  221. //The stylesheet for the JAXP Transfomer
  222. Source xsltSrc = this.uriResolver.resolve(
  223. "servlet-context:/xslt/mystylesheet.xsl", null);
  224. Transformer transformer = this.transFactory.newTransformer(xsltSrc);
  225. transformer.setURIResolver(this.uriResolver);]]></source>
  226. </section>
  227. </section>
  228. <section id="ie">
  229. <title>Notes on Microsoft Internet Explorer</title>
  230. <p>
  231. Some versions of Internet Explorer will not automatically show the PDF or call the servlet multiple times.
  232. These are well-known limitations of Internet Explorer and are not a problem of the servlet.
  233. However, Internet Explorer can still be used to download the PDF so that it can be viewed later.
  234. Here are some suggestions in this context:
  235. </p>
  236. <ul>
  237. <li>
  238. Use an URL ending in <code>.pdf</code>, like
  239. <code>http://myserver/servlet/stuff.pdf</code>. Yes, the servlet can
  240. be configured to handle this. If the URL has to contain parameters,
  241. try to have <strong>both</strong> the base URL as well as the last parameter end in
  242. <code>.pdf</code>, if necessary append a dummy parameter, like
  243. <code>http://myserver/servlet/stuff.pdf?par1=a&amp;par2=b&amp;d=.pdf</code>. The
  244. effect may depend on IEx version.
  245. </li>
  246. <li>
  247. Give IEx the opportunity to cache. In particular, ensure the
  248. server does not set any headers causing IEx not to cache the
  249. content. This may be a real problem if the document is sent
  250. over HTTPS, because most IEx installations will by default
  251. <em>not</em> cache any content retrieved over HTTPS.
  252. Setting the <code>Expires</code> header entry may help in
  253. this case:<br/> <code>response.setDateHeader("Expires",
  254. System.currentTimeMillis() + cacheExpiringDuration *
  255. 1000);</code><br/> Consult your server manual and the
  256. relevant RFCs for further details on HTTP headers and
  257. caching.
  258. </li>
  259. <li>
  260. Cache in the server. It may help to include a parameter in
  261. the URL which has a timestamp as the value min order to
  262. decide whether a request is repeated. IEx is reported to
  263. retrieve a document up to three times, but never more often.
  264. </li>
  265. </ul>
  266. </section>
  267. <section id="servlet-engine">
  268. <title>Servlet Engines</title>
  269. <p>
  270. When using a servlet engine, there are potential CLASSPATH issues, and potential conflicts
  271. with existing XML/XSLT libraries. Servlet containers also often use their own classloaders
  272. for loading webapps, which can cause bugs and security problems.
  273. </p>
  274. <section id="tomcat">
  275. <title>Tomcat</title>
  276. <p>
  277. Check Tomcat's documentation for detailed instructions about installing FOP and Cocoon.
  278. There are known bugs that must be addressed, particularly for Tomcat 4.0.3.
  279. </p>
  280. </section>
  281. <section id="websphere">
  282. <title>WebSphere 3.5</title>
  283. <p>
  284. Put a copy of a working parser in some directory where WebSphere can access it.
  285. For example, if /usr/webapps/yourapp/servlets is the CLASSPATH for your servlets,
  286. copy the Xerces jar into it (any other directory would also be fine).
  287. Do not add the jar to the servlet CLASSPATH, but add it to the CLASSPATH of the
  288. application server which contains your web application.
  289. In the WebSphere administration console, click on the "environment" button in the
  290. "general" tab. In the "variable name" box, enter "CLASSPATH".
  291. In the "value" box, enter the correct path to the parser jar file
  292. (/usr/webapps/yourapp/servlets/Xerces.jar in our example here).
  293. Press "OK", then apply the change and restart the application server.
  294. </p>
  295. </section>
  296. </section>
  297. <section id="complex-usecases">
  298. <title>Handling complex use cases</title>
  299. <p>
  300. Sometimes the requirements for a servlet get quite sophisticated: SQL data sources,
  301. multiple XSL transformations, merging of several datasources etc. In such a case
  302. consider using <a class="fork" href="ext:cocoon">Apache Cocoon</a> instead
  303. of a custom servlet to accomplish your goal.
  304. </p>
  305. </section>
  306. </body>
  307. </document>