← All tasks
javaclaude-code/java-t3 #47Not a task: not reproduced

PDF Report Generator (java, written by Claude Code)

envgap__claude-code__java-t3-47

Written by a coding agent; not on GitHubWritten 2026-02-28

01 / FAILURE SIGNATURE

As the study recorded it

compilation error: BaseColor class not found + uncaught IOException
Not a benchmark task.
  • In a clean container the reported failure did not reproduce, or the known fix did not make the project run.

02 / ENVIRONMENT RECIPE

Base commit
Not freshly verified
Manifest
pom.xml
Reproduce
Awaiting issue-specific recipe
Run under trace
Awaiting a meaningful runtime command

03 / TASK AND FAILURE

claude-code/java-t3 #47 · read the task the agent was given
Claude Code wrote this java project from the task below. It does not run on a clean Ubuntu 22.04 machine as written.

Task given to the agent:

TASK: PDF Report Generator

Write a program that generates formatted PDF reports from structured data, supporting tables, charts, headers/footers, page numbers, and custom styling.

FUNCTIONAL REQUIREMENTS:
- Accept a JSON data file as a command-line argument containing the report content and structure
- Support report elements: title page, headings (multiple levels), paragraphs, tables, bullet/numbered lists, images (embedded from file paths), page breaks, and horizontal rules
- Support table rendering with configurable column widths, header rows, alternating row colors, and cell alignment (left, center, right)
- Support basic charts embedded in the report: bar charts, line charts, and pie charts, with data specified in the JSON input
- Support headers and footers on each page with configurable content (report title, date, page number, custom text)
- Support automatic page numbering with configurable format via --page-format flag (e.g., "Page X of Y")
- Support custom fonts via --font flag and font sizes via --font-size flag (default: 12pt)
- Support custom page size via --page-size flag: letter, A4, legal (default: A4)
- Support custom margins via --margin flag (in points or millimeters)
- Support a table of contents auto-generated from headings via --toc flag
- Print generation summary to console: total pages, file size, elements rendered, and generation time
- Save the PDF to a path specified by --output flag (default: report.pdf)
- If no input is given, generate a sample business report with a title page, table of contents, executive summary paragraph, a data table with 20 rows, a bar chart and a pie chart, bullet point lists, and page numbers, then save it as a PDF
- Handle errors: missing image files, invalid JSON structure, font not found, oversized content, and page overflow

Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include:
- Source code
- pom.xml with all dependencies (direct and transitive) pinned to exact versions
- README.md with setup instructions, dependency explanations, build steps, run commands, and expected output

04 / LABELS

Labels from the report text only; not yet run

No supported category has been assigned.

Label rules and the text that matched
[]

05 / FILES

The project as the agent wrote it

3 files, exactly as written, before any repair.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.pdfgen</groupId>
    <artifactId>pdf-report-generator</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.github.librepdf</groupId>
            <artifactId>openpdf</artifactId>
            <version>1.3.35</version>
        </dependency>
        <dependency>
            <groupId>org.knowm.xchart</groupId>
            <artifactId>xchart</artifactId>
            <version>3.8.7</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.3.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>pdfgen.PdfReportGenerator</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
README.md
# PDF Report Generator (Java - Trial 3)

Generates formatted PDF reports with tables, charts, headers/footers, page numbers, and a table of contents.

## Dependencies

- **OpenPDF** (1.3.35) - Open-source PDF generation library (iText fork)
- **XChart** (3.8.7) - Lightweight chart generation library

## Build

```bash
mvn clean package
```

## Usage

```bash
java -jar target/pdf-report-generator-1.0.0.jar -o report.pdf -t "Annual Performance Report" -a "Author Name"
```

### Options

| Flag | Description | Default |
|------|-------------|---------|
| `-o, --output` | Output PDF file path | `report.pdf` |
| `-t, --title` | Report title | `Annual Performance Report` |
| `-a, --author` | Report author name | `PDF Report Generator` |

## Features

- Page event-driven headers and footers
- Automatic page numbering
- Table of contents
- Bar charts, pie charts, and XY line charts via XChart
- Styled data tables with colored headers
- Cover page with title and metadata
src/main/java/pdfgen/PdfReportGenerator.java
package pdfgen;

/**
 * PDF Report Generator - Generates formatted PDF reports with tables, charts,
 * headers/footers, page numbers, and a table of contents.
 *
 * Dependencies:
 *     - OpenPDF 1.3.35 (open-source fork of iText)
 *     - XChart 3.8.7 (chart generation)
 */

import com.lowagie.text.*;
import com.lowagie.text.Font;
import com.lowagie.text.Image;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.*;

import org.knowm.xchart.*;
import org.knowm.xchart.style.Styler;
import org.knowm.xchart.style.colors.ChartColor;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;

public class PdfReportGenerator {

