ReportingCloud

Java

Topic

If your application runs on the JVM, the ReportingCloud Java SDK gives it a ReportingCloud class with a method for most endpoints of the Web API. The SDK is source code on GitHub, not a package in a repository: you build the library yourself and add it to your project. Read on for its requirements, the build, how it authenticates, a merge example and its methods.

The code dates from 2019. It authenticates with the user name and password of the account only, and it has no methods for the thumbnails of a document, sharing or tracked changes. Where these matter, call the Web API directly, as Web API in Getting Started shows with curl.

Java in Getting Started builds the SDK and a first program that merges a template step by step.

Source and Requirements

RepositoryVersionLast changeJavaDependency
TextControl/txtextcontrol-reportingcloud-java1.3March 4, 2019JDK 8com.google.code.gson:gson 1.7.2

The SDK isn't published in Maven Central. The package of its classes is com.textcontrol.reportingcloud, and build.gradle sets the Java version to 1.8. One class, FindAndReplaceBody, uses javafx.util.Pair from JavaFX: the SDK compiles with a JDK that includes JavaFX, or with the org.openjfx:javafx-base library on the class path.

Build the SDK

The repository contains the Gradle wrapper for Gradle 2.9. The script gradlew isn't marked as executable, so start it with bash, or run gradlew.bat on Windows; sh fails where it is dash, as on Debian and Ubuntu. The wrapper runs on JDK 8 only; Java in Getting Started builds the SDK with javac and a current JDK. In the root folder of a clone, the folder of build.gradle, build the library and its API documentation:

bash gradlew build -x test
bash gradlew javadoc

-x test excludes the unit tests from the build, as Gradle's command-line interface describes. The tests call the Web API with the credentials of an account. They read them from src/test/resources/rc_credentials.json, a JSON object with the properties username and password. They build the path of this file with Windows path separators (\), so on Linux and macOS they don't find it and fail, even when the file exists. Installing an SDK shows the whole build, from the clone to the JAR file and a first call.

Authentication

The Java SDK sends every request with Basic authentication. It has no constructor or setting that authenticates with an API key, so it needs the user name and password of your ReportingCloud account:

ConstructorBase URL
ReportingCloud(String username, String password)https://api.reporting.cloud
ReportingCloud(String username, String password, String baseUrl)The given URL; pass it without a trailing slash, because the constructor removes two characters from a URL that ends with one

Authentication explains Basic authentication and why API keys are recommended for the Web API.

Merge a Template

The following program merges sample_invoice.tx, the demo template in the template storage of every trial account, with one invoice record and saves invoice.pdf. It reads the credentials from the environment variables REPORTINGCLOUD_USERNAME and REPORTINGCLOUD_PASSWORD. Compile it with the SDK and Gson on the class path:

import com.textcontrol.reportingcloud.MergeBody;
import com.textcontrol.reportingcloud.MergeSettings;
import com.textcontrol.reportingcloud.ReportingCloud;
import com.textcontrol.reportingcloud.ReturnFormat;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

class Item {
    public final String qty;
    public final String item_no;
    public final String item_description;
    public final String item_total;

    Item(String qty, String itemNo, String itemDescription, String itemTotal) {
        this.qty = qty;
        this.item_no = itemNo;
        this.item_description = itemDescription;
        this.item_total = itemTotal;
    }
}

class Invoice {
    public final String invoice_no;
    public final String billto_name;
    public final String billto_companyname;
    public final List<Item> item = new ArrayList<>();
    public final String total;

    Invoice(String invoiceNo, String billtoName, String billtoCompanyname, String total) {
        this.invoice_no = invoiceNo;
        this.billto_name = billtoName;
        this.billto_companyname = billtoCompanyname;
        this.total = total;
    }
}

