Java client library for the Draftable document comparison API
A thin Java client for the Draftable API which wraps all available endpoints and handles authentication and signing.
See the full API documentation for an introduction to the API, usage notes, and other reference material.
import com.draftable.api.client.Comparisons;
import com.draftable.api.client.Comparisons.Side;
import com.draftable.api.client.Comparison;
Comparisons comparisons = new Comparisons("<yourAccountId>", "<yourAuthToken>");
Comparison comparison = comparisons.createComparison(
Side.create("https://api.draftable.com/static/test-documents/code-of-conduct/left.rtf", "rtf"),
Side.create("https://api.draftable.com/static/test-documents/code-of-conduct/right.pdf", "pdf")
);
System.out.println(String.format("Comparison created: %s", comparison));
// Generate a signed viewer URL to access the private comparison. The expiry
// time defaults to 30 minutes if the validUntil parameter is not provided.
String viewerURL = comparisons.signedViewerURL(comparison.identifier, Duration.ofMinutes(30), false);
System.out.println(String.format("Viewer URL (expires in 30 mins): %s", viewerURL));
Method calls immediately validate parameters. Parameter validation failures throw IllegalArgumentException
.
Java exceptions are categorised as either checked or unchecked. In this library:
IOException
.In practice, while you may elect to handle unchecked exceptions, it should be possible to write your application such that they’re never thrown.
Async
.CompletableFuture
, which when awaited, will complete successfully or throw an exception.The API client class, Comparisons
, is thread-safe. If close()
is called prematurely future requests will re-open the underlying HTTP clients.
The package provides a module, com.draftable.api.client
, with which a Comparisons
instance can be created for your API account.
Comparisons
provides methods to manage the comparisons for your API account and return individual Comparison
objects.
Creating a Comparisons
instance differs slightly based on the API endpoint being used:
import com.draftable.api.client.Comparisons;
import com.draftable.api.client.Comparison;
// Draftable API (default endpoint)
Comparisons comparisons = new Comparisons(
"<yourAccountId>", // Replace with your API credentials from:
"<yourAuthToken>" // https://api.draftable.com/account/credentials
);
// Draftable API regional endpoint or Self-hosted
Comparisons comparisons = new Comparisons(
"<yourAccountId>", // Replace with your API credentials from the regional
"<yourAuthToken>", // Draftable API endpoint or your Self-hosted container
'https://draftable.example.com/api/v1' // Replace with the endpoint URL
);
The Comparisons
instance can be closed by calling close()
.
For API Self-hosted you may need to suppress TLS certificate validation if the server is using a self-signed certificate (the default).
getAllComparisons()
List<Comparison>
of all your comparisons, ordered from newest to oldest. This is potentially an expensive operation.getComparison(String identifier)
Comparison
or raises a Comparisons.ComparisonNotFoundException
exception if the specified comparison identifier does not exist.Comparison
objects have the following getter methods:
getIdentifier(): String
getLeft(): Comparison.Side
/ getRight(): Comparison.Side
getFileType(): String
getSourceURL(): String
null
getDisplayName(): String
null
getIsPublic(): boolean
getCreationTime(): Instant
getExpiryTime(): Instant
null
getReady(): boolean
If a Comparison
is ready (i.e. it has been processed) the following additional getter methods are meaningful:
getReadyTime(): Instant
getFailed(): Boolean
getErrorMessage(): String
(only present if failed
)
String identifier = "<identifier>";
try {
Comparison comparison = comparisons.getComparison(identifier);
System.out.println(String.format(
"Comparison '%s' (%s) is %s.",
identifier,
comparison.getIsPublic() ? "public" : "private",
comparison.getReady() ? "ready" : "not ready"
));
if (comparison.getReady()) {
System.out.println(String.format(
"The comparison took %s seconds.",
comparison.getReadyTime().getEpochSecond() - comparison.getCreationTime().getEpochSecond()
));
if (comparison.getFailed()) {
System.out.println(String.format(
"The comparison failed with error: %s",
comparison.getErrorMessage()
));
}
}
} catch (Comparisons.ComparisonNotFoundException ex) {
System.out.println(String.format("Comparison '%s' does not exist.", identifier));
}
deleteComparison(String identifier)
Comparisons.ComparisonNotFoundException
exception if no such comparison exists.
List<Comparison> allComparisons = comparisons.getAllComparisons();
List<Comparison> oldestComparisons = allComparisons.subList(Math.max(allComparisons.size() - 10, 0), allComparisons.size());
System.out.println(String.format("Deleting oldest %s comparisons ...", oldestComparisons.size()));
for (Comparison comparison : oldestComparisons) {
comparisons.deleteComparison(comparison.getIdentifier());
System.out.println(String.format("Comparison '%s' deleted.", comparison.getIdentifier()));
}
createComparison(Comparisons.Side left, Comparisons.Side right, String identifier, boolean isPublic, Instant expires)
Comparison
representing the newly created comparison.createComparison
accepts the following arguments:
left
/ right
identifier
(nullable)null
, the API will automatically generate a unique identifierisPublic
false
authentication is required to view the comparisontrue
the comparison can be accessed by anyone with knowledge of the URLexpires
(nullable)null
, the comparison will never expire (but may be explicitly deleted)The following exceptions may be raised in addition to parameter validation exceptions:
BadRequestException
identifier
already in use)The two most common static constructors for creating Comparisons.Side
objects are:
Comparisons.Side.create(File file, String fileType, String displayName)
Comparisons.Side
for a locally accessible file.Comparisons.Side.create(String sourceURL, String fileType, String displayName)
Comparisons.Side
for a remotely accessible file referenced by URL.These constructors accept the following arguments:
file
sourceURL
fileType
pdf
docx
, docm
, doc
, rtf
pptx
, pptm
, ppt
txt
displayName
(nullable)
File rightFile = new File(...);
Comparison comparison = comparisons.createComparison(
Comparisons.Side.create("https://domain.com/path/to/left.pdf", "pdf"),
Comparisons.Side.create(new File("path/to/right/file.docx"), "docx"),
// identifier: null indicates the library should generate an identifier
null,
// isPublic: false ensures the comparison requires a signed URL to access
false,
// expires: The system should delete this comparison after two hours
Instant.now().plus(Duration.ofHours(2))
);
System.out.println(String.format("Created comparison: %s", comparison));
publicViewerURL(String identifier, boolean wait)
signedViewerURL(String identifier, Instant|Duration validUntil, boolean wait)
Both methods use the following common parameters:
identifier
wait
false
, the viewer will show an error if the identifier
does not existtrue
, the viewer will wait for a comparison with the provided identifier
to existidentifier
is never createdThe signedViewerURL
method also supports the following parameters:
validUntil
(nullable)null
, the URL will be generated with the default 30 minute expirySee the displaying comparisons section in the API documentation for additional details.
String identifier = "<identifier>";
// Retrieve a signed viewer URL which is valid for 1 hour. The viewer will wait
// for the comparison to exist in the event processing has not yet completed.
String viewerURL = comparisons.signedViewerURL(identifier, Duration.ofHours(1), true);
System.out.println(String.format("Viewer URL (expires in 1 hour): %s", viewerURL));
getExport(String identifier)
Export
or raises a Comparisons.ComparisonNotFoundException
exception if the specified export identifier does not exist.Export
objects have the folowing getter methods:
getIdentifier(): String
getComparison(): String
getKind(): ExportKind
LEFT
RIGHT
COMBINED
SINGLE_PAGE
isReady(): boolean
If a Export
is ready (i.e. it has been processed) the following additional getter methods are meaningful:
getFailed(): Boolean
getUrl(): String
(only present if not failed
)getErrorMessage(): String
(only present if failed
)createExport(String comparisonId, ExportKind exportKind, boolean includeCoverPage)
Export
representing the newly created export.createExport
accepts the following arguments:
comparisonId
exportKind
LEFT
RIGHT
COMBINED
SINGLE_PAGE
includeCoverPage
COMBINED
export kind.generateIdentifier()
The library utilises the Apache httpclient
and httpasyncclient
packages for performing HTTP requests, which respect configured system properties pertaining to network configuration. The full list of consulted system properties can be found in the HttpClientBuilder class documentation.
Basic configuration for usage of a network proxy typically entails setting the following properties:
Property name | Description | Example |
---|---|---|
https.proxyHost |
IP address or DNS hostname of proxy for HTTPS connections | proxy.corp.net |
https.proxyPort |
HTTPS port of proxy for HTTPS connections (defaults to 443 ) |
8443 |
https.proxyUser |
Username when authenticating to the proxy using basic auth | myuser |
https.proxyPassword |
Passsword when authenticating to the proxy using basic auth | mypass |
The above properties also have http
equivalents used when making plain HTTP connections. The Draftable API only permits HTTPS by default, so these options are not relevant for most deployments. The above list of properties is not comprehensive and only serves as a starting point for performing basic proxy configuration.
If connecting to an API Self-hosted endpoint which is using a self-signed certificate (the default) you will need to suppress certificate validation. The library supports disabling validation for self-signed certificates and associated hostname validation via a Java system property: draftable.allowSelfSignedCerts
.
Setting this property to 1
or true
will enable the capability and print a warning to stderr
. Java system properties can be easily set when launching the runtime with the -D
parameter. For example: java -Ddraftable.allowSelfSignedCerts=1 ...
.
Note this capability only applies to requests initiated by the client library. Certificate and hostname validation will not be impacted for requests made by other libraries.
Setting this system property in production environments is strongly discouraged as it significantly lowers security. We only recommend setting this system property in development environments if configuring a CA signed certificate for API Self-hosted is not possible.
All content is licensed under the terms of The MIT License.