Package com.isomorphic.contentexport

# Class PdfExport

java.lang.Object
com.isomorphic.base.Base
com.isomorphic.contentexport.PdfExport

All Implemented Interfaces:
  `com.isomorphic.base.IAutoConfigurable`, `IPdfExporter`

public class PdfExport extends com.isomorphic.base.Base implements IPdfExporter

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `getPdfObject(String html, Map settings, jakarta.servlet.http.HttpServletResponse response, RPCManager rpc)`
  Converts the provided HTML to a PDF object and streams the response back to the browser as the response to an RPCRequest/DSRequest.
  `org.xhtmlrenderer.pdf.ITextRenderer`
  `getPdfRenderer(String html, Map settings)`
  Method to create an ITextRenderer object ready to generate a PDF object.

- ## Method Details

  - ### getPdfObject

    public void getPdfObject(String html, Map settings, jakarta.servlet.http.HttpServletResponse response, RPCManager rpc) throws Exception
    Converts the provided HTML to a PDF object and streams the response back to the browser as the response to an RPCRequest/DSRequest.

    For additional methods, including the ability to generate a .pdf that be saved to a database or emailed rather than streamed to the client, see `getPdfRenderer(String, Map)`

    When the provided HTML contains <img> tags, such as when an Img widget is to be included in the PDF export, SmartClient Server Framework needs to be able to download the image for inclusion in the PDF. If images are not appearing in an exported PDF, examine the server's log output for information on why an image request failed. Common ResourceLoader errors include:

    - `Failed to download http://MY_HOST:PORT/SOME_IMAGE.png: java.net.ConnectException: Connection refused`

      The server was unable to connect to the server at MY_HOST:PORT.

      One possible cause is that the server is not bound on all addresses (also called "listening on all addresses"). If you are using JBoss, refer to ConfigureServerPorts for more information on JBoss' `-b` command line option. When developing within Eclipse and deploying to the internal Web Server, try using the `-bindAddress 0.0.0.0` Development Mode option.

      Another possible cause is that port forwarding is not set up correctly or the Java networking API's proxy settings need to be configured.

    - `Failed to download http://SOME_HOST/PROTECTED_RESOURCE.png: java.io.IOException: Server returned HTTP response code: 401`

      The server responded with a 401 Unauthorized response code.

      The SOME_HOST server is requiring authorization, but needs to pass through requests made by the SmartClient Server Framework.

    - `Failed to download http://SOME_HOST/SOME_IMAGE.png: java.io.IOException: Server returned HTTP response code: 404`

      The SOME_HOST server responded with a 404 Not Found response code.

      This may happen if requests for the image need to go through a reverse proxy. Refer to http://docs.oracle.com/javase/6/docs/technotes/guides/net/proxies.html for a guide on configuring the Java networking API's proxy settings.

    Specified by:
      `getPdfObject` in interface `IPdfExporter`
    Parameters:
      `html` - generated html from client-side
      `settings` - map of parameters
      `response` - in this parameter we send the answer
      `rpc` - our RPCManager parameter
    Throws:
      `Exception`

  - ### getPdfRenderer

    public org.xhtmlrenderer.pdf.ITextRenderer getPdfRenderer(String html, Map settings) throws Exception
    Method to create an ITextRenderer object ready to generate a PDF object. With the ITextRenderer object, you can use any OutputStream object to generate a PDF object, eg.: To generate a PDF file from this ITextRenderer object, you can make:
    server-side:

         public String generatePdf(DSRequest request) {
             String response = "Operation completed successfully";
             try {
                 Map data = request.getValues();
                 Map settings = new HashMap();
                 settings.put("skinName", data.get("skinName").toString());
                 String dirServer = "/shared/directoryPdf/";
                 String fileName = "default";
                 String outputFile = dirServer+fileName+".pdf";
                 OutputStream outputSream = new FileOutputStream(outputFile);
                 PdfExport export = new PdfExport();
                 ITextRenderer renderer = export.getPdfRenderer(data.get("html").toString(), settings);
                 renderer.createPDF(outputSream);
                 outputSream.close();
             }catch (Exception e) {
                 e.printStackTrace();
                 response = e.getMessage();
             }
             return response;
         }

    You can use DataSource.performCustomOperation() in client-side to invoke your custom method in server-side, eg.:

         ...........
         vLayout.getPrintHTML(null, new PrintHTMLCallback(){
             public void setHTML(String html) {
                 DSRequest request = new DSRequest();
                 LinkedHashMap data = new LinkedHashMap();
                 data.put("html", html);
                 data.put("skinName", "Enterprise");
                 request.setData(data);
                 ds.performCustomOperation("generatePdf", new Record(), new DSCallback() {
                     public void execute(DSResponse response, Object rawData, DSRequest request) {
                         SC.say((String)rawData);
                     }
                 }, request);
             }
         });

    and the .ds.xml DataSource would be something like this:

         <DataSource ID="supplyItem>
         <fields>
             ..........
         </fields>
         <operationBindings>
             <operationBinding operationId="generatePdf" operationType="custom" serverMethod="generatePdf">
                 <serverObject lookupStyle="new" className="com.smartgwt.sample.server.CustomOperation"/>
             </operationBinding>
         </operationBindings>
         </DataSource>

    If required, it is possible to use an extra stylesheet. To make the extra stylesheet available for this process, follow these steps:
    1.- In server.properties, set:
    skin.[skinName].extraStyleSheet: path/to/stylesheet/[extraStyleSheet.css]
    Eg.: skin.Enterprise.extraStyleSheet: dirSkins/mySkins/myStyleSheet.css
    The dirSkins/ folder must be placed under webroot.
    2.- When using images within the extra stylesheet, these images must be placed in, for example:
    - dirSkins/mySkins/images/picture1.png (as in the previous example)
    Or, when these images are in a different folder other than the extra stylesheet:
    - myCustomImages/48x48/picture1.png (The myCustomImages/ folder must be placed under webroot)

    - Internationalization and Fonts with PDFs

    When you are displaying HTML content in the browser, and you use non-Latin Unicode characters such as Japanese characters or Cyrillic letters, web browsers will automatically locate and use a font that includes these characters.

    PDF generation doesn't work this way. When you declare in CSS that text content in your HTML is rendered with a certain font-family, that font-family is what the PDF library will use, even if the font file for that font-family has no support for some of the characters in your text. Unfortunately, the default font files included for Arial and other common web fonts do not include support for many non-Latin characters, including Cyrillic and CJK (Chinese Japanese Korean) characters.

    To get around this problem, you need to provide a font file that has support for international characters, and explicitly configure it. For example, the ARIALUNI.TFF file that exists in standard Windows installations has a font-family "Arial Unicode MS" with support for all Unicode 2.0 characters.

    To use this file, you would provide an extraStyleSheet with a declaration like this:

         @font-face {
             font-family: 'Arial Unicode MS';
             src: url('fonts/ARIALUNI.TTF');
         }

    Place the font file in the "fonts" directory under the directory where the extra stylesheet is located.

    Your extraStyleSheet can then declare "Arial Unicode MS" as the font family to use wherever Unicode characters may appear, for example, a declaration like this won't cause "Arial Unicode MS" to be used for all ListGrid cell content:

         .cell,
         .cellDark,
         ... several other variants ...
         .cellDisabledDark {
             font-family:"Arial Unicode MS";
         }

    Typically however, Unicode characters may appear anywhere in your application. A full solution is to take the skin_styles.css file for the skin you are using and do a search-and-replace across the entire file, prefixing all font-family declarations with a font-family that covers Unicode characters. Then use the resulting file as your extraStylesheet.

    How to obtain and license appropriate font files is out of the scope of this document, but the following website has extensive information about fonts that support Unicode, including free options:
    http://www.alanwood.net/unicode/fonts.html

    Parameters:
      `html` - generated html from client-side
      `settings` - map of parameters
    Returns:
      ITextRenderer
    Throws:
      `Exception`