1

I want to draw a xy line chart on PDF. After clicking on a button on a JSP, a PDF will be generated with xy line chart. So I have used jfreechart to create xy line chart and then wants to print it in PDF format using OrsonPDF.

I have seen the same example on https://jfree.github.io/orsonpdf/

But the problem is I couldn't run it using server request, response. And also the code itself gives some error.

The button code is as below:

    <form action="testPdf" method="post" target="_blank">
    <center><button class="submitbtn" value="submit" type="submit"><center>Generate PDF</center></button></center>
    </form>

Here I am attaching my 'testPdf.java' code:

package servlet;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Rectangle;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.xobject.PdfFormXObject;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.orsonpdf.PDFDocument;
import com.orsonpdf.PDFGraphics2D;
import com.orsonpdf.Page;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.ui.HorizontalAlignment;
import org.jfree.data.time.Month;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;

/**
 * Creates a PDF document with iText, then inserts a PDF chart generated with
 * JFreeChart and OrsonPDF.
 */
public class testPdf extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
       static final long serialVersionUID = 1L;
       
        /* (non-Java-doc)
         * @see javax.servlet.http.HttpServlet#HttpServlet()
         */
        public testPdf() {
            super();
        }

    private static byte[] generateChartPDF() {
        // here we use OrsonPDF to generate PDF in a byte array
        PDFDocument doc = new PDFDocument();
        Rectangle bounds = new Rectangle(500, 335);
        Page page = doc.createPage(bounds);
        PDFGraphics2D g2 = page.getGraphics2D();
        JFreeChart chart = createChart(createDataset());
        chart.draw(g2, bounds);
        return doc.getPDFBytes();
    }
    
    /**
     * Creates a chart.
     *
     * @param dataset  a dataset.
     *
     * @return A chart.
     */
    private static JFreeChart createChart(XYDataset dataset) {

        JFreeChart chart = ChartFactory.createTimeSeriesChart(
            "International Coffee Organisation : Coffee Prices",
            null, "US cents/lb", dataset);

        String fontName = "Serif";
        chart.getTitle().setFont(new Font(fontName, Font.BOLD, 18));
        chart.addSubtitle(new TextTitle(
                "Source: http://www.ico.org/historical/2010-19/PDF/HIST-PRICES.pdf", 
                new Font(fontName, Font.PLAIN, 14)));

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setDomainPannable(true);
        plot.setRangePannable(false);
        plot.setDomainCrosshairVisible(true);
        plot.setRangeCrosshairVisible(true);
        plot.getDomainAxis().setLowerMargin(0.0);
        plot.getDomainAxis().setLabelFont(new Font(fontName, Font.BOLD, 14));
        plot.getDomainAxis().setTickLabelFont(new Font(fontName, Font.PLAIN, 10));
        plot.getRangeAxis().setLabelFont(new Font(fontName, Font.BOLD, 14));
        plot.getRangeAxis().setTickLabelFont(new Font(fontName, Font.PLAIN, 10));
        plot.setRangeGridlinePaint(Color.GRAY);
        plot.setDomainGridlinePaint(Color.GRAY);
        chart.getLegend().setItemFont(new Font(fontName, Font.PLAIN, 14));
        chart.getLegend().setFrame(BlockBorder.NONE);
        chart.getLegend().setHorizontalAlignment(HorizontalAlignment.CENTER);
        XYItemRenderer r = plot.getRenderer();
        if (r instanceof XYLineAndShapeRenderer) {
            XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
            renderer.setDefaultShapesVisible(false);
            renderer.setDrawSeriesLineAsPath(true);
            // set the default stroke for all series
            renderer.setAutoPopulateSeriesStroke(false);
            renderer.setDefaultStroke(new BasicStroke(3.0f, 
                    BasicStroke.CAP_ROUND, BasicStroke.JOIN_BEVEL), false);
            renderer.setSeriesPaint(0, Color.RED);
            renderer.setSeriesPaint(1, new Color(24, 123, 58));
            renderer.setSeriesPaint(2, new Color(149, 201, 136));
            renderer.setSeriesPaint(3, new Color(1, 62, 29));
            renderer.setSeriesPaint(4, new Color(81, 176, 86));
            renderer.setSeriesPaint(5, new Color(0, 55, 122));
            renderer.setSeriesPaint(6, new Color(0, 92, 165));
        }

        return chart;

    }

    /**
     * Creates a dataset, consisting of two series of monthly data.
     *
     * @return the dataset.
     */
    private static XYDataset createDataset() {

        TimeSeries s1 = new TimeSeries("Indicator Price");
        s1.add(new Month(1, 2010), 126.80);
        s1.add(new Month(2, 2010), 123.37);
        s1.add(new Month(3, 2010), 125.30);
        s1.add(new Month(4, 2010), 126.89);
        s1.add(new Month(5, 2010), 128.10);
        s1.add(new Month(6, 2010), 142.20);
        s1.add(new Month(7, 2010), 153.41);
        s1.add(new Month(8, 2010), 157.46);
        s1.add(new Month(9, 2010), 163.61);
        s1.add(new Month(10, 2010), 161.56);

        TimeSeries s2 = new TimeSeries("Columbian Milds");
        s2.add(new Month(1, 2010), 207.51);
        s2.add(new Month(2, 2010), 204.71);
        s2.add(new Month(3, 2010), 205.71);
        s2.add(new Month(4, 2010), 200.00);
        s2.add(new Month(5, 2010), 200.54);
        s2.add(new Month(6, 2010), 224.49);
        s2.add(new Month(7, 2010), 235.52);
        s2.add(new Month(8, 2010), 243.98);
        s2.add(new Month(9, 2010), 247.77);
        s2.add(new Month(10, 2010), 230.02);
        
        TimeSeries s3 = new TimeSeries("Other Milds");
        s3.add(new Month(1, 2010), 158.90);
        s3.add(new Month(2, 2010), 157.86);
        s3.add(new Month(3, 2010), 164.50);
        s3.add(new Month(4, 2010), 169.55);
        s3.add(new Month(5, 2010), 173.38);
        s3.add(new Month(6, 2010), 190.90);
        s3.add(new Month(7, 2010), 203.21);
        s3.add(new Month(8, 2010), 211.59);
        s3.add(new Month(9, 2010), 222.71);
        s3.add(new Month(10, 2010), 217.64);
       
        TimeSeriesCollection dataset = new TimeSeriesCollection();
        dataset.addSeries(s1);
        dataset.addSeries(s2);
        dataset.addSeries(s3);
        return dataset;
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletOutputStream os = response.getOutputStream();
        response.setContentType("application/pdf");
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, os);
        PdfDocument targetPDF = new PdfDocument(writer);
        document.add(new Paragraph("Demo showing a JFreeChart being rendered into a PDF document created by iText 7."));
        
        PdfReader reader = new PdfReader(new ByteArrayInputStream(generateChartPDF()));
        PdfDocument chartDoc = new PdfDocument(reader);
        PdfFormXObject chart = chartDoc.getFirstPage().copyAsFormXObject(targetPDF);
        Image chartImage = new Image(chart);
        document.add(new Paragraph("Here we add a chart... ").add(chartImage));
        document.close();
    }
/* (non-Java-doc)
 * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 */
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}               
}

Please help me to find the solution. I cannot solve this problem from last couple of days. I know its a very common problem although, but couldn't find any solution. Thank you in advance.

Amit K Kushwaha
  • 113
  • 1
  • 7
  • although I'm not familiar with orsonpdf, have you considered using the SVG version of your chart to embed on your PDF (I'm assuming you want to use orson for vector/quality purposes)? I believe you can do it with jfreechart. Another option would be to use [Lets-Plot](https://github.com/JetBrains/lets-plot-kotlin). It's actually what we use to plot charts in iText DITO (which uses iText Core and pdfHTML). – André Lemos Sep 14 '22 at 12:59
  • 1
    I don't know what errors you'e getting, but your `createChart()` and `createDataset()` are correct. – Catalina Island Oct 05 '22 at 17:58

0 Answers0