Voeg Barcode PDF Java toe – Ondertekenen & Verifiëren met GroupDocs
Als je een snelle, visuele manier nodig hebt om documenten te labelen voor interne workflows, is het toevoegen van een barcode aan een PDF in Java een perfecte oplossing. Met GroupDocs.Signature kun je barcode‑handtekeningen insluiten, verifiëren, zoeken, bijwerken en verwijderen zonder de overhead van volledige PKI‑gebaseerde digitale handtekeningen. Deze tutorial leidt je stap voor stap, van omgeving configuratie tot productie‑klare best practices.
Snelle antwoorden
- Welke bibliotheek voegt barcode toe aan PDF’s in Java? GroupDocs.Signature voor Java.
- Kan ik PDF, Word en afbeeldingen ondertekenen? Ja – de API ondersteunt meer dan 30 formaten.
- Heb ik een licentie nodig voor ontwikkeling? Een tijdelijke 30‑daagse licentie is gratis; een volledige licentie is vereist voor productie.
- Hoeveel regels code zijn nodig om een PDF te ondertekenen? Slechts twee regels: maak een
Signature‑object aan en roepsignaan. - Is barcode‑verificatie hoofdlettergevoelig? Ja – de tekst moet exact overeenkomen, inclusief hoofdletters en spaties.
Wat is add barcode pdf java?
add barcode pdf java verwijst naar het proces waarbij Java‑code wordt gebruikt om een barcode (zoals Code128, QR of Data Matrix) in een PDF‑bestand in te sluiten. Deze techniek biedt een machinaal leesbare tag die kan worden gescand of programmatisch geverifieerd, waardoor snelle documenttracking in interne systemen mogelijk wordt.
Waarom barcode‑handtekeningen gebruiken in plaats van volledige digitale handtekeningen?
Barcode‑handtekeningen zijn 30‑50 % sneller om te genereren en te verifiëren dan PKI‑gebaseerde digitale handtekeningen, en ze werken betrouwbaar na een print‑scan‑cyclus. Ze vereisen bovendien geen certificaatbeheer, waardoor ze ideaal zijn voor high‑volume, interne workflows waar cryptografisch bewijs niet verplicht is.
Voorvereisten
- Java Development Kit (JDK) 8+ – Java 11 of 17 wordt aanbevolen voor betere prestaties.
- IDE – IntelliJ IDEA of Eclipse (de voorbeelden gebruiken IntelliJ‑syntaxis).
- Build‑tool – Maven of Gradle voor afhankelijkheidsbeheer.
GroupDocs.Signature toevoegen aan je project
De eenvoudigste manier om te beginnen is de bibliotheek via je build‑tool toe te voegen. Zo doe je dat:
Maven‑gebruikers – Voeg dit toe aan je pom.xml:
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-signature</artifactId>
<version>23.12</version>
</dependency>
Gradle‑gebruikers – Voeg dit toe aan je build.gradle:
implementation 'com.groupdocs:groupdocs-signature:23.12'
Directe JAR‑download – Als je handmatige installatie verkiest, download de JAR van GroupDocs.Signature releases en voeg deze toe aan je classpath.
Je licentie regelen
GroupDocs.Signature is niet gratis voor productie, maar je hebt flexibele opties:
- Gratis proefversie – Download van de GroupDocs download‑pagina om functies te testen (evaluatiewatermerken worden toegevoegd).
- Tijdelijke licentie – Krijg 30 dagen volledige toegang via GroupDocs tijdelijke licentie‑pagina – perfect voor proof‑of‑concepts.
- Volledige licentie – Voor productie‑implementaties, bekijk de GroupDocs aankoopopties.
Pro tip: Begin met de tijdelijke licentie voor ontwikkeling; deze verwijdert watermerken zodra je overschakelt naar een permanente sleutel.
Snelle omgevingscontrole
Nadat je de afhankelijkheid hebt toegevoegd, voer een eenvoudige rooktest uit:
import com.groupdocs.signature.Signature;
public class SignatureTest {
public static void main(String[] args) {
try {
Signature signature = new Signature("test.pdf");
System.out.println("GroupDocs.Signature initialized successfully!");
signature.dispose();
} catch (Exception e) {
System.err.println("Setup issue: " + e.getMessage());
}
}
}
Als het programma zonder fouten draait, is je omgeving klaar. Bij problemen, controleer de JDK‑versie en de exacte bibliotheekversie die je hebt toegevoegd.
Wanneer barcode‑handtekeningen gebruiken
Barcode‑handtekeningen blinken uit in specifieke scenario’s:
- Interne document‑workflows – Volg facturen, inkooporders of memo’s door goedkeuringsketens.
- High‑volume verwerking – Onderteken duizenden documenten snel; barcode‑generatie is tot 2× sneller dan volledige digitale ondertekening.
- Print‑scan bruggen – Barcodes overleven de print‑scan‑cyclus, waardoor ze ideaal zijn voor hybride papier‑digitaal processen.
- Legacy‑systeemintegratie – Bestaande barcodescanners kunnen de tags lezen zonder extra software.
- Audit‑trails – Voeg transacties‑ID’s of tijdstempels in die auditors direct kunnen verifiëren.
Vermijd barcode‑handtekeningen voor juridische contracten, high‑security documenten of uitwisseling met externe partners waar PKI‑gebaseerde digitale handtekeningen vereist zijn.
GroupDocs.Signature voor Java configureren
Kernklassedefinitie
De Signature‑klasse is het toegangspunt voor alle onderteken‑, verificatie‑, zoek‑, update‑ en delete‑operaties in GroupDocs.Signature.
import com.groupdocs.signature.Signature;
Basisinitialisatie
Maak een Signature‑object dat naar het doelbestand wijst:
Signature signature = new Signature("path/to/your/document.pdf");
Belangrijke opmerkingen
- Paden kunnen absoluut of relatief zijn; gebruik
System.getProperty("user.home")voor platform‑onafhankelijke compatibiliteit. - GroupDocs ondersteunt 30+ invoer‑ en uitvoerformaten, waaronder PDF, DOCX, XLSX, PPTX en PNG.
- Maak altijd resources vrij met
signature.dispose()of een try‑with‑resources‑blok:
try (Signature signature = new Signature("path/to/your/document.pdf")) {
// Your signing operations here
} catch (Exception e) {
System.err.println("Error working with document: " + e.getMessage());
}
Nu ben je klaar om barcodes toe te voegen.
Hoe voeg ik een barcode toe aan een PDF in Java?
Laad de bron‑PDF met new Signature("input.pdf"), configureer een BarcodeSignature‑object (bijv. Code128 met de tekst “John Smith”), en roep sign aan om het ondertekende bestand te produceren – alles in drie beknopte code‑regels. Deze aanpak stelt je in staat een machinaal leesbare tag in te sluiten terwijl de oorspronkelijke lay‑out behouden blijft, en werkt voor elk ondersteund formaat, niet alleen PDF’s.
Stapsgewijze implementatie
1. Bestandspaden definiëren
Stel de locaties voor de bron‑ en outputbestanden in:
String filePath = "YOUR_DOCUMENT_DIRECTORY/sample.docx";
String outputFilePath = "YOUR_OUTPUT_DIRECTORY/signed_sample.docx";
2. De handtekening‑handler maken
Initialiseer de handler met het bron‑document:
Signature signature = new Signature(filePath);
3. Barcode‑opties configureren
Een BarcodeSignature‑object definieert de visuele en data‑eigenschappen van de barcode die moet worden ingebed. Stel het barcode‑type, de gecodeerde tekst, positie, grootte, kleur en optioneel een mens‑leesbaar lettertype in:
BarcodeSignOptions signOptions = new BarcodeSignOptions("John Smith", BarcodeTypes.Code128);
signOptions.setVerticalAlignment(VerticalAlignment.Top);
signOptions.setHorizontalAlignment(HorizontalAlignment.Center);
signOptions.setWidth(100);
signOptions.setHeight(40);
signOptions.setMargin(new java.awt.Rectangle(20, 20, 0, 0));
signOptions.setForeColor(Color.RED);
SignatureFont signatureFont = new SignatureFont();
signatureFont.setSize(12);
signatureFont.setFamilyName("Comic Sans MS");
signOptions.setFont(signatureFont);
Pro tip: Als de gecodeerde string langer is dan 20 tekens, vergroot dan de barcode‑breedte om scan‑fouten te voorkomen.
4. De handtekening toepassen
Voer de onderteken‑operatie uit en genereer het output‑bestand:
signature.sign(outputFilePath, signOptions);
5. Praktijkvoorbeeld
In een factuur‑goedkeuringssysteem kun je de medewerker‑ID van de goedkeurder en een tijdstempel embedden:
String invoiceId = "INV-2025-0042";
String approver = "john.smith@company.com";
String timestamp = LocalDateTime.now().toString();
// Combine into barcode data
String barcodeData = invoiceId + "|" + approver + "|" + timestamp;
BarcodeSignOptions signOptions = new BarcodeSignOptions(barcodeData, BarcodeTypes.QR);
signOptions.setVerticalAlignment(VerticalAlignment.Bottom);
signOptions.setHorizontalAlignment(HorizontalAlignment.Right);
signature.sign(outputFilePath, signOptions);
Het resulterende PDF‑bestand bevat nu een scanbare barcode die alle benodigde goedkeuringsmetadata codeert.
Hoe kan ik een barcode‑handtekening verifiëren in een Java‑document?
De methode Signature.verify controleert een document op overeenkomende barcode‑handtekeningen op basis van de opgegeven opties, en retourneert een boolean die aangeeft of de verwachte barcode aanwezig is. Verificatie is nuttig voor geautomatiseerde workflows waarbij je moet bevestigen dat een document door de juiste partij is verwerkt voordat verdere acties worden ondernomen.
Verificatiestappen
1. Het ondertekende document laden
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
2. Verificatiecriteria instellen
Definieer de exacte tekst, barcode‑formaat en paginanummer die je verwacht:
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setAllPages(false); // Only check the first page
verifyOptions.setPageNumber(1);
verifyOptions.setEncodeType(BarcodeTypes.Code128);
verifyOptions.setText("John Smith");
3. Verificatie uitvoeren
Voer de controle uit en verwerk het resultaat:
boolean isValid = signature.verify(verifyOptions) != null;
if (isValid) {
System.out.println("Document signature verified successfully!");
} else {
System.out.println("Warning: Signature verification failed!");
}
Veelvoorkomend patroon: Om simpelweg te bevestigen dat een barcode van een bepaald type bestaat, laat je de setText‑filter weg:
BarcodeVerifyOptions flexibleOptions = new BarcodeVerifyOptions();
flexibleOptions.setAllPages(true);
flexibleOptions.setEncodeType(BarcodeTypes.Code128);
// No setText() call = accept any text with this barcode type
boolean hasAnySignature = signature.verify(flexibleOptions) != null;
Of verifieer alleen het barcode‑formaat zonder de inhoud te controleren:
BarcodeVerifyOptions formatOnly = new BarcodeVerifyOptions();
formatOnly.setEncodeType(BarcodeTypes.QR);
// Confirms a QR code exists, regardless of content
Waarschuwing: Verificatie is hoofdletter‑ en spatie‑gevoelig; trim en normaliseer data altijd vóór ondertekening.
Hoe zoek ik naar barcode‑handtekeningen in een document?
De methode Signature.search scant een document op barcode‑handtekeningen die overeenkomen met de opgegeven BarcodeSearchOptions, en retourneert een collectie met locatie, paginanummer en gecodeerde waarde van elke barcode. Deze functionaliteit maakt bulk‑extractie van metadata mogelijk zonder elk bestand handmatig te openen.
Zoek‑workflow
1. Zoekinitialisatie
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
2. Zoekparameters configureren
Specificeer paginabereik, barcode‑type of tekstfilters:
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true); // Search the entire document
Optioneel kun je de zoekopdracht beperken om de prestaties te verbeteren:
BarcodeSearchOptions narrowSearch = new BarcodeSearchOptions();
narrowSearch.setAllPages(false);
narrowSearch.setPageNumber(1); // Only search page 1
narrowSearch.setEncodeType(BarcodeTypes.Code128); // Only find Code128 barcodes
3. Zoekopdracht uitvoeren
java.util.List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
System.out.println("Found " + signatures.size() + " barcode signature(s)");
for (BarcodeSignature bcSignature : signatures) {
System.out.println("Barcode Type: " + bcSignature.getEncodeType().getTypeName());
System.out.println("Text: " + bcSignature.getText());
System.out.println("Position: (" + bcSignature.getLeft() + ", " + bcSignature.getTop() + ")");
System.out.println("Size: " + bcSignature.getWidth() + "x" + bcSignature.getHeight());
System.out.println("---");
}
4. Voorbeeld data‑extractie
Haal goedkeuringsdata op van elke barcode in een factuurbatch:
List<BarcodeSignature> foundSignatures = signature.search(BarcodeSignature.class, searchOptions);
for (BarcodeSignature sig : foundSignatures) {
String barcodeData = sig.getText();
// Parse your custom format (remember our invoice example?)
String[] parts = barcodeData.split("\\|");
if (parts.length == 3) {
String invoiceId = parts[0];
String approver = parts[1];
String timestamp = parts[2];
System.out.println("Invoice " + invoiceId + " approved by " + approver + " at " + timestamp);
}
}
Prestatie‑tip: Voor documenten met meer dan 100 pagina’s, beperk de zoekopdracht altijd tot de pagina’s die daadwerkelijk barcodes bevatten; dit kan de runtime met tot 70 % verkorten.
Hoe kan ik een bestaande barcode‑handtekening bijwerken?
De methode Signature.update wijzigt visuele attributen van een bestaande barcode‑handtekening — zoals positie, grootte of kleur — terwijl de originele gecodeerde data behouden blijft. Handig wanneer lay‑out‑aanpassingen nodig zijn nadat het document al is ondertekend.
Update‑procedure
1. Handtekeningen vinden die moeten worden bijgewerkt
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true);
List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
2. Gewenste eigenschappen wijzigen
List<BarcodeSignature> signaturesToUpdate = new ArrayList<>();
if (!signatures.isEmpty()) {
BarcodeSignature bcSignature = signatures.get(0); // Update the first found signature
// Move it 100px right and 100px down
bcSignature.setLeft(bcSignature.getLeft() + 100);
bcSignature.setTop(bcSignature.getTop() + 100);
// Make it bigger
bcSignature.setWidth(200);
bcSignature.setHeight(50);
signaturesToUpdate.add(bcSignature);
}
Je kunt meerdere attributen tegelijk aanpassen:
bcSignature.setLeft(50);
bcSignature.setTop(50);
bcSignature.setWidth(150);
bcSignature.setHeight(45);
// Note: You can't change the encoded text or barcode type with update
// For that, you'd need to delete and re-sign
3. Wijzigingen opslaan
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
signature.update(outputStream, signaturesToUpdate);
// If you want to save to a file instead:
// signature.update("path/to/updated_document.docx", signaturesToUpdate);
4. Praktijkscenario
Verplaats alle handtekeningen om overlapping met een nieuw toegevoegd bedrijfslogo te voorkomen:
List<BarcodeSignature> allSignatures = signature.search(BarcodeSignature.class, searchOptions);
List<BarcodeSignature> toUpdate = new ArrayList<>();
for (BarcodeSignature sig : allSignatures) {
// Move all signatures down by 50px to clear space for new logo
if (sig.getTop() < 100) {
sig.setTop(sig.getTop() + 50);
toUpdate.add(sig);
}
}
if (!toUpdate.isEmpty()) {
signature.update(outputStream, toUpdate);
System.out.println("Repositioned " + toUpdate.size() + " signature(s)");
}
Beperking: Het wijzigen van de gecodeerde tekst vereist verwijdering en een nieuwe handtekeninginvoeging.
Hoe verwijder ik barcode‑handtekeningen uit een document?
De methode Signature.delete verwijdert permanent geselecteerde barcode‑handtekeningen uit een document, waardoor zowel het visuele element als de gecodeerde data verdwijnen. Gebruik deze operatie bij het opschonen van test‑handtekeningen of wanneer een barcode niet langer relevant is.
Verwijderingsstappen
1. Handtekeningen lokaliseren
Signature signature = new Signature("YOUR_OUTPUT_DIRECTORY/signed_sample.docx");
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true);
List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
2. Geselecteerde handtekeningen verwijderen
List<BarcodeSignature> signaturesToDelete = new ArrayList<>();
// Delete all Code128 signatures (for example)
for (BarcodeSignature sig : signatures) {
if (sig.getEncodeType().equals(BarcodeTypes.Code128)) {
signaturesToDelete.add(sig);
}
}
if (!signaturesToDelete.isEmpty()) {
boolean result = signature.delete(signaturesToDelete);
if (result) {
System.out.println("Successfully deleted " + signaturesToDelete.size() + " signature(s)");
} else {
System.err.println("Failed to delete signatures");
}
}
3. Voorbeeld voor conditionele verwijdering
Verwijder alleen barcodes ouder dan een specifieke tijdstempel (ervan uitgaande dat de tijdstempel deel uitmaakt van de gecodeerde tekst):
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(30);
List<BarcodeSignature> outdatedSignatures = new ArrayList<>();
for (BarcodeSignature sig : signatures) {
try {
String text = sig.getText();
// Assuming format like "data|timestamp"
String[] parts = text.split("\\|");
if (parts.length > 1) {
LocalDateTime sigDate = LocalDateTime.parse(parts[1]);
if (sigDate.isBefore(cutoffDate)) {
outdatedSignatures.add(sig);
}
}
} catch (Exception e) {
// Skip signatures that don't match our format
continue;
}
}
if (!outdatedSignatures.isEmpty()) {
signature.delete(outdatedSignatures);
System.out.println("Removed " + outdatedSignatures.size() + " outdated signature(s)");
}
Voorzichtig: Verwijderen kan niet ongedaan worden gemaakt; werk altijd met een kopie van productiebestanden tijdens tests.
4. Batch‑verwijderingspatroon
Ruim test‑handtekeningen op vóór een release:
// Remove all signatures containing "TEST" in their text
List<BarcodeSignature> testSignatures = signatures.stream()
.filter(sig -> sig.getText().toUpperCase().contains("TEST"))
.collect(Collectors.toList());
if (!testSignatures.isEmpty()) {
signature.delete(testSignatures);
System.out.println("Cleaned up " + testSignatures.size() + " test signature(s)");
}
Barcode‑typen: Een praktische gids
De juiste barcode kiezen beïnvloedt scan‑betrouwbaarheid, datacapaciteit en printercompatibiliteit.
Code128 (Meest gangbare keuze)
- Wanneer te gebruiken: Alfanumerieke data, hoge dichtheid, afgedrukte documenten.
- Voordelen: Compact, werkt met standaardscanners, print duidelijk op kleine formaten.
- Nadelen: Beperkt tot ASCII, minder fout‑tolerant dan 2‑D‑codes.
Voorbeeld:
BarcodeSignOptions code128 = new BarcodeSignOptions("INV-2025-042", BarcodeTypes.Code128);
QR‑code (Beste voor mobiel)
- Wanneer te gebruiken: Mobiel scannen, grote datalast (URL’s, JSON, enz.), documenten die beschadigd kunnen raken.
- Voordelen: Tot 4 000 tekens, ingebouwde foutcorrectie, smartphone‑vriendelijk.
- Nadelen: Grotere visuele voetafdruk, vereist hogere resolutie voor kleine formaten.
Voorbeeld:
String jsonData = "{\"invoice\":\"INV-042\",\"amount\":1500.00,\"approver\":\"john@company.com\"}";
BarcodeSignOptions qrCode = new BarcodeSignOptions(jsonData, BarcodeTypes.QR);
Code39 (Oude betrouwbare)
- Wanneer te gebruiken: Legacy‑scanneromgevingen, behoefte aan mens‑leesbare tekst.
- Voordelen: Brede legacy‑ondersteuning, eenvoudig formaat, geen checksum vereist.
- Nadelen: Lage datadichtheid, beperkt teken‑set, neemt meer ruimte in beslag.
Data Matrix (Compacte krachtpatser)
- Wanneer te gebruiken: Zeer beperkte ruimte, markering van kleine objecten, hoge‑dichtheid data.
- Voordelen: Zeer compact, sterke foutcorrectie, werkt op gebogen oppervlakken.
- Nadelen: Vereist hoge‑kwaliteit printen, minder gangbare scannerondersteuning.
Snelle vergelijking
| Barcode‑type | Datacapaciteit | Beste voor | Typische grootte |
|---|---|---|---|
| Code128 | ~100 tekens | Algemeen labelen | Klein |
| QR‑code | ~4 000 tekens | Mobiel scannen, rijke data | Middel |
| Code39 | ~43 tekens | Legacy‑hardware | Groot |
| Data Matrix | ~3 000 tekens | Zeer kleine ruimtes, industriële tags | Zeer klein |
Aanbeveling: Begin met Code128 voor eenvoudige ID’s. Schakel over naar QR wanneer je URL’s of grotere payloads moet embedden. Gebruik Code39 alleen voor legacy‑integraties.
Veelvoorkomende problemen & oplossingen
Probleem: “Barcode niet gevonden tijdens verificatie”
Symptomen: Verificatie geeft false terwijl de barcode zichtbaar is.
Typische oorzaken
- Hoofdletter‑mismatch (bijv. “John Smith” vs. “john smith”).
- Extra spaties in de gecodeerde tekst.
- Verkeerd barcode‑type opgegeven in de verificatie‑opties.
- Zoeken op verkeerd paginanummer.
Oplossing: Normaliseer de tekst vóór ondertekening en verificatie, en zorg dat setEncodeType overeenkomt met het oorspronkelijke type.
// Always normalize your data
String signatureText = originalText.trim().toLowerCase();
// When signing:
BarcodeSignOptions signOptions = new BarcodeSignOptions(signatureText, BarcodeTypes.Code128);
// When verifying:
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setText(signatureText); // Use the same normalized text
verifyOptions.setEncodeType(BarcodeTypes.Code128);
Probleem: “Barcode is onscherp of onleesbaar”
Symptomen: Afgedrukte barcodes kunnen niet worden gescand.
Oorzaken
- Barcode‑afmetingen te klein voor de gecodeerde data.
- Printerinstellingen met lage resolutie.
- Onvoldoende contrast tussen barcode‑kleur en achtergrond.
Oplossing: Vergroot de barcode‑breedte/hoogte, gebruik hoog‑contrast kleuren (zwart op wit), en stel de printer‑DPI in op minimaal 300 dpi.
// Increase size for longer strings
int dataLength = barcodeText.length();
int minWidth = Math.max(100, dataLength * 10); // 10px per character minimum
BarcodeSignOptions signOptions = new BarcodeSignOptions(barcodeText, BarcodeTypes.Code128);
signOptions.setWidth(minWidth);
signOptions.setHeight(60); // Taller = easier to scan
// Use high-contrast colors
signOptions.setForeColor(Color.BLACK); // Black on white is most reliable
signOptions.setBackColor(Color.WHITE);
Probleem: “OutOfMemoryError bij grote documenten”
Symptomen: Applicatie crasht bij verwerking van PDF’s met honderden pagina’s.
Oorzaak: De bibliotheek laadt het volledige document in het geheugen.
Oplossing: Schakel streaming‑modus in en verwerk pagina’s incrementeel.
// Process pages in batches instead of all at once
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(false);
List<BarcodeSignature> allSignatures = new ArrayList<>();
for (int page = 1; page <= totalPages; page++) {
searchOptions.setPageNumber(page);
List<BarcodeSignature> pageSignatures = signature.search(BarcodeSignature.class, searchOptions);
allSignatures.addAll(pageSignatures);
// Process and clear as you go
if (page % 10 == 0) {
System.gc(); // Suggest garbage collection every 10 pages
}
}
Probleem: “Handtekening‑positie inconsistent tussen documenttypen”
Symptomen: Barcodes verschijnen op verschillende locaties bij ondertekening van PDF’s versus Word‑documenten.
Oorzaak: PDF gebruikt een oorsprong links‑onder, terwijl Word een oorsprong links‑boven hanteert.
Oplossing: Detecteer het documenttype en pas de juiste coördinatentransformatie toe.
// Use relative positioning instead of absolute
signOptions.setVerticalAlignment(VerticalAlignment.Bottom);
signOptions.setHorizontalAlignment(HorizontalAlignment.Right);
// Then use margins for fine-tuning
Padding margin = new Padding();
margin.setRight(50); // 50px from right edge
margin.setBottom(50); // 50px from bottom
signOptions.setMargin(margin);
// This works consistently across PDF, DOCX, XLSX, etc.
Probleem: “Bijgewerkte handtekeningen verliezen opmaak”
Symptomen: Na een update verandert de kleur of het lettertype van de barcode onverwacht.
Oorzaak: Niet alle visuele eigenschappen worden bewaard tijdens een update‑operatie.
Oplossing: Pas eventuele visuele instellingen opnieuw toe na de update‑aanroep.
// When updating, explicitly set all visual properties
bcSignature.setLeft(newLeft);
bcSignature.setTop(newTop);
bcSignature.setWidth(originalWidth); // Don't forget these!
bcSignature.setHeight(originalHeight);
// Note: Color and font can't be updated - you'd need to delete and re-sign
Best practices voor productie
Prestatie‑optimalisatie
- Signature‑instanties hergebruiken – Maak één
Signature‑object per document aan en hergebruik dit voor meerdere operaties.
// Bad - Creates new instance each time
public void processDocument(String path) {
Signature sig1 = new Signature(path);
sig1.search(/* ... */);
Signature sig2 = new Signature(path); // Unnecessary reload
sig2.verify(/* ... */);
}
// Good - Reuse the same instance
public void processDocument(String path) {
try (Signature signature = new Signature(path)) {
signature.search(/* ... */);
signature.verify(/* ... */);
signature.update(/* ... */);
}
}
- Zoek alleen specifieke pagina’s – Beperk het paginabereik tot waar barcodes verwacht worden.
// Slow for 100+ page documents
BarcodeSearchOptions slowSearch = new BarcodeSearchOptions();
slowSearch.setAllPages(true);
// Fast - only check where signatures actually are
BarcodeSearchOptions fastSearch = new BarcodeSearchOptions();
fastSearch.setAllPages(false);
fastSearch.setPageNumber(1); // Only check cover page
- Kies het eenvoudigste barcode‑type – Simpler barcodes genereren sneller; gebruik QR of Data Matrix alleen wanneer de extra capaciteit echt nodig is.
// Overkill for simple IDs
BarcodeSignOptions slow = new BarcodeSignOptions("12345", BarcodeTypes.QR);
// Faster and more appropriate
BarcodeSignOptions fast = new BarcodeSignOptions("12345", BarcodeTypes.Code128);
Beveiligingsoverwegingen
- Encodeer nooit gevoelige persoonsgegevens – Barcodes zijn gemakkelijk leesbaar; vermijd PII zoals BSN’s of wachtwoorden.
// Bad - exposes sensitive data
String barcodeData = "SSN:123-45-6789|Password:hunter2";
// Good - use reference IDs
String barcodeData = "USER-REF-7721X"; // Look up sensitive data server-side
- Server‑side validatie – Vertrouw nooit alleen op client‑side verificatie; verifieer altijd opnieuw op een vertrouwde backend.
// Client scans barcode and extracts "APPROVED-BY-ADMIN"
// Always verify server-side:
public boolean verifyApproval(String documentId, String scannedData) {
// Load document from secure storage
Signature signature = new Signature(getSecureDocument(documentId));
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setText(scannedData);
boolean isValid = signature.verify(verifyOptions) != null;
// Also check against your database
boolean isInDatabase = checkApprovalDatabase(documentId, scannedData);
return isValid && isInDatabase;
}
- Voeg tijdstempels toe – Neem een tijdstempel op in de barcode‑payload om replay‑aanvallen te voorkomen.
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
String timestamp = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS).toString();
String barcodeData = "APPROVAL|" + userId + "|" + timestamp;
// When verifying, check the timestamp isn't too old
public boolean isSignatureRecent(String barcodeData, int maxAgeHours) {
String[] parts = barcodeData.split("\\|");
if (parts.length < 3) return false;
LocalDateTime signatureTime = LocalDateTime.parse(parts[2]);
LocalDateTime now = LocalDateTime.now();
long hoursSince = ChronoUnit.HOURS.between(signatureTime, now);
return hoursSince <= maxAgeHours;
}
Foutafhandelingspatronen
- Altijd try‑with‑resources gebruiken om ervoor te zorgen dat
Signature‑objecten worden vrijgegeven.
try (Signature signature = new Signature(documentPath)) {
// Your operations here
signature.sign(outputPath, signOptions);
} catch (Exception e) {
logger.error("Failed to sign document: " + documentPath, e);
throw new DocumentSigningException("Could not process document", e);
}
- Bestands‑toegang valideren vóór ondertekening.
public void signDocument(String inputPath, String outputPath) {
File inputFile = new File(inputPath);
if (!inputFile.exists()) {
throw new IllegalArgumentException("Input file not found: " + inputPath);
}
if (!inputFile.canRead()) {
throw new SecurityException("Cannot read input file: " + inputPath);
}
File outputDir = new File(outputPath).getParentFile();
if (outputDir != null && !outputDir.exists()) {
outputDir.mkdirs();
}
try (Signature signature = new Signature(inputPath)) {
signature.sign(outputPath, signOptions);
}
}
- Synchroniseer toegang als meerdere threads mogelijk hetzelfde bestand bewerken.
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.ConcurrentHashMap;
public class SignatureManager {
private final ConcurrentHashMap<String, ReentrantLock> documentLocks = new ConcurrentHashMap<>();
public void signDocument(String documentPath, BarcodeSignOptions options) {
ReentrantLock lock = documentLocks.computeIfAbsent(documentPath, k -> new ReentrantLock());
lock.lock();
try (Signature signature = new Signature(documentPath)) {
signature.sign(documentPath + ".signed", options);
} finally {
lock.unlock();
}
}
}
Je implementatie testen
Unit‑test‑template
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import static org.junit.jupiter.api.Assertions.*;
public class BarcodeSignatureTest {
@TempDir
Path tempDir;
@Test
public void testSignAndVerify() throws Exception {
// Setup
String testDoc = "test-document.pdf";
String outputDoc = tempDir.resolve("signed-test.pdf").toString();
String testData = "TEST-USER-12345";
// Sign
try (Signature signature = new Signature(testDoc)) {
BarcodeSignOptions signOptions = new BarcodeSignOptions(testData, BarcodeTypes.Code128);
signature.sign(outputDoc, signOptions);
}
// Verify
try (Signature signature = new Signature(outputDoc)) {
BarcodeVerifyOptions verifyOptions = new BarcodeVerifyOptions();
verifyOptions.setText(testData);
verifyOptions.setEncodeType(BarcodeTypes.Code128);
boolean isValid = signature.verify(verifyOptions) != null;
assertTrue(isValid, "Signature should be valid");
}
}
@Test
public void testSearchFindsSignature() throws Exception {
String signedDoc = "signed-document.pdf";
try (Signature signature = new Signature(signedDoc)) {
BarcodeSearchOptions searchOptions = new BarcodeSearchOptions();
searchOptions.setAllPages(true);
List<BarcodeSignature> signatures = signature.search(BarcodeSignature.class, searchOptions);
assertFalse(signatures.isEmpty(), "Should find at least one signature");
assertEquals("TEST-USER-12345", signatures.get(0).getText());
}
}
}
Integratie‑checklist
- ✅ Test alle ondersteunde formaten (PDF, DOCX, XLSX, PPTX, PNG).
- ✅ Verifieer dat barcodes een print‑scan‑cyclus overleven.
- ✅ Stress‑test met maximale datalengtes.
- ✅ Bevestig positionering op A4, Letter en aangepaste paginagroottes.
- ✅ Voer gelijktijdige ondertekening uit op meerdere documenten.
- ✅ Monitor geheugengebruik voor documenten > 500 pagina’s.
- ✅ Zorg dat barcodescanners de output betrouwbaar lezen.
Logging en monitoring
Voeg betekenisvolle logs toe rond elke operatie:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class DocumentSigningService {
private static final Logger logger = LoggerFactory.getLogger(DocumentSigningService.class);
public void signDocument(String docPath, String barcodeData) {
logger.info("Starting signature process for document: {}", docPath);
logger.debug("Barcode data length: {} characters", barcodeData.length());
try (Signature signature = new Signature(docPath)) {
BarcodeSignOptions options = new BarcodeSignOptions(barcodeData, BarcodeTypes.Code128);
long startTime = System.currentTimeMillis();
signature.sign(docPath + ".signed", options);
long duration = System.currentTimeMillis() - startTime;
logger.info("Successfully signed document in {}ms", duration);
} catch (Exception e) {
logger.error("Failed to sign document: {}", docPath, e);
throw new RuntimeException("Signature operation failed", e);
}
}
}
Volg belangrijke metrics zoals verwerkingstijd, geheugengebruik en foutpercentages:
// Track success/failure rates
metricsService.incrementCounter("signature.sign.success");
metricsService.incrementCounter("signature.verify.failure");
// Track performance
metricsService.recordTimer("signature.sign.duration", duration);
// Track document sizes
metricsService.recordHistogram("signature.document.pages", pageCount);
Pro‑tips uit de praktijk
Batch‑verwerkingsstrategie
Bij verwerking van honderden bestanden, werk in batches en rapporteer voortgang:
public void signBatch(List<String> documents, String barcodePrefix) {
int total = documents.size();
int completed = 0;
int failed = 0;
for (String docPath : documents) {
try {
String barcodeData = barcodePrefix + "-" + UUID.randomUUID().toString();
signDocument(docPath, barcodeData);
completed++;
if (completed % 10 == 0) {
logger.info("Progress: {}/{} documents signed", completed, total);
}
} catch (Exception e) {
failed++;
logger.warn("Failed to sign: {}", docPath, e);
}
}
logger.info("Batch complete: {} succeeded, {} failed", completed, failed);
}
Configuratie externaliseren
Sla barcode‑instellingen (type, grootte, kleur) op in een properties‑bestand voor eenvoudige afstemming zonder hercompilatie:
public class BarcodeConfig {
private int defaultWidth = 100;
private int defaultHeight = 40;
private String defaultBarcodeType = "Code128";
private String defaultColor = "BLACK";
// Load from properties file or environment variables
public BarcodeConfig() {
this.defaultWidth = Integer.parseInt(
System.getProperty("barcode.width", "100")
);
// ... load other properties
}
public BarcodeSignOptions createDefaultOptions(String text) {
BarcodeSignOptions options = new BarcodeSignOptions(text, getBarcodeType());
options.setWidth(defaultWidth);
options.setHeight(defaultHeight);
options.setForeColor(getColor());
return options;
}
}
Gestandaardiseerde barcode‑payload
Gebruik een gescheiden formaat zoals EMPID|TIMESTAMP|DOCID om parsing eenvoudig en consistent te houden:
public class BarcodeDataBuilder {
private String userId;
private String action;
private LocalDateTime timestamp;
private String documentId;
public BarcodeDataBuilder setUserId(String userId) {
this.userId = userId;
return this;
}
public BarcodeDataBuilder setAction(String action) {
this.action = action;
return this;
}
public BarcodeDataBuilder setDocumentId(String documentId) {
this.documentId = documentId;
return this;
}
public String build() {
this.timestamp = LocalDateTime.now();
// Format: VERSION|USER|ACTION|DOC_ID|TIMESTAMP|CHECKSUM
String data = String.join("|",
"v1",
userId,
action,
documentId,
timestamp.toString()
);
// Add simple checksum
int checksum = data.hashCode();
return data + "|" + checksum;
}
public static ParsedBarcodeData parse(String barcodeData) {
String[] parts = barcodeData.split("\\|");
if (parts.length != 6 || !parts[0].equals("v1")) {
throw new IllegalArgumentException("Invalid barcode format");
}
return new ParsedBarcodeData(parts[1], parts[2], parts[3],
LocalDateTime.parse(parts[4]));
}
}
// Usage:
String barcodeData = new BarcodeDataBuilder()
.setUserId("john.smith")
.setAction("APPROVED")
.setDocumentId("INV-2025-042")
.build();
Documenttype automatisch detecteren
Pas barcode‑afmetingen aan op basis van of het doel PDF, Word of een afbeelding is:
public BarcodeSignOptions getOptimalOptions(String documentPath, String text) {
String extension = documentPath.substring(documentPath.lastIndexOf(".") + 1).toLowerCase();
BarcodeSignOptions options = new BarcodeSignOptions(text, BarcodeTypes.Code128);
switch (extension) {
case "pdf":
// PDFs can handle larger, detailed barcodes
options.setWidth(150);
options.setHeight(50);
break;
case "docx":
case "doc":
// Word docs need compact signatures that don't disrupt flow
options.setWidth(100);
options.setHeight(35);
options.setVerticalAlignment(VerticalAlignment.Bottom);
break;
case "xlsx":
case "xls":
// Excel needs signatures that don't obscure data
options.setWidth(80);
options.setHeight(30);
options.setHorizontalAlignment(HorizontalAlignment.Right);
break;
default:
// Safe defaults
options.setWidth(100);
options.setHeight(40);
}
return options;
}
Aanvullende bronnen
- GroupDocs.Signature documentatie – Volledige API‑gids en voorbeeldcode.
- GroupDocs support forum – Community‑hulp en probleemoplossing.
- API‑referentie – Gedetailleerde methodesignatures en parameterbeschrijvingen.
Veelgestelde vragen
V: Kan ik GroupDocs.Signature gebruiken met Java 17?
A: Ja – de bibliotheek is volledig compatibel met JDK 8, 11 en 17.
V: Overleeft de barcode een print‑scan‑cyclus?
A: Wanneer je Code128 of QR gebruikt met voldoende grootte en contrast, blijft de barcode scanbaar na afdrukken en scannen.
V: Hoeveel barcodes kan één document bevatten?
A: Er is geen harde limiet; voor optimale prestaties houd je het aantal onder 200 per document.
V: Is een licentie vereist voor ontwikkel‑builds?
A: Een tijdelijke licentie verwijdert evaluatiewatermerken; een volledige licentie is verplicht voor elke productie‑implementatie.
V: Kan ik wachtwoord‑beveiligde PDF’s ondertekenen?
A: Ja – geef het wachtwoord door bij het aanmaken van het Signature‑object; de API ontgrendelt het bestand intern.
Laatst bijgewerkt: 2026-07-15
Getest met: GroupDocs.Signature 23.9 voor Java
Auteur: GroupDocs