Skip to content

dechoi83/compare-api-java-client

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Draftable Compare API - Java Client Library

maven javadoc license

travis

Open in Visual Studio Code

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.

Requirements

  • Operating system: Any maintained Linux, macOS, or Windows release
  • Java runtime: Java SE 8+ or compatible implementation

Getting started

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>");
  • Start creating comparisons
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));

API reference

Design notes

Exceptions and error handling

Method calls immediately validate parameters. Parameter validation failures throw IllegalArgumentException.

Java exceptions are categorised as either checked or unchecked. In this library:

  • I/O failures (e.g. network connectivity) throw a checked IOException.
  • Unchecked exceptions may be thrown as documented in Javadoc and below.

In practice, while you may elect to handle unchecked exceptions, it should be possible to write your application such that they're never thrown.

Synchronous and asynchronous requests

  • Requests may be made synchronously, or asynchronously using the methods suffixed with Async.
  • Asynchronous methods return a CompletableFuture, which when awaited, will complete successfully or throw an exception.

Thread safety

The API client class, Comparisons, is thread-safe. If close() is called prematurely future requests will re-open the underlying HTTP clients.

Initializing the client

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).

Retrieving comparisons

  • getAllComparisons()
    Returns a List<Comparison> of all your comparisons, ordered from newest to oldest. This is potentially an expensive operation.
  • getComparison(String identifier)
    Returns the specified Comparison or raises a Comparisons.ComparisonNotFoundException exception if the specified comparison identifier does not exist.

Comparison objects have the following getter methods:

  • getIdentifier(): String
    The unique identifier of the comparison
  • getLeft(): Comparison.Side / getRight(): Comparison.Side
    Information about each side of the comparison
    • getFileType(): String
      The file extension
    • getSourceURL(): String
      The URL for the file if the original request was specified by URL, otherwise null
    • getDisplayName(): String
      The display name for the file if given in the original request, otherwise null
  • getIsPublic(): boolean
    Indicates if the comparison is public
  • getCreationTime(): Instant
    Time in UTC when the comparison was created
  • getExpiryTime(): Instant
    The expiry time if the comparison is set to expire, otherwise null
  • getReady(): boolean
    Indicates if the comparison is ready to display

If a Comparison is ready (i.e. it has been processed) the following additional getter methods are meaningful:

  • getReadyTime(): Instant
    Time in UTC the comparison became ready
  • getFailed(): boolean
    Indicates if comparison processing failed
  • getErrorMessage(): String (only present if failed)
    Reason processing of the comparison failed

Example usage

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));
}

Deleting comparisons

  • deleteComparison(String identifier)
    Returns nothing on successfully deleting the specified comparison or raises a Comparisons.ComparisonNotFoundException exception if no such comparison exists.

Example usage

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()));
}

Creating comparisons

  • createComparison(Comparisons.Side left, Comparisons.Side right, String identifier, boolean isPublic, Instant expires)
    Returns a Comparison representing the newly created comparison.

createComparison accepts the following arguments:

  • left / right
    Describes the left and right files (see following section)
  • identifier (nullable)
    Identifier to use for the comparison:
    • If specified, the identifier must be unique (i.e. not already be in use)
    • If null, the API will automatically generate a unique identifier
  • isPublic
    Specifies the comparison visibility:
    • If false authentication is required to view the comparison
    • If true the comparison can be accessed by anyone with knowledge of the URL
  • expires (nullable)
    Time at which the comparison will be deleted:
    • If specified, the provided expiry time must be UTC and in the future
    • If null, the comparison will never expire (but may be explicitly deleted)

The following exceptions may be raised in addition to parameter validation exceptions:

  • BadRequestException
    The request could not be processed (e.g. identifier already in use)

Creating comparison sides

The two most common static constructors for creating Comparisons.Side objects are:

  • Comparisons.Side.create(File file, String fileType, String displayName)
    Returns a Comparisons.Side for a locally accessible file.
  • Comparisons.Side.create(String sourceURL, String fileType, String displayName)
    Returns a Comparisons.Side for a remotely accessible file referenced by URL.

These constructors accept the following arguments:

  • file
    A file object to be read and uploaded
  • sourceURL
    The URL from which the server will download the file
  • fileType
    The type of file being submitted:
    • PDF: pdf
    • Word: docx, docm, doc, rtf
    • PowerPoint: pptx, pptm, ppt
    • Text: txt
  • displayName (nullable)
    The name of the file shown in the comparison viewer

Example usage

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));

Displaying comparisons

  • publicViewerURL(String identifier, boolean wait)
    Generates a public viewer URL for the specified comparison
  • signedViewerURL(String identifier, Instant|Duration validUntil, boolean wait)
    Generates a signed viewer URL for the specified comparison

Both methods use the following common parameters:

  • identifier
    Identifier of the comparison for which to generate a viewer URL
  • wait
    Specifies the behaviour of the viewer if the provided comparison does not exist
    • If false, the viewer will show an error if the identifier does not exist
    • If true, the viewer will wait for a comparison with the provided identifier to exist
      Note this will result in a perpetual loading animation if the identifier is never created

The signedViewerURL method also supports the following parameters:

  • validUntil (nullable)
    Time at which the URL will expire (no longer load)
    • If specified, the provided expiry time must be UTC and in the future
    • If null, the URL will be generated with the default 30 minute expiry

See the displaying comparisons section in the API documentation for additional details.

Example usage

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));

Utility methods

  • generateIdentifier() Generates a random unique comparison identifier

Comparison exports

Creating export

  • createExport(String comparisonId, ExportKind exportKind, boolean includeCoverPage) Returns an Export instance representing the newly created export. This method needs the following parameters:

    • comparisonId - identifier of comparison, for which we run the export
    • exportKind - kind of the export we intend to run. Following values are supported here:
      • LEFT - content of the left comparison side, with deletions highlights applied
      • RIGHT - content of the right comparison side, with insertions highlights applied
      • COMBINED - content of left and right document, placed side by side
      • SIGLE_PAGE - comparison content in single page mode.
    • includeCoverPage - relevant only for combined comparison, indicates whether it should include a cover page.
  • There can exist multiple exports of the same type, created for the same comparison.

  • Class Export represents a single export. It has the following fields:

    • identifier - Identifier of the export itself (note that it is different from the comparison ID).
    • comparison - Identifier of the comparison used for running this export.
    • url - Download url of the export document
    • kind - Export kind. Supported values: single_page, combined, left, right.
    • ready - Indicates if processing of the export request has completed.
    • failed - Indicates if export has failed
    • errorMessage - Error message for failed exports. This is set to null for successful exports.

Retrieving export

  • getExport(String identifier) Retrieves existing export by its identifier. Note that the export returned here may not be ready yet.

Other information

Network & proxy configuration

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.

Self-signed certificates

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.

About

Java client library for the Draftable document comparison API

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%