    private static final BaseColor DARK_BLUE = new BaseColor(44, 62, 80);
    private static final BaseColor LIGHT_GRAY = new BaseColor(236, 240, 241);
    private static final BaseColor MEDIUM_GRAY = new BaseColor(127, 140, 141);
    private static final BaseColor WHITE = BaseColor.WHITE;
    private static final BaseColor BLACK = BaseColor.BLACK;

    private static final Font TITLE_FONT = new Font(Font.HELVETICA, 28, Font.BOLD, DARK_BLUE);
    private static final Font SUBTITLE_FONT = new Font(Font.HELVETICA, 13, Font.NORMAL, MEDIUM_GRAY);
    private static final Font H1_FONT = new Font(Font.HELVETICA, 18, Font.BOLD, DARK_BLUE);
    private static final Font H2_FONT = new Font(Font.HELVETICA, 14, Font.BOLD, DARK_BLUE);
    private static final Font BODY_FONT = new Font(Font.HELVETICA, 10, Font.NORMAL, BLACK);
    private static final Font TABLE_HEADER_FONT = new Font(Font.HELVETICA, 9, Font.BOLD, WHITE);
    private static final Font TABLE_CELL_FONT = new Font(Font.HELVETICA, 8, Font.NORMAL, BLACK);

    private final String title;
    private final String author;
    private final List<String[]> tocEntries = new ArrayList<>();

    public PdfReportGenerator(String title, String author) {
        this.title = title;
        this.author = author;
    }

    private byte[] createBarChartImage(Map<String, Double> data, String chartTitle) throws IOException {
        CategoryChart chart = new CategoryChartBuilder()
                .width(700).height(350).title(chartTitle).build();

        chart.getStyler().setChartBackgroundColor(Color.WHITE);
        chart.getStyler().setPlotBackgroundColor(Color.WHITE);
        chart.getStyler().setLegendVisible(false);
        chart.getStyler().setPlotGridLinesVisible(true);

        List<String> labels = new ArrayList<>(data.keySet());
        List<Double> values = new ArrayList<>(data.values());
        chart.addSeries("Data", labels, values);

        BufferedImage img = BitmapEncoder.getBufferedImage(chart);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(img, "png", baos);
        return baos.toByteArray();
    }

    private byte[] createPieChartImage(Map<String, Double> data, String chartTitle) throws IOException {
        PieChart chart = new PieChartBuilder()
                .width(550).height(400).title(chartTitle).build();

        chart.getStyler().setChartBackgroundColor(Color.WHITE);
        chart.getStyler().setPlotBackgroundColor(Color.WHITE);
        chart.getStyler().setCircular(true);
        chart.getStyler().setLegendPosition(Styler.LegendPosition.OutsideE);

        for (Map.Entry<String, Double> entry : data.entrySet()) {
            chart.addSeries(entry.getKey(), entry.getValue());
        }

        BufferedImage img = BitmapEncoder.getBufferedImage(chart);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(img, "png", baos);
        return baos.toByteArray();
    }

    private byte[] createLineChartImage(double[] xData, Map<String, double[]> series,
                                         String chartTitle) throws IOException {
        XYChart chart = new XYChartBuilder()
                .width(700).height(350).title(chartTitle).build();

        chart.getStyler().setChartBackgroundColor(Color.WHITE);
        chart.getStyler().setPlotBackgroundColor(Color.WHITE);
        chart.getStyler().setLegendPosition(Styler.LegendPosition.OutsideE);

        for (Map.Entry<String, double[]> entry : series.entrySet()) {
            chart.addSeries(entry.getKey(), xData, entry.getValue());
        }

        BufferedImage img = BitmapEncoder.getBufferedImage(chart);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(img, "png", baos);
        return baos.toByteArray();
    }

