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