/
Example (Java)
Example (Java)
The whole project may be fetched as a zip or tape archive.
The code in the listing ViewThenSignAPdfWithPad may be used to view
and then to sign a PDF document with a StepOver signature pad such as the duraSign Pad Brilliance.
It uses code from the listing Common below. A resulting signed document is attached here.
ViewThenSignAPdfWithPad.java
package com.so.net.example; import static com.so.net.DeviceApi.*; import com.so.net.SignApi; import static com.so.net.SignApi.Behaviour.*; import static com.so.net.SignApi.Pdf.*; import static com.so.net.example.Common.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; public class ViewThenSignAPdfWithPad { public static void main(String[] args) throws Exception { // This requires // .NET5 with hostfxr, // libgdiplus on Linux and MacOS, // the PDF service, // and the native SignAPI. SignApi.load(); // To connect to a pad on the remote computer "ThinClient" // Communication.useTCP(java.net.InetAddress.getByName("ThinClient"), 8888); // Search for signature device. final List<Device.Name> devices = enumerateDevices(Filter.StepOver); if (devices.isEmpty()) { System.out.println("Exit because no device was found."); return; } // Select the first device. Device.Name firstDevice = devices.get(0); setDevice(firstDevice); // See https://www.stepoverinfo.net/confluence/display/NETDEVAPI/Driver+XML+certificate setTheDriverXmlCertificate(Paths.get("DriverXmlCertificate.xml")); // Loads a PDF document from the file system. byte[] theDocument = Files.readAllBytes(Paths.get("TheDocument.pdf")); loadPdf(theDocument); // View the document on the pad SignApi.viewDocument(0, Zoom.Level.FitWidth, true); // wait until the start-signing-button is clicked // with a timeout of 10 minutes. waitForStartSignButton(600); // Performs an example signature with hardcoded // signature field position, signer info and signing behaviour. exampleSign(); // If the device shall no longer show the document. // setCustomerLogoMode(); // Download and save the signed document. byte[] signedDocument = downloadPdf(); Files.write(Paths.get("SignedDocument.pdf"), signedDocument); // Frees unmanaged resources. close(); } }
The code in the listing ViewAPdfWithPad displays document pages and prints button clicks.
ViewAPdfWithPad
package com.so.net.example; import static com.so.net.DeviceApi.*; import com.so.net.SignApi; import static com.so.net.SignApi.Pdf.*; import static com.so.net.example.Common.*; import static java.lang.Math.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.Optional; public class ViewAPdfWithPad { public static void main(String[] args) throws Exception { // This requires // .NET5 with hostfxr, // libgdiplus on Linux and MacOS, // the PDF service, // and the native SignAPI. SignApi.load(); final List<Device.Name> devices = enumerateDevices(Filter.StepOver); if (devices.isEmpty()) { System.out.println("Exit because no device was found."); return; } // Select the first device. Device.Name firstDevice = devices.get(0); setDevice(firstDevice); // Loads a PDF document from the file system. byte[] theDocument = Files.readAllBytes(Paths.get("TheDocument.pdf")); loadPdf(theDocument); // View the document on the pad // wait and print button clicks // and stop if the start signature button was clicked // or stop if no button is clicked for more than 10 minutes. showAndEnableAllButtonsInTheDocViewMode(); printButtonClicksInDocViewMode(600, 0); // Frees unmanaged resources. close(); } static void printButtonClicksInDocViewMode(int timeout, int page) { int numberOfPages = getNumberOfPages().orElse(0); final int pageInRange = max(0, min(numberOfPages - 1, page)); renderPage(pageInRange, 96) .ifPresent(pageImage -> DocumentViewing.start(pageImage, 1 + pageInRange, numberOfPages)); Optional<Button.Kind> buttonKind; try { buttonKind = waitForButton(timeout); } catch (InterruptedException ex) { return; } if (buttonKind.isPresent()) { Button.Kind kind = buttonKind.get(); printButton(kind); int nextPage = pageInRange; if (Button.Kind.Next == kind) { nextPage++; } else if (Button.Kind.Prev == kind) { nextPage--; } else if (Button.Kind.StartSignature == kind) { System.out.println("Good bye."); return; } printButtonClicksInDocViewMode(timeout, nextPage); } } static void printButton(Button.Kind buttonKind) { System.out.println("Button " + buttonKind.toString() + " was clicked."); } }
Common functions.
Common.java with exampleSign.
package com.so.net.example; import com.so.net.DeviceApi; import com.so.net.DeviceApi.*; import com.so.net.SignApi; import static com.so.net.SignApi.Pdf.*; import java.awt.Color; import java.util.Optional; import static com.so.net.SignApi.*; import com.so.net.SignApi.Behaviour; import static java.lang.Math.*; import java.nio.file.Path; public class Common { static class ClickedButton { Optional<Button.Kind> kind; } static Optional<Button.Kind> waitForButton(int timeoutSeconds) throws InterruptedException { ClickedButton obj = new ClickedButton(); DeviceApi.Button.setCallback(e -> { obj.kind = Optional.of(e.kind); notify(obj); }); wait(obj, timeoutSeconds); return obj.kind; } static void waitForStartSignButton(int timeoutSeconds) throws InterruptedException { Object obj = new Object(); DeviceApi.Button.setCallback(e -> { if (DeviceApi.Button.Kind.StartSignature == e.kind) { notify(obj); } }); wait(obj, timeoutSeconds); } static void wait(Object obj, int timeoutSeconds) throws InterruptedException { synchronized (obj) { obj.wait(timeoutSeconds * 1000); } } static void notify(Object obj) { synchronized (obj) { obj.notifyAll(); } } static boolean exampleSign() { Behaviour behaviour = Behaviour.Builder.getDefault() .signInDocument(Behaviour.DocSign.Rectangle.Builder // The rectangle should be at least 40mm wide and 30mm high. // and place the signature rectangle on the device display // with a distance of 10mm to the lower and the left display edge. .fromBottomLeft(10, 10, 40, 30) // The document shall be shown on the pad while signing .withColor(Color.LIGHT_GRAY) // The rectangle shall be highlighted by a red border .withBorderColor(Color.RED) // which shall be 5 dots wide. .withBorderWidth(5)) .build().get(); // Choose a field name, field position and signature info. FieldName fieldName = FieldName.of(null); // Choose the position of the new signature field. int page = 0; FieldPosition pageDim = getPageDimensions().get(page); // The default length unit is inch/72. double width = 4 * 72; //4 inches wide double height = 2 * 72; //2 inches high double row0 = max(pageDim.getHeight() / 2 - height / 2, 0); double column0 = max(pageDim.getWidth() / 2 - width / 2, 0); double row1 = min(row0 + height / 2, pageDim.getHeight()); double column1 = min(column0 + width / 2, pageDim.getWidth()); FieldPosition fieldPosition = FieldPosition.of(row0, column0, row1, column1, page); // Adds a signature field with the given field name and position. addSignatureField(fieldName, fieldPosition); // This queries for the signature field just added. SignatureField signatureField = getSignatureField(fieldName).get(); // A signature field can have these entries. // They are not mandatory. Pass an empty string or null to skip a field. final String name = "Signer's name."; final String reason = "Reason for signing."; final String location = "The location."; final String contactInfo = "The contact info."; SignatureInfo signatureInfo = SignatureInfo.of(name, reason, location, contactInfo); // Signs this signature field with the selected pad. return sign(signatureField, signatureInfo, behaviour); } static Optional<SignApi.Pdf.SignatureField> getSignatureField(SignApi.Pdf.FieldName fieldName) { return getAcroFormFields().stream() .filter(field -> fieldName.equals(field.getFieldName())) .filter(field -> field instanceof SignApi.Pdf.SignatureField) .map(field -> (SignApi.Pdf.SignatureField) field) .findFirst(); } static void setTheDriverXmlCertificate(Path certPath) { boolean fileExists = certPath.toFile().exists(); if (!fileExists) { System.out.println(certPath.toAbsolutePath().toString() + " does not exist."); } boolean success = DeviceApi.DriverXmlCertificate.set(certPath); if (!success) { System.out.println("Failed to set the driver XML certificate."); } } static void showAndEnableAllButtonsInTheDocViewMode() { // The device can show document pages in the DocView mode. DeviceApi.Button.Bar.get(DeviceApi.Button.Bar.Mode.DocView) .ifPresent(bar -> { bar.configs.forEach(Common::showAndEnable); bar.set(); }); } static void showAndEnable(Button.Config buttonConfig) { buttonConfig.setEnabled(true); buttonConfig.setVisible(true); } }
The POM of the example project.
Example pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.so</groupId> <artifactId>net-example</artifactId> <version>0.0.2</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <repositories> <!-- https://www.stepoverinfo.net/confluence/display/NETSIGNAPI/Install+with+Maven --> <repository> <id>nexus-stepover-maven-public</id> <url>https://nexus.stepover.de:8043/repository/maven-public/</url> </repository> </repositories> <dependencies> <dependency> <groupId>com.so</groupId> <artifactId>net</artifactId> <version>1.0.0</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.so.net.example.ViewThenSignAPdfWithPad</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> </project>
, multiple selections available,
Related content
Overview - API
Overview - API
Read with this
How to (Java)
How to (Java)
More like this
2. How to start
2. How to start
More like this
Java interface
Java interface
Read with this