It is deterministic.  Running against the same data reproduces the exact
error.

You are correct.  When I pass null for the root outline node, and pass null
in the recursive calls to prevent bookmarking from occuring, the issue does
go away.

I am fairly new to iText, so I am a little confused by your question about
the bookmarks being off by a single page.  To create the bookmark
PdfDestination I call getVerticalPosition(true), I thought that the result
is just the y coordinate of the current vertical position within the entire
document.  What do you mean by off by a single page?

-- Jason


> On Tue, Apr 12, 2011 at 8:24 PM, Mark Storer <[email protected]> wrote:
>
    You can call getPageReference(Integer.MAX_INT) any time you like, though
>> I don't recommend it.  Any time getPageReference is called for a page
>> greater than the last page when you call close, you get this exception.  You
>> can create all your page references in advance via getPageReference(), but
>> they'd better have pages to go with them when you call close().
>>
>> This looks an awful lot like an off-by-one error.  Are your bookmarks off
>> by a single page?
>>
>> Is it deterministic?  Does running your app over the same data reproduce
>> the issue time and again?
>>
>> I suspect that if you disable your outline code, this problem will Go
>> Away, though I can't point my finger at anything in particular to back that
>> up.
>>
>> One final trick you could try would be to change
>> PdfWriter.getPageReference(int) such that it logged the desired page along
>> with a stack trace:
>>    try {
>>      throw new RuntimeException("Requested page " + page);
>>    } catch (RuntimeException re) {
>>      re.printStackTrace(myPrintWriter);
>>    }
>>
>> You really only need to track the largest request.  If the error /is/
>> deterministic, you can just log calls to getPageReference() when page
>> ==1356568.  There could be more than one.
>>
>> --Mark Storer
>>   Senior Software Engineer
>>   Cardiff.com
>>
>> import legalese.Disclaimer;
>> Disclaimer<Cardiff> DisCard = null;
>>
>>
>>
>>  ------------------------------
>> *From:* Jason DeLawder [mailto:[email protected]]
>> *Sent:* Tuesday, April 12, 2011 1:43 PM
>> *To:* [email protected]
>> *Subject:* [iText-questions] RuntimeExcpetion - Size of pageReferences
>> and currentPageNumber -1 Are Not Equal
>>
>>   I have written an application that exports hundreds of PDF documents
>> from a content repository and then merges those documents into a single PDF
>> document.  Any PDFs that are either encrypted or corrupted are supplied to
>> the requester as attachements to the merged PDF (ideally these shouldn't
>> exist but they do get into the system).
>>
>> The domain object graph corresponding to the folders and documents in the
>> content repository is recursively processed and the Document domain object
>> has a reference to the file path where the document was exported.  Once all
>> of the files have been merged and bookmarks created, the PdfDocument is
>> closed, but I am receiving the following RuntimeException
>>
>> 11/04/12 15:28:31 Caused by: java.lang.RuntimeException: The page 135658
>> was requested but the document has only 135657 pages.
>> 11/04/12 15:28:31  at
>> com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1165)
>> 11/04/12 15:28:31  at
>> com.itextpdf.text.pdf.PdfCopy.close(PdfCopy.java:488)
>> 11/04/12 15:28:31  at
>> com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:780)
>> 11/04/12 15:28:31  at com.itextpdf.text.Document.close(Document.java:409)
>> 11/04/12 15:28:31  at
>> ebackend.service.pdf.ITextPDFService.append(ITextPDFService.java:249)
>> 11/04/12 15:28:31  at
>> ebackend.ejb.EbackendMessageBean.processRedactRequest(EbackendMessageBean.java:432)
>>
>> This exception only seems to occur when there is a large number of
>> documents being merged.  I have debugged over and over, but have been unable
>> to determine why this error occurrs. The code is below, the methods of
>> interest are append() and mergePDFs() and the merging begins with
>> append().
>>
>> I would appreciate it if someone could take a quick look at the code to
>> see if I am doing something incorrectly.  If the code looks correct, what
>> conditions could yield this result?  What conditions could cause PdfWriter's
>> pageReferences list to be larger than the currentPageNumber - 1 ?
>>
>> Thanks.
>>
>> public class ITextPDFService {
>>
>>        private static final Logger logger =
>> Logger.getLogger(ITextPDFService.class);
>>
>>         /**
>>          * Loads the CoverPage pdf file and completes the embedded
>> AcroForm.  After
>>          * completing the AcroForm the file is wrapped in a  domain object
>>          * so that it can be merged.  The page is not added to  in any
>> way.
>>          *
>>          * @param info  The CoverLetterInfo contains the summary data
>> needed to create
>>          * the title/cover page.
>>          *
>>          * @param exportFolder  The folder where all of the exported
>> documents are located.
>>          *
>>          * @return Document that wraps the physical Cover Page file, null
>> if the
>>          *         cover page could not be created.
>>          *
>>          * @throws IOException
>>          * @throws DocumentException
>>          */
>>         private Document getCoverPage(CoverLetterInfo info, String
>> exportFolder) {
>>
>>             if(!exportFolder.endsWith("\\")){
>>                 exportFolder+= "\\";
>>             }
>>
>>             PdfStamper stamper      = null;
>>             Document d    = null;
>>             String coverLetterPath  = exportFolder + "coverletter.pdf";
>>
>>             try {
>>               InputStream is =
>> getClass().getClassLoader().getResourceAsStream("coverletter.pdf");
>>               PdfReader reader  = new PdfReader(is);
>>               stamper           = new PdfStamper(reader, new
>> FileOutputStream(coverLetterPath));
>>
>>               AcroFields form   = stamper.getAcroFields();
>>               form.setField("title", info.getLabelTitle());
>>               form.setField("user", info.getLabelUser());
>>               form.setField("folder", info.getLabelFolder());
>>               form.setField("company", info.getLabelCompany());
>>               form.setField("product", info.getLabelProduct());
>>               form.setField("summary", info.getLabelSummary());
>>               form.setField("dateRequested",
>> info.getLabelDateRequested());
>>               form.setField("datePrinted", info.getLabelDatePrinted());
>>               form.setField("note", info.getLabelNote());
>>               stamper.setFormFlattening(true);
>>               d = new Document();
>>               d.setDownloadedPath(coverLetterPath);
>>
>>             } catch(Exception e) {
>>               logger.error("Error creating the cover page for " +
>> FilenameUtils.getName(exportFolder) ,e);
>>               e.printStackTrace();
>>
>>             } finally {
>>               try {stamper.close();}catch(Exception e){
>> logger.error("Unable to close PdfStamper",e); }
>>             }
>>
>>             return d;
>>         }
>>
>>
>>        /**
>>        *
>>        * @param Folder
>>        * @param exportFolder
>>        * @param destFilePath
>>        * @param info
>>        * @param doPageStamps
>>        * @return
>>        * @throws Exception
>>        */
>>        public List<String> append(Folder Folder, String exportFolder,
>> String destFilePath, CoverLetterInfo info, boolean doPageStamps) {
>>
>>            List<String> errorDescriptions = new
>> ArrayList<String>();
>>            // get the total number of pages for all documents in the
>> export folder
>>            int totalPageNum = countPages(exportFolder);
>>            info.setTotalPageNumber(String.valueOf(totalPageNum));
>>
>>            logger.info("Total Page Count: " + (totalPageNum + 1)); //
>> including the cover page
>>
>>            Document document = null;
>>            PdfCopy copy = null;
>>            try {
>>
>>              document = new Document();
>>              copy = new PdfCopy(document, new
>> FileOutputStream(destFilePath));
>>              document.open();
>>
>>              // create and add the cover page
>>               try {
>>                 Document coverLetter = getCoverPage(info, exportFolder);
>>                 if(coverLetter != null)
>>                 {
>>                    PdfReader reader = new
>> PdfReader(coverLetter.getDownloadedPath());
>>                    PdfImportedPage page = copy.getImportedPage(reader,1);
>>                    copy.addPage(page);
>>                 }
>>               }
>>               catch(Exception e)
>>               {
>>                 logger.error(e);
>>                 errorDescriptions.add(COVER_LETTER_ERROR);
>>               }
>>
>>              // merge pdfs
>>              logger.info("Begin merge of " + Folder.getName() + " folder
>> contents.");
>>              long startTime = new Date().getTime();
>>              errorDescriptions.addAll(
>>                                       mergePDFs(copy,
>>                                                copy.getRootOutline(),
>>                                                Folder,
>>                                                doPageStamps,
>>                                                totalPageNum)
>>                                       );
>>              long endTime = new Date().getTime();
>>              logger.info("Merge of " + Folder + " folder contents
>> completed.  Time: " + ((endTime - startTime) / 1000) + " seconds");
>>            } catch(Exception e){
>>              logger.error("Unrecoverable error occurred creating base
>> Document for folder " + Folder, e);
>>              throw new EbackendServiceException(e);
>>
>>            } finally {
>>               if(document != null)
>>                 document.close();
>>            }
>>
>>            return errorDescriptions;
>>        }
>>
>>        /**
>>        *
>>        * @param copy
>>        * @param outline
>>        * @param Folder
>>        * @param doPageStamps
>>        * @param totalPages
>>        * @return
>>        */
>>        public List<String> mergePDFs(PdfCopy copy, PdfOutline outline,
>> Folder Folder, boolean doPageStamps, int totalPages) {
>>           List<String> errorDescriptions = new ArrayList<String>();
>>
>>           PdfImportedPage page  = null;
>>           Font font = new Font(Font.FontFamily.HELVETICA,12.0f,Font.BOLD);
>>
>>
>>           List children = Folder.getChildren();
>>           for(Object o : children)
>>           {
>>             if(o instanceof Folder)
>>             {
>>               Folder f = (Folder) o;
>>               if(f.getChildren().size() > 0 &&
>> f.hasDocumentDescendents()){
>>                 PdfOutline subOutline = new PdfOutline(outline,
>>                                                        new
>> PdfDestination(PdfDestination.FITH,copy.getVerticalPosition(true)),
>>                                                        f.getName(),
>>                                                        true);
>>                 subOutline.setStyle(Font.BOLD);
>>                 logger.debug("Merging contents of folder: " +
>> f.getName());
>>                 errorDescriptions.addAll(
>> mergePDF(copy,subOutline,f,doPageStamps, totalPages) );
>>               }
>>             }
>>             else if(o instanceof Document)
>>             {
>>               float startVerticalPosition =
>> copy.getVerticalPosition(true);
>>               int startPage = copy.getCurrentPageNumber();
>>
>>               String filePath = ( (Document)o).getDownloadedPath();
>>               logger.debug("Merging document: " + filePath);
>>               PdfReader reader = null;
>>               PdfCopy.PageStamp stamp = null;
>>               try
>>               {
>>                 reader = new PdfReader(new
>> RandomAccessFileOrArray(filePath),null);
>>                 int pageCount = reader.getNumberOfPages();
>>
>>                 for(int i = 1; i <= pageCount; i++){
>>                   page = copy.getImportedPage(reader,i);
>>
>>                   if(doPageStamps){
>>                     stamp = copy.createPageStamp(page);
>>                     ColumnText.showTextAligned(
>>                                 stamp.getOverContent(),
>>                                 Element.ALIGN_LEFT,
>>                                 new Phrase(String.format("Page %d of %d",
>> copy.getCurrentPageNumber() - 1, totalPages ),font),
>>                                 30.0f, 20.0f, 0.0f);
>>                     stamp.alterContents();
>>                   }
>>                   copy.addPage(page);
>>                 }
>>
>>               }
>>               catch(Exception e) // could be encrypted or corrupted, the
>> latter results in NPE within iText
>>               {
>>                 e.printStackTrace();
>>                 String fileBaseName = FilenameUtils.getName(filePath);
>>                 logger.error("Error encountered with document " +
>> fileBaseName + " creating error page ",e);
>>
>>                 // create an error page
>>                 InputStream is =
>> getErrorPageInputStream(fileBaseName,e.getMessage());
>>                 PdfReader reader2 = null;
>>                 try
>>                 {
>>                   reader2 = new PdfReader(is);
>>                   page = copy.getImportedPage(reader2,1);
>>                   if(doPageStamps)
>>                   {
>>                     stamp = copy.createPageStamp(page);
>>                     ColumnText.showTextAligned(
>>                                 stamp.getOverContent(),
>>                                 Element.ALIGN_LEFT,
>>                                 new Phrase(String.format("Page %d of %d",
>> copy.getCurrentPageNumber() - 1, totalPages ),font),
>>                                 30.0f, 20.0f, 0.0f);
>>                     stamp.alterContents();
>>                   }
>>                   copy.addPage(page);
>>                   copy.addFileAttachment(
>> ((Document)o).getName(),null,filePath,fileBaseName );
>>
>> errorDescriptions.add(String.format(MERGING_ERROR,((Document)o).getId(),e.getMessage()));
>>                 }
>>                 catch(Exception e2)
>>                 {
>>                   e2.printStackTrace();
>>                   logger.error("Issue creating error page for document " +
>> fileBaseName,e2);
>>                 }
>>                 finally
>>                 {
>>                   try {is.close(); } catch(Exception
>> e3){logger.error("Unable to close error page InputStream",e3);}
>>                 }
>>
>>               }
>>               finally
>>               {
>>                 /* based on iText source, I think this should result in an
>>                 IndexOutOfBoundsException if the page counts do not match,
>> but it does not */
>>                 int endingPage = copy.getCurrentPageNumber();
>>                 try {
>>                   copy.getPageReference(--endingPage);
>>                 }catch(Exception re){
>>                   logger.error("Page counts are off after adding " +
>> ((Document)o).getName() + ": " + ((Document)o).getId());
>>                 }
>>
>>                 // Create a bookmark for the imported document
>>                 if(endingPage > startPage)
>>                 {
>>                   new PdfOutline(outline,
>>                                  new
>> PdfDestination(PdfDestination.FITH,startVerticalPosition),
>>                                 ((Document)o).getName(),
>>                                 true);
>>                 }
>>               }
>>
>>             }
>>
>>           }
>>
>>           return errorDescriptions;
>>
>>       }
>> }
>>
>>
>>
>> ------------------------------------------------------------------------------
>> Forrester Wave Report - Recovery time is now measured in hours and minutes
>> not days. Key insights are discussed in the 2010 Forrester Wave Report as
>> part of an in-depth evaluation of disaster recovery service providers.
>> Forrester found the best-in-class provider in terms of services and
>> vision.
>> Read this report now!  http://p.sf.net/sfu/ibm-webcastpromo
>>
>> _______________________________________________
>> iText-questions mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/itext-questions
>>
>> iText(R) is a registered trademark of 1T3XT BVBA.
>> Many questions posted to this list can (and will) be answered with a
>> reference to the iText book: http://www.itextpdf.com/book/
>> Please check the keywords list before you ask for examples:
>> http://itextpdf.com/themes/keywords.php
>>
>>
>
------------------------------------------------------------------------------
Benefiting from Server Virtualization: Beyond Initial Workload 
Consolidation -- Increasing the use of server virtualization is a top
priority.Virtualization can reduce costs, simplify management, and improve 
application availability and disaster protection. Learn more about boosting 
the value of server virtualization. http://p.sf.net/sfu/vmware-sfdev2dev
_______________________________________________
iText-questions mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/itext-questions

iText(R) is a registered trademark of 1T3XT BVBA.
Many questions posted to this list can (and will) be answered with a reference 
to the iText book: http://www.itextpdf.com/book/
Please check the keywords list before you ask for examples: 
http://itextpdf.com/themes/keywords.php

Reply via email to