Skip to content
Advertisement

COSStream has been closed and cannot be read

I have next code in my project and time to time it falls with COSStream has been closed and cannot be read. Perhaps its enclosing PDDocument has been closed? It happens in different time and with different workload, so I want to fix it. Thanks in advance.

public void transferBankActPagesToPdfFile(List<PdfBankActPage> acts, HttpServletResponse response)
            throws IOException {
        try (PDDocument outPDDocument = new PDDocument()) {
            for (PdfBankActPage pdfBankActPage : acts) {
                String templateFilename = TEMPLATES_FOLDER + DELIMETER + pdfBankActPage.getPdfTemplateName();
                PDDocument templatePDDocument = PDDocument.load(readResource(templateFilename));
                PDPage pdPage = templatePDDocument.getPage(0);
                String fontTemplatePath = TEMPLATES_FOLDER + DELIMETER + FONT_TEMPLATE;
                PDDocument fontTemplatePdf = PDDocument.load(readResource(fontTemplatePath));
                PDPage fontTemplatePage = fontTemplatePdf.getPage(0);
                PDResources fontTemplateResources = fontTemplatePage.getResources();
                PDFont cyrillicFont = null;
                for (COSName cosName : fontTemplateResources.getFontNames()) {
                    if (cosName.getName().equals("F4")) {
                        cyrillicFont = fontTemplateResources.getFont(cosName);
                    }
                }
                outPDDocument.addPage(pdPage);
                PDPageContentStream contentStream = new PDPageContentStream(templatePDDocument, pdPage,
                        PDPageContentStream.AppendMode.APPEND, true, true);
                List<PdfTextLine> textLines = pdfBankActPage.getTextLines();
                if (textLines != null) {
                    for (PdfTextLine textLine : textLines) {
                        contentStream.setFont(cyrillicFont, textLine.getFontSize());
                        contentStream.beginText();
                        contentStream.newLineAtOffset(textLine.getOffsetX(), textLine.getOffsetY());
                        contentStream.showText(textLine.getText());
                        contentStream.endText();
                    }
                }
                contentStream.close();
            }
            response.setContentType(MediaType.APPLICATION_PDF_VALUE);
            outPDDocument.save(response.getOutputStream());
        }
    }

and here part that load resourse:

 private InputStream readResource(String resourceFilename) {
        InputStream inputStream = PdfBankActPagesToPdfFile.class.getResourceAsStream(resourceFilename);
        if (inputStream == null) {
            inputStream = PdfBankActPagesToPdfFile.class.getClassLoader().getResourceAsStream(resourceFilename);
        }
        return inputStream;
    }

Answer

You use streams from template documents (templatePDDocument, fontTemplatePdf) created anew and also given free for garbage collection in each loop iteration. Thus, some of these template documents may have been finalized by garbage collection before you call outPDDocument.save, causing the errors you observe.

If you keep this base architecture, you can prevent that those template documents are finalized prematurely by adding them all to some collection and clearing that collection only after calling outPDDocument.save.

Alternatively you can switch to cloning the template pages and using the clones instead of using the original template pages.

Advertisement