public class MergeInvoice {
    public static void main(String[] args) throws IOException {
        // The Java SDK authenticates with the user name and password of the account
        ReportingCloud reportingCloud = new ReportingCloud(
                System.getenv("REPORTINGCLOUD_USERNAME"),
                System.getenv("REPORTINGCLOUD_PASSWORD"));

        // One record with the fields and the item block of sample_invoice.tx
        Invoice invoice = new Invoice("778723", "Joey Montana", "Montana, LLC", "8210.538");
        invoice.item.add(new Item("1", "1", "Item description 1", "2130.40"));
        invoice.item.add(new Item("1", "2", "Item description 2", "5543"));

        MergeSettings mergeSettings = new MergeSettings();
        mergeSettings.setDocumentTitle("Invoice 778723");

        MergeBody mergeBody = new MergeBody(new Object[] { invoice }, mergeSettings);

        try {
            // Merge the stored template and return the documents as byte arrays
            List<byte[]> documents = reportingCloud.mergeDocument(
                    mergeBody, "sample_invoice.tx", ReturnFormat.PDF);

            Files.write(Paths.get("invoice.pdf"), documents.get(0));
            System.out.println("invoice.pdf has been written.");
        } catch (IllegalArgumentException exception) {
            // The SDK throws the response body of a failed request
            System.out.println(exception.getMessage());
        }
    }
}

The code works as follows:

  • Invoice and Item hold the merge data. Gson writes their fields with the names they have in Java, so the field names are the merge field names of the template, and the list item fills the merge block of the same name. Merge Data describes the structure.
  • MergeBody takes the records as an Object[] or an Iterable<Object>, optionally MergeSettings and a template as a byte array, which replaces the template name.
  • mergeDocument sends the request to POST /v1/document/merge and returns a List<byte[]>, one entry for each created document. Its overloads add the template name, a ReturnFormat (PDF by default), append and test, both false by default. Passing a template name together with template data, or neither, throws an InvalidParameterException.

A new MergeSettings has removeEmptyFields, removeEmptyBlocks, removeEmptyImages and removeTrailingWhitespace set to true and mergeHtml set to false, and the SDK sends all five. removeEmptyImages is therefore true, while the Web API's default is false. MergeSettings has no property for the culture. The other properties are those of DocumentSettings: author, creator application, subject, title, user password and the two dates. Merge Settings describes every setting.

ReportingCloud Methods

MethodWeb API endpointReturns
mergeDocumentPOST /v1/document/mergeList<byte[]>
appendDocumentsPOST /v1/document/appendbyte[], one document from an AppendBody of AppendDocument objects
convertDocumentPOST /v1/document/convertbyte[]
findAndReplacePOST /v1/document/findandreplacebyte[]
uploadTemplatePOST /v1/templates/uploadNothing
listTemplatesGET /v1/templates/listList<Template>
getTemplateCountGET /v1/templates/countint
templateExistsGET /v1/templates/existsboolean
getTemplateInfoGET /v1/templates/infoTemplateInfo
getTemplatePageCountGET /v1/templates/pagecountint
getTemplateThumbnailsGET /v1/templates/thumbnailsList<byte[]>, one image per page
downloadTemplateGET /v1/templates/downloadbyte[]
deleteTemplateDELETE /v1/templates/deleteNothing
getAccountSettingsGET /v1/account/settingsAccountSettings
getAPIKeys, createAPIKey, deleteAPIKeyGET /v1/account/apikeys, PUT and DELETE /v1/account/apikeyList<APIKey>, the new key as a String or nothing
listFontsGET /v1/fonts/listList<String>
checkTextGET /v1/proofing/checkList<IncorrectWord>
getAvailableDictionariesGET /v1/proofing/availabledictionariesList<String>
getSuggestionsGET /v1/proofing/suggestionsList<String>

convertDocument, appendDocuments and findAndReplace also have overloads with a test argument. The API key methods manage the keys of the account; the SDK itself still signs in with the user name and password.

Errors

When the Web API answers with an error, a method throws an IllegalArgumentException whose message is the response body; the HTTP status code isn't part of it. The connection timeout is 10 seconds. When the server can't be reached, a method that sends a body, such as mergeDocument, throws an IOException, while a method without a body, such as getTemplateCount, throws a NullPointerException: the SDK then reads an error stream that doesn't exist. The methods also throw IllegalArgumentException or java.security.InvalidParameterException for arguments they reject before sending, such as an empty template name. Errors and Status Codes lists the status codes and their causes.

API Documentation and Source

  • API documentation. The Javadoc of version 1.3, reportingcloud 1.3 API, describes every class and method; bash gradlew javadoc builds the same pages from the source.
  • Source code. The repository TextControl/txtextcontrol-reportingcloud-java holds the source under a BSD license, with unit tests.