title: PDFBox 1.8.10: Fill and Sign Document, Filling again fails
body: <p>In my previous SO question <a href="https://stackoverflow.com/questions/32884607/pdfbox-1-8-10-fill-and-sign-pdf-produces-invalid-signatures">PDFBox 1.8.10: Fill and Sign PDF produces invalid signatures</a> 
  I explained, how I failed to fill and afterwards sign a PDF-Document, using PDFBox 1.8.10. 
  After this got sorted out with some kind help,  I now continue to work on the same topic. 
  Starting with <strong>doc_v2.pdf</strong> (links to the file are below!), I fill and sign it, resulting in
  <strong>doc_v2_fillsigned.pdf</strong>  (doing it in one go, saving it incrementally).
  Again I open the edited document (using again PDFBox) and try to fill another field.</p>
  
  <p>Then saving the document leads to the following stack trace:</p>
  
  <pre><code>    Exception in thread "main" java.lang.NullPointerException
          at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.calculateFontSize(PDAppearance.java:930)
          at org.apache.pdfbox.pdmodel.interactive.form.PDAppearance.setAppearanceValue(PDAppearance.java:359)
          at org.apache.pdfbox.pdmodel.interactive.form.PDVariableText.setValue(PDVariableText.java:131)
          at com.c10n.scalibur.ehealthdemo.examples.PdfEditor.fill(PdfEditor.java:100)
          at com.c10n.scalibur.ehealthdemo.examples.SignPdf_ProfileLayer.start(SignPdf_ProfileLayer.java:66)
          at com.c10n.scalibur.ehealthdemo.examples.SignPdf_ProfileLayer.main(SignPdf_ProfileLayer.java:28)
  </code></pre>
  
  <p>What I do in the failing fill run:</p>
  
  <pre><code>    File curentDocument new File("doc_v2_fillsigned.pdf);
      File newDocument = new File("doc_v2_fillsigned_filled.pdf);
  
      String fieldName ="New Emergency Contact";
      String value="test";
      PDDocument doc = null;
  
      try(FileOutputStream fos = new FileOutputStream(newDocument)){
  
          try(FileInputStream fis = new FileInputStream(currentDocument);){
              int c;
              while ((c = fis.read(buffer)) != -1) {
                  fos.write(buffer, 0, c);
              }
          }
  
          doc = PDDocument.load(currentDocument);
          PDDocumentCatalog catalog = doc.getDocumentCatalog();
  
          catalog.getCOSObject().setNeedToBeUpdate(true);
          catalog.getPages().getCOSObject().setNeedToBeUpdate(true);
  
          PDAcroForm form = catalog.getAcroForm();
  
          form.getCOSObject().setNeedToBeUpdate(true);
          form.getDefaultResources().getCOSObject().setNeedToBeUpdate(true);
  
          PDField field = form.getField(fieldName);
          field.setValue(value); // here the exception occurs.
  
          // What should happen afterwards:
          field.getCOSObject().setNeedToBeUpdate(true);
          field.getAcroForm().getCOSObject().setNeedToBeUpdate(true);
  
          ((COSDictionary) field.getDictionary().getDictionaryObject("AP")).getDictionaryObject("N").setNeedToBeUpdate(true);
  
          try(FileInputStream fis = new FileInputStream(newDocument)){
              doc.saveIncremental(fis, fos);
          }
      }finally{
          if(null != doc){
              doc.close();
              doc=null;
          }
      }
  </code></pre>
  
  <p><strong>Files:</strong></p>
  
  <p>the empty document: <a href="https://www.dropbox.com/s/xf5pb0ng8k9zd4i/doc_v2.pdf?dl=0" rel="nofollow noreferrer">https://www.dropbox.com/s/xf5pb0ng8k9zd4i/doc_v2.pdf?dl=0</a></p>
  
  <p>filled and signed instance: <a href="https://www.dropbox.com/s/s8295tfyjpe1l4l/doc_v2_fillsigned.pdf?dl=0" rel="nofollow noreferrer">https://www.dropbox.com/s/s8295tfyjpe1l4l/doc_v2_fillsigned.pdf?dl=0</a></p>
  
  <p>Again, any help to resolve this is welcome!</p>
  
  <p><strong>Update:</strong></p>
  
  <p>mkl asked in the comments for the code to create the fillsigned pdf. So far I learned, that only signing suffices, to let the fill-code above fail afterwards. 
  So here are some excepts from my signing code:</p>
  
  <pre><code>@Override
  public byte[] sign(InputStream data) throws SignatureException, IOException {
      CMSTypedDataInputStream input = new CMSTypedDataInputStream(data);
      try {
  
          CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
          InputStream in = new ByteArrayInputStream(certData);
  
          X509Certificate signCert = (X509Certificate)certFactory.generateCertificate(in);
  
          ContentSigner signer = new MyContentSigner(profile);
  
          SignerInfoGenerator i = new JcaSignerInfoGeneratorBuilder(
                  new JcaDigestCalculatorProviderBuilder().setProvider("BC").build())
  
          .build(signer,signCert);
  
          Store&lt;?&gt; certStore = new JcaCertStore(Collections.singletonList(signCert));
  
          CMSSignedDataGenerator cmsGen = new CMSSignedDataGenerator();
  
          cmsGen.addCertificates(certStore);
          cmsGen.addSignerInfoGenerator(i);
  
          CMSSignedData signedData = cmsGen.generate(input);
  
          byte[] result =signedData.getEncoded(); 
          return result;
      } catch (Exception e) {
          e.printStackTrace();
          throw new SignatureException(e);
      }
  }
  </code></pre>
  
  <p>this creates the signature, using BouncyCastle 1.52, the code is called from</p>
  
  <pre><code>public void sign(SignatureInterface signer, String signatureFieldName, int pageNumber, String location, String reason, boolean lock) throws IOException, SignatureException{
      PDSignature signature = new PDSignature();
      signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE); // default filter
      signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED); // for visible sigs!
  
      signature.setLocation(location);
      signature.setReason(reason);
  
      signature.setSignDate(Calendar.getInstance());
  
      SignatureOptions options = makeSignatureVisible(signature,signatureFieldName, pageNumber, lock );
  
      doc.addSignature(signature, signer, options);
  }
  </code></pre>
  
  <p>which uses the following method, to produce a visible signature in some signature field, adding a picture there and placing it correctly:</p>
  
  <pre><code>SignatureOptions makeSignatureVisible( PDSignature signature, String fieldName, int pageNumber, boolean lock) throws IOException{
      PDDocumentCatalog catalog = doc.getDocumentCatalog();
  
      catalog.getCOSObject().setNeedToBeUpdate(true);
      catalog.getPages().getCOSObject().setNeedToBeUpdate(true);
  
      PDAcroForm form = catalog.getAcroForm();
  
      form.getCOSObject().setNeedToBeUpdate(true);
      form.getDefaultResources().getCOSObject().setNeedToBeUpdate(true);
  
      PDSignatureField field = (PDSignatureField) form.getField(fieldName);
  
      field.setSignature(signature);      
      field.setReadonly(lock);
  
      FileInputStream image = new FileInputStream("MUniverse_Signature.jpg");
  
      PDVisibleSignDesigner visibleSig =  new PDVisibleSignDesigner(newDocument.getName(), image, 1);
  
      PDRectangle area = getFieldArea(field);
  
      float max_width = area.getWidth();
      float max_height = area.getHeight();
  
      float scale = 1;
  
      if(max_height &lt; visibleSig.getHeight()){
          scale = max_height / visibleSig.getHeight();
          System.out.println("scale: "+scale);
      }
  
      if(max_width &lt; scale*visibleSig.getWidth()){
          scale = max_width / visibleSig.getWidth();
          System.out.println("scale: "+scale);
      }
  
      float zoom = ((scale-1)*100);
  
      visibleSig.zoom(zoom);
  
      PDPage page = (PDPage) doc.getDocumentCatalog().getAllPages().get(pageNumber);
      visibleSig.coordinates(area.getLowerLeftX(),page.getMediaBox().getHeight()-area.getUpperRightY());
      visibleSig.signatureFieldName(fieldName);
  
      PDVisibleSigProperties signatureProperties = new PDVisibleSigProperties();
  
      signatureProperties.signerName("name").signerLocation("location").signatureReason("Security")
      .visualSignEnabled(true).setPdVisibleSignature(visibleSig).buildSignature();
  
      SignatureOptions options = new SignatureOptions();
      options.setVisualSignature(signatureProperties);
  
      return options;
  }
  </code></pre>
  
  <p>I suspect these fragment are no neccessary, and applying the signing examples, which come with PDFBox results in the same conflict, when trying to fill the pdf with incrementle saving afterwards.</p>
  
  <p>regards,</p>
  
  <p>daniel</p>