I am creating a Table using PDF Box API. When i try to run my code i get Null Pointer Exception. What I am doing is I am setting properties like color border width etc. of the table at different levels i.e. At Cell level, row level, table level.
Here Row, Cell, Table are different classes.
It means that if a border width is set at cell level it will be used at that cell only, if this property is set at row level then it will set border width of whole row where cell border width property is not being used, and same for table level.
Priority: Cell>Row>Table
But my code does is when the value is not set at cell level using setter, so the value will be obviously 0 (In case of primitive type). and if it is 0 then it will get value from row level. Same in the case of row.
But I am getting Null Pointer Exception when I try to get value that is inherited from row. and indirectly from table. And also getting Null Pointer exception when i try to get get Row because it is returned null.
Firstly I tried to solve Null Pointer Exception using if loop. But result is still same.
Error Message :
Exception in thread "main" java.lang.NullPointerException
at main.Cell.getBorderWidth(Cell.java:66)
at main.CreateTable.createSampleDocument(CreateTable.java:54)
at main.CreateTable.main(CreateTable.java:16)
I am providing little part of code.
Table Class
public class Table {
private List<Row> rows = new LinkedList<>();
private float borderWidth = 0.2f;
private Table(final List<Row> rows) {
this.rows = rows;
}
public List<Row> getRows() {
return rows;
}
public float getTableWidth() {
return tableWidth;
}
public void setTableWidth(final float tableWidth) {
this.tableWidth = tableWidth;
}
public static class TableBuilder {
private final List<Row> rows = new LinkedList<>();
private Table table = new Table(rows, columns);
public TableBuilder addRow(Row row) {
row.setTable(table);
rows.add(row);
return this;
}
public TableBuilder setTableWidth(final float tableWidth) {
this.tableWidth = tableWidth;
this.table.setTableWidth(tableWidth);
return this;
}
public Table build() {
return table;
}
}
}
Row Class
public class Row {
private Table table;
private final List<Cell> cells;
private float borderWidth;
private Row(final List<Cell> cells) {
super();
this.cells = cells;
}
public List<Cell> getCells() {
return this.cells;
}
public Table getTable() {
return table;
}
void setTable(final Table table) {
this.table = table;
}
public float getBorderWidth() {
if(borderWidth == 0) {
System.out.println(getTable().getBorderWidth());
borderWidth = getTable().getBorderWidth();
}
return borderWidth;
}
public void setBorderWidth(float borderWidth) {
this.borderWidth = borderWidth;
}
public static class RowBuilder {
private final List<Cell> cells = new LinkedList<>();
Row row = new Row(cells);
public RowBuilder add(final Cell cell) {
cell.setRow(row);
cells.add(cell);
return this;
}
public RowBuilder setAllPadding(float allPadding) {
//this.allPadding = Optional.of(allPadding);
this.row.setAllPadding(allPadding);
return this;
}
public RowBuilder setBorderWidth(float borderWidth) {
/*this.borderWidth = Optional.of(borderWidth);
this.borderWidth.ifPresent(row::setBorderWidth);*/
this.row.setBorderWidth(borderWidth);
return this;
}
public Row build() {
return row;
}
}
}
Cell Class
public class Cell {
private Row row;
private final String text;
private float borderWidth; //To be seen afterwards
private Cell(Object object) {
this.text = String.valueOf(object);
}
public static Cell addText(Object object) {
System.out.println(String.valueOf(object));
return new Cell(object);
}
public String getText() {
return text;
}
public Row getRow() {
return row;
}
public void setRow(final Row row) {
this.row = row;
}
public float getBorderWidth() {
//Optional<Float> optBorderWidth = Optional.ofNullable(borderWidth);
//return optBorderWidth.orElse(getRow().getBorderWidth());
if(borderWidth == 0) {
borderWidth = getRow().getTable().getBorderWidth();
}
return borderWidth;
}
public Cell setBorderWidth(float borderWidth) {
this.borderWidth = borderWidth;
return this;
}
}
Edit
I just forgot to tell how this value are being used and set in memory.
Here is code
public class CreateTable {
public static void main (String[] args) throws Exception {
new CreateTable().createSampleDocument();
}
public void createSampleDocument() throws Exception {
final Object[][] tableData = {
{"ent",0.8, 0.5},
{"AV",144, 51.7},
{"Scc",0.1, 0.5}
};
TableBuilder tableBuilder = new TableBuilder()
.setBorderWidth(0.2f)
tableBuilder.addRow(new RowBuilder()
.add(Cell.addText("P").withAllBorders().setBorderColor(Color.BLUE).setLineSpacing(2))
.add(Cell.addText("S").withAllBorders())
.add(Cell.addText("D").withAllBorders())
.setBorderColor(Color.RED).setLineSpacing(1)
.build());
final PDDocument document = new PDDocument();
final PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);
final PDPageContentStream contentStream = new PDPageContentStream(document, page);
(new TableDrawer(contentStream, tableBuilder.build(), 300, 300)).draw();
contentStream.close();
document.save("C:\\Users\\sa\\Desktop\\table_pdf.pdf");
document.close();
}
}
Null Pointer Exception being caught at
Inside Cell class (because getRow() method is returning null)
public float getBorderWidth() {
//Optional<Float> optBorderWidth = Optional.ofNullable(borderWidth);
//return optBorderWidth.orElse(getRow().getBorderWidth());
if(borderWidth == 0) {
borderWidth = getRow().getTable().getBorderWidth();
}
return borderWidth;
}