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);
}
}