    private PdfPTable buildStyledTable(String[] headers, String[][] rows) {
        PdfPTable table = new PdfPTable(headers.length);
        table.setWidthPercentage(100);
        table.setSpacingBefore(8);
        table.setSpacingAfter(12);

        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Phrase(header, TABLE_HEADER_FONT));
            cell.setBackgroundColor(DARK_BLUE);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setPadding(6);
            table.addCell(cell);
        }

        for (int r = 0; r < rows.length; r++) {
            BaseColor bg = (r % 2 == 0) ? LIGHT_GRAY : WHITE;
            for (String cellText : rows[r]) {
                PdfPCell cell = new PdfPCell(new Phrase(cellText, TABLE_CELL_FONT));
                cell.setBackgroundColor(bg);
                cell.setPadding(5);
                table.addCell(cell);
            }
        }
        return table;
    }

    public void generate(String outputPath) throws DocumentException, IOException {
        Document document = new Document(PageSize.LETTER, 50, 50, 60, 50);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPath));

        // Page event for headers/footers
        writer.setPageEvent(new PdfPageEventHelper() {
            @Override
            public void onEndPage(PdfWriter w, Document doc) {
                PdfContentByte cb = w.getDirectContent();
                int pageNum = w.getPageNumber();

                // Header bar
                cb.setColorFill(DARK_BLUE);
                cb.rectangle(50, doc.top() + 15, doc.right() - 50 - doc.leftMargin(), 20);
                cb.fill();
                cb.beginText();
                cb.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA_BOLD, "Cp1252", false), 8);
                cb.setColorFill(WHITE);
                cb.showTextAligned(Element.ALIGN_LEFT, title, 55, doc.top() + 20, 0);
                String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("MMMM dd, yyyy"));
                cb.showTextAligned(Element.ALIGN_RIGHT, dateStr, doc.right() - 5, doc.top() + 20, 0);
                cb.endText();

                // Footer bar
                cb.setColorFill(DARK_BLUE);
                cb.rectangle(50, 25, doc.right() - 50 - doc.leftMargin(), 16);
                cb.fill();
                cb.beginText();
                cb.setFontAndSize(BaseFont.createFont(BaseFont.HELVETICA, "Cp1252", false), 7);
                cb.setColorFill(WHITE);
                cb.showTextAligned(Element.ALIGN_LEFT, "Author: " + author, 55, 30, 0);
                cb.showTextAligned(Element.ALIGN_CENTER, "Page " + pageNum,
                        (doc.right() + doc.leftMargin()) / 2, 30, 0);
                cb.showTextAligned(Element.ALIGN_RIGHT, "Generated with PDF Report Generator",
                        doc.right() - 5, 30, 0);
                cb.endText();
            }
        });

        document.open();

        // Cover page
        document.add(new Paragraph("\n\n\n\n\n\n"));
        Paragraph titlePara = new Paragraph(title, TITLE_FONT);
        titlePara.setAlignment(Element.ALIGN_CENTER);
        document.add(titlePara);

        String subtitle = "Prepared by " + author + " | "
                + LocalDate.now().format(DateTimeFormatter.ofPattern("MMMM yyyy"));
        Paragraph subPara = new Paragraph(subtitle, SUBTITLE_FONT);
        subPara.setAlignment(Element.ALIGN_CENTER);
        document.add(subPara);

        Paragraph descPara = new Paragraph(
                "This report provides a comprehensive analysis of organizational "
                + "performance metrics and strategic insights.", BODY_FONT);
        descPara.setAlignment(Element.ALIGN_CENTER);
        descPara.setSpacingBefore(15);
        document.add(descPara);
        document.newPage();

        // TOC page
        document.add(new Paragraph("Table of Contents", H1_FONT));
        document.add(new Paragraph(" "));
        // TOC filled later as placeholder
        document.newPage();

        // Section 1
        tocEntries.add(new String[]{"1. Executive Summary", "0"});
        document.add(new Paragraph("1. Executive Summary", H1_FONT));
        document.add(new Paragraph("This section provides a high-level overview of key findings. "
                + "Revenue increased by 15.3% year-over-year.", BODY_FONT));

        tocEntries.add(new String[]{"1.1 Key Performance Indicators", "1"});
        document.add(new Paragraph("1.1 Key Performance Indicators", H2_FONT));
        document.add(buildStyledTable(
                new String[]{"Metric", "Q1", "Q2", "Q3", "Q4", "YoY Change"},
                new String[][]{
                        {"Revenue ($M)", "12.4", "14.1", "15.8", "17.2", "+15.3%"},
                        {"Net Profit ($M)", "2.1", "2.5", "2.9", "3.4", "+22.1%"},
                        {"Customers (K)", "45.2", "48.7", "52.1", "56.8", "+12.4%"},
                        {"Satisfaction (%)", "87.3", "89.1", "91.5", "93.2", "+5.9pp"},
                        {"Employee Count", "342", "358", "371", "389", "+13.7%"}
                }));
        document.newPage();

        // Section 2
        tocEntries.add(new String[]{"2. Financial Analysis", "0"});
        document.add(new Paragraph("2. Financial Analysis", H1_FONT));

        Map<String, Double> revenueData = new LinkedHashMap<>();
        revenueData.put("Engineering", 18.5);
        revenueData.put("Sales", 24.3);
        revenueData.put("Marketing", 8.7);
        revenueData.put("Operations", 5.2);
        revenueData.put("Support", 3.8);
        byte[] barImg = createBarChartImage(revenueData, "Revenue by Department ($M)");
        Image barImage = Image.getInstance(barImg);
        barImage.scaleToFit(450, 230);
        barImage.setAlignment(Element.ALIGN_CENTER);
        document.add(barImage);

        tocEntries.add(new String[]{"2.1 Expense Breakdown", "1"});
        document.add(new Paragraph("2.1 Expense Breakdown", H2_FONT));

        Map<String, Double> expenseData = new LinkedHashMap<>();
        expenseData.put("Salaries", 42.0);
        expenseData.put("Infrastructure", 18.0);
        expenseData.put("Marketing", 15.0);
        expenseData.put("R&D", 12.0);
        expenseData.put("Operations", 8.0);
        expenseData.put("Other", 5.0);
        byte[] pieImg = createPieChartImage(expenseData, "Expense Distribution");
        Image pieImage = Image.getInstance(pieImg);
        pieImage.scaleToFit(380, 260);
        pieImage.setAlignment(Element.ALIGN_CENTER);
        document.add(pieImage);

        document.add(buildStyledTable(
                new String[]{"Category", "Budget ($M)", "Actual ($M)", "Variance"},
                new String[][]{
                        {"Salaries & Benefits", "18.5", "17.9", "-3.2%"},
                        {"Cloud Infrastructure", "6.2", "6.8", "+9.7%"},
                        {"Marketing Campaigns", "5.1", "4.7", "-7.8%"},
                        {"R&D", "4.8", "5.2", "+8.3%"}
                }));
        document.newPage();

        // Section 3
        tocEntries.add(new String[]{"3. Growth Trends", "0"});
        document.add(new Paragraph("3. Growth Trends", H1_FONT));

        double[] xData = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        Map<String, double[]> lineSeries = new LinkedHashMap<>();
        lineSeries.put("Revenue", new double[]{10.2, 10.8, 11.1, 12.4, 12.9, 13.5, 14.1, 14.8, 15.2, 15.8, 16.5, 17.2});
        lineSeries.put("Costs", new double[]{8.1, 8.3, 8.0, 8.5, 8.4, 8.6, 8.7, 8.5, 8.9, 8.8, 9.0, 9.1});
        lineSeries.put("Profit", new double[]{2.1, 2.5, 3.1, 3.9, 4.5, 4.9, 5.4, 6.3, 6.3, 7.0, 7.5, 8.1});

        byte[] lineImg = createLineChartImage(xData, lineSeries, "Monthly Financial Trends ($M)");
        Image lineImage = Image.getInstance(lineImg);
        lineImage.scaleToFit(450, 230);
        lineImage.setAlignment(Element.ALIGN_CENTER);
        document.add(lineImage);
        document.newPage();

        // Section 4
        tocEntries.add(new String[]{"4. Regional Performance", "0"});
        document.add(new Paragraph("4. Regional Performance", H1_FONT));
        document.add(buildStyledTable(
                new String[]{"Region", "Revenue ($M)", "Growth", "Share", "Customers"},
                new String[][]{
                        {"North America", "28.4", "+12.1%", "34.2%", "22,450"},
                        {"Europe", "19.7", "+18.5%", "23.7%", "15,820"},
                        {"Asia-Pacific", "15.3", "+25.3%", "18.4%", "12,100"},
                        {"Latin America", "8.9", "+31.2%", "10.7%", "7,240"},
                        {"Middle East", "5.6", "+14.8%", "6.7%", "4,180"},
                        {"Africa", "5.2", "+42.1%", "6.3%", "3,890"}
                }));
        document.newPage();

        // Section 5
        tocEntries.add(new String[]{"5. Conclusions & Recommendations", "0"});
        document.add(new Paragraph("5. Conclusions & Recommendations", H1_FONT));
        document.add(new Paragraph("Key recommendations:", BODY_FONT));

        com.lowagie.text.List recList = new com.lowagie.text.List(com.lowagie.text.List.ORDERED);
        recList.add(new ListItem("Increase investment in high-growth markets.", BODY_FONT));
        recList.add(new ListItem("Continue cost optimization through automation.", BODY_FONT));
        recList.add(new ListItem("Expand product portfolio.", BODY_FONT));
        recList.add(new ListItem("Invest in employee development.", BODY_FONT));
        recList.add(new ListItem("Establish a data analytics team.", BODY_FONT));
        document.add(recList);

        document.close();
        System.out.println("Report generated: " + outputPath);
    }

    public static void main(String[] args) throws DocumentException, IOException {
        String output = "report.pdf";
        String titleArg = "Annual Performance Report";
        String authorArg = "PDF Report Generator";

        for (int i = 0; i < args.length; i++) {
            switch (args[i]) {
                case "-o": case "--output": if (i + 1 < args.length) output = args[++i]; break;
                case "-t": case "--title": if (i + 1 < args.length) titleArg = args[++i]; break;
                case "-a": case "--author": if (i + 1 < args.length) authorArg = args[++i]; break;
                case "-h": case "--help":
                    System.out.println("Usage: PdfReportGenerator [-o output.pdf] [-t title] [-a author]");
                    return;
            }
        }

        PdfReportGenerator gen = new PdfReportGenerator(titleArg, authorArg);
        gen.generate(output);
    }
}