diff options
Diffstat (limited to 'src/documentation/content/xdocs/1.1/servlets.xml')
-rw-r--r-- | src/documentation/content/xdocs/1.1/servlets.xml | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/src/documentation/content/xdocs/1.1/servlets.xml b/src/documentation/content/xdocs/1.1/servlets.xml new file mode 100644 index 000000000..dd2df4351 --- /dev/null +++ b/src/documentation/content/xdocs/1.1/servlets.xml @@ -0,0 +1,325 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<!-- $Id$ --> +<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V2.0//EN" "http://forrest.apache.org/dtd/document-v20.dtd"> +<document> + <header> + <title>Apache™ FOP: Servlets</title> + <subtitle>How to use Apache™ FOP in a Servlet</subtitle> + <version>$Revision$</version> + </header> + <body> + <section id="overview"> + <title>Overview</title> + <p> + This page discusses topic all around using Apache™ FOP in a servlet environment. + </p> + </section> + <section id="example-servlets"> + <title>Example Servlets in the FOP distribution</title> + <p> + In the directory {fop-dir}/src/java/org/apache/fop/servlet, you'll find a working example + of a FOP-enabled servlet. + </p> + <p> + The servlet is automatically built when you build Apache FOP using the supplied Ant script. After building + the servlet, drop fop.war into the webapps directory of Apache Tomcat (or any other web container). Then, you can use + URLs like the following to generate PDF files: + </p> + <ul> + <li>http://localhost:8080/fop/fop?fo=/home/path/to/fofile.fo</li> + <li>http://localhost:8080/fop/fop?xml=/home/path/to/xmlfile.xml&xsl=/home/path/to/xslfile.xsl</li> + </ul> + <p/> + <p>The source code for the servlet can be found under {fop-dir}/src/java/org/apache/fop/servlet/FopServlet.java.</p> + <note> + This example servlet should not be used on a public web server connected to the Internet as it does not contain + any measures to prevent Denial-of-Service-Attacks. It is provided as an example and as a starting point for + your own servlet. + </note> + </section> + <section id="servlet"> + <title>Create your own Servlet</title> + <note> + This section assumes you are familiar with <a href="embedding.html">embedding FOP</a>. + </note> + <section id="minimal-servlet"> + <title>A minimal Servlet</title> + <p> + Here is a minimal code snippet to demonstrate the basics: + </p> + <source>private FopFactory fopFactory = FopFactory.newInstance(); +private TransformerFactory tFactory = TransformerFactory.newInstance(); + +public void doGet(HttpServletRequest request, + HttpServletResponse response) throws ServletException { + try { + response.setContentType("application/pdf"); + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, response.getOutputStream()); + Transformer transformer = tFactory.newTransformer(); + Source src = new StreamSource("foo.fo"); + Result res = new SAXResult(fop.getDefaultHandler()); + transformer.transform(src, res); + } catch (Exception ex) { + throw new ServletException(ex); + } +}</source> + <note> + There are numerous problems with the code snippet above. + Its purpose is only to demonstrate the basic concepts. + See below for details. + </note> + </section> + <section id="xslt"> + <title>Adding XSL tranformation (XSLT)</title> + <p> + A common requirement is to transform an XML source to + XSL-FO using an XSL transformation. It is recommended to use + JAXP for this task. The following snippet shows the basic + code: + </p> + <source>private FopFactory fopFactory = FopFactory.newInstance(); +private TransformerFactory tFactory = TransformerFactory.newInstance(); + +public void init() throws ServletException { + //Optionally customize the FopFactory and TransformerFactory here +} + +[..] + + //Setup a buffer to obtain the content length + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + //Setup FOP + Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); + + //Setup Transformer + Source xsltSrc = new StreamSource(new File("foo-xml2fo.xsl")); + Transformer transformer = tFactory.newTransformer(xsltSrc); + + //Make sure the XSL transformation's result is piped through to FOP + Result res = new SAXResult(fop.getDefaultHandler()); + + //Setup input + Source src = new StreamSource(new File("foo.xml")); + + //Start the transformation and rendering process + transformer.transform(src, res); + + //Prepare response + response.setContentType("application/pdf"); + response.setContentLength(out.size()); + + //Send content to Browser + response.getOutputStream().write(out.toByteArray()); + response.getOutputStream().flush();</source> + <note> + Buffering the generated PDF in a ByteArrayOutputStream is done to avoid potential + problems with the Acrobat Reader Plug-in in Microsoft Internet Explorer. + </note> + <p> + The <code>Source</code> instance used above is simply an + example. If you have to read the XML from a string, supply + a <code>new StreamSource(new + StringReader(xmlstring))</code>. Constructing and reparsing + an XML string is generally less desirable than using a + SAXSource if you generate your XML. You can alternatively + supply a DOMSource as well. You may also use dynamically + generated XSL if you like. + </p> + <p> + Because you have an explicit <code>Transformer</code> object, you can also use it to + explicitely set parameters for the transformation run. + </p> + </section> + <section id="cfg"> + <title>Custom configuration</title> + <p> + You can easily set up your own FOUserAgent as demonstrated on the <a href="embedding.html">Embedding page</a>. + </p> + </section> + <section id="performance"> + <title>Improving performance</title> + <p> + There are several options to consider: + </p> + <ul> + <li> + Instead of java.io.ByteArrayOutputStream consider using the ByteArrayOutputStream + implementation from the <a href="ext:commons-io">Jakarta Commons IO project</a> which allocates less memory. + The full class name is: <code>org.apache.commons.io.output.ByteArrayOutputStream</code> + </li> + <li> + In certain cases it can help to write the generated PDF to a temporary file so + you can quickly reuse the file. This is especially useful, if Internet Explorer + calls the servlet multiple times with the same request or if you often generate + equal PDFs. + </li> + </ul> + <p> + Of course, the + <a href="embedding.html#performance">performance hints from the Embedding page</a> + apply here, too. + </p> + </section> + <section id="uriresolver"> + <title>Accessing resources in your web application</title> + <p> + Often, you will want to use resources (stylesheets, images etc.) which are bundled with + your web application. FOP provides a URIResolver implementation that lets you access + files via the Servlet's ServletContext. The class is called + <code>org.apache.fop.servlet.ServletContextURIResolver</code>. + </p> + <p> + Here's how to set it up in your servlet. Instantiate a new instance in the servlet's + init() method: + </p> + <source><![CDATA[ + /** URIResolver for use by this servlet */ + protected URIResolver uriResolver; + + public void init() throws ServletException { + this.uriResolver = new ServletContextURIResolver(getServletContext()); + [..] + }]]></source> + <p> + The ServletContextURIResolver reacts on URIs beginning with "servlet-context:". If you + want to access an image in a subdirectory of your web application, you could, for + example, use: "servlet-context:/images/myimage.png". Don't forget the leading slash + after the colon! + </p> + <p> + Further down, you can use the URIResolver for various things: + </p> + <ul> + <li> + With the Transformer (JAXP/XSLT) so things like document() functions can resolver + "servlet-context:" URIs. + </li> + <li> + With the FopFactory so every resource FOP loads can be loaded using a "servlet-context:" + URI. + </li> + <li> + You can the ServletContextURIResolver yourself in your servlet code to access + stylesheets or XML files bundled with your web application. + </li> + </ul> + <p> + Here are some example snippets: + </p> + <source><![CDATA[ +//Setting up the JAXP TransformerFactory +this.transFactory = TransformerFactory.newInstance(); +this.transFactory.setURIResolver(this.uriResolver); + +[..] + +//Setting up the FOP factory +this.fopFactory = FopFactory.newInstance(); +this.fopFactory.setURIResolver(this.uriResolver); + +[..] + +//The stylesheet for the JAXP Transfomer +Source xsltSrc = this.uriResolver.resolve( + "servlet-context:/xslt/mystylesheet.xsl", null); +Transformer transformer = this.transFactory.newTransformer(xsltSrc); +transformer.setURIResolver(this.uriResolver);]]></source> + </section> + </section> + <section id="ie"> + <title>Notes on Microsoft Internet Explorer</title> + <p> + Some versions of Internet Explorer will not automatically show the PDF or call the servlet multiple times. + These are well-known limitations of Internet Explorer and are not a problem of the servlet. + However, Internet Explorer can still be used to download the PDF so that it can be viewed later. + Here are some suggestions in this context: + </p> + <ul> + <li> + Use an URL ending in <code>.pdf</code>, like + <code>http://myserver/servlet/stuff.pdf</code>. Yes, the servlet can + be configured to handle this. If the URL has to contain parameters, + try to have <strong>both</strong> the base URL as well as the last parameter end in + <code>.pdf</code>, if necessary append a dummy parameter, like + <code>http://myserver/servlet/stuff.pdf?par1=a&par2=b&d=.pdf</code>. The + effect may depend on IEx version. + </li> + <li> + Give IEx the opportunity to cache. In particular, ensure the + server does not set any headers causing IEx not to cache the + content. This may be a real problem if the document is sent + over HTTPS, because most IEx installations will by default + <em>not</em> cache any content retrieved over HTTPS. + Setting the <code>Expires</code> header entry may help in + this case:<br/> <code>response.setDateHeader("Expires", + System.currentTimeMillis() + cacheExpiringDuration * + 1000);</code><br/> Consult your server manual and the + relevant RFCs for further details on HTTP headers and + caching. + </li> + <li> + Cache in the server. It may help to include a parameter in + the URL which has a timestamp as the value min order to + decide whether a request is repeated. IEx is reported to + retrieve a document up to three times, but never more often. + </li> + </ul> + </section> + <section id="servlet-engine"> + <title>Servlet Engines</title> + <p> + When using a servlet engine, there are potential CLASSPATH issues, and potential conflicts + with existing XML/XSLT libraries. Servlet containers also often use their own classloaders + for loading webapps, which can cause bugs and security problems. + </p> + <section id="tomcat"> + <title>Tomcat</title> + <p> + Check Tomcat's documentation for detailed instructions about installing FOP and Cocoon. + There are known bugs that must be addressed, particularly for Tomcat 4.0.3. + </p> + </section> + <section id="websphere"> + <title>WebSphere 3.5</title> + <p> + Put a copy of a working parser in some directory where WebSphere can access it. + For example, if /usr/webapps/yourapp/servlets is the CLASSPATH for your servlets, + copy the Xerces jar into it (any other directory would also be fine). + Do not add the jar to the servlet CLASSPATH, but add it to the CLASSPATH of the + application server which contains your web application. + In the WebSphere administration console, click on the "environment" button in the + "general" tab. In the "variable name" box, enter "CLASSPATH". + In the "value" box, enter the correct path to the parser jar file + (/usr/webapps/yourapp/servlets/Xerces.jar in our example here). + Press "OK", then apply the change and restart the application server. + </p> + </section> + </section> + <section id="complex-usecases"> + <title>Handling complex use cases</title> + <p> + Sometimes the requirements for a servlet get quite sophisticated: SQL data sources, + multiple XSL transformations, merging of several datasources etc. In such a case + consider using <a class="fork" href="ext:cocoon">Apache Cocoon</a> instead + of a custom servlet to accomplish your goal. + </p> + </section> + </body> +</document>
\ No newline at end of file |