Qoppa’s Java PDF library jPDFProcess can be packaged as a REST API and then deployed to any J2EE server to provide RESTful services. See below.

If you are looking for an-easy to install solution, Qoppa Software also offers a Restful API Module as part of Qoppa’s PDF Automation Server that be installed and started by simply running the installer for your OS (Windows, Mac, Linux or Unix) and includes more functions than the sample war below.

The following sample WAR file provides a number of PDF functions from jPDFProcess as a REST API:

jPDFRest.war

1. Introduction

The jPDFRest sample implements a prototype of a RESTful API for accessing Qoppa’s jPDFProcess functionality.

This sample implements:

  • transferring PDF files to/from the REST service
  • returning PDF and image representations of PDF pages and
  • retrieving basic document metadata information.

This prototype has very limited features, but we provide source code to the implementation so that it is very simple to add any function supported by jPDFProcess: create PDF, print PDF, convert PDF to images, merge PDF form data, add watermark, flatten comments or fields, assemble or split PDF, linearize PDF, extract content, encrypt / secure.  Contact us if you need help.

2. jPDFRest Server

The jPDFRest server has been implemented and packaged (jPDFRest.war) to deploy as a servlet.  This allows for easy deployment to servlet containers (Tomcat, WildFly, etc.).

The following configuration is needed before deploying the .WAR file:

  1. Determine (select or create) a file storage directory for use by the REST service.  The REST API implementation needs somewhere to store uploaded PDF files.
  2. Edit the restConfig.xml file (supplied) with the license for jPDFProcess and the path of the REST storage directory created in step (a).
  3. Configure your servlet container with a Java system property named PDFREST_CONFIG which has as its value the path to the restConfig.xml file.
    (Ex.  For Tomcat this requires editing the setenv.sh (or .bat) file in Tomcat’s configuration directory, /bin, to set this property in the CATALINA_OPTS environment variable.)

After deployment the REST API can be accessed via a URL structured like this: http://  {host:port} /jPDFRest/api/… where

  • {host:port} are the hostname and port where Tomcat is setup (ex. “server.company.com:8080”)
  • “/jPDFRest” is the servlet context name.  This defaults to the name of the deployed .WAR file – so the above example assumes that jPDFRest.WAR was deployed.  The context name can be changed by renaming the .WAR file before deployment (or eliminated through configuration options for the servlet container).

After deployment the following tests can be performed to ensure that configuration and installation are correct:

  1. Connect to the API version URL from a browser – you should receive XML data with version information for the REST service.  This will establish that the REST API service is deployed and running. Ex.  http://server.com/jPDFRest/api/version
  2. Copy a pdf file (ex. “test.pdf”) to the REST storage directory and retrieve the first page using a URL like this: http://server.com/jPDFRest/api/pdfs/test/pages/0?format=JPEGNote:  On a Linux service the file permissions for your PDF file will need to be set in order for the REST service to access that file – otherwise you will get an exception message.If this works without error (i.e. returns JPEG image) then the REST service has been configured correctly.

3. Clients

3.1. Service Client

The “Service Client” is a library that Qoppa developed to facilitate accessing the jPDFProcess REST service in a manner programmatically similar to using jPDFProcess directly.

The service client implements 4 objects:

  • Service
  • SvcPDFDocument
  • SvcPDFPage
  • SvcDocumentInfo

SvcPDFDocument, SvcPDFPage and SvcDocumentInfo are designed to perform limited operations with the same semantics as the PDFDocument, PDFPage and DocumentInfo classes in jPDFProcess.

The full API for the service client is supplied as Javadocs.

Here is a sample (that uses most significant parts of the API) to open a PDF file and save each page to a JPEG image :

import com.qoppa.pdf.rest.client;
// Create service and open PDF file
Service svc = new Service("localhost:8080");
SvcPDFDocument doc = new SvcPDFDocument(svc, "C:/temp/test01.pdf", null);
// Get document info
SvcDocumentInfo docInfo = doc.getDocumentInfo();
// Save pages
for( int i=0; i<docInfo.getPageCount(); i++)
{
FileOutputStream fStream = null;
fStream = new FileOutputStream("c:/temp/test01_page" + i + ".jpg");
SvcPDFPage page = doc.getPage(i);
page.savePageAsJPEG(fStream, 300, 0.8f);
fStream.close();
}
// Close document (delete from server)
doc.close();

3.2. Jersey 1.x Client API

The Jersey JAX-RS reference implementation project (http://jersey.java.net) provided a REST client API framework in its 1.x release.  (Note:  Jersey 2.x contains an implementation of the JAX-RS 2.0 Client API – which is different from the Jersey 1.x REST Client API.)

Using this API, a simple REST client program can be written to use the jPDFRest server.

Here is code for equivalent to the above service client sample, but written using the Jersey 1.x Client API.  Note that this code uses, but doesn’t contain definitions for, a copyStream() function that copies one stream to another.

Sample Java Code

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.ws.rs.core.MediaType;
import com.qoppa.pdf.IPassword;
import com.qoppa.pdf.PDFException;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
// Open file
File pdfFile = new File("c:/temp/test.pdf");
// Setup URI web resource builder
Client cli = Client.<i>create</i>();
WebResource webRes = cli.resource("http://localhost:8080/jPDFRest/api/pdfs");
// Setup for POST request
WebResource.Builder req = webRes.type(MediaType.<i>valueOf</i>("application/pdf"));
if(password != null)
req = req.header("X-pdfpass", _pass.getPasswords()[0]);      // 1st password
// Send PDF file via POST
ClientResponse response = req.post(ClientResponse.class, pdfFile);
// Parse and save {pdfId} from returned Location URI
String Location = response.getHeaders().get("Location").get(0);
String pdfId = Location.substring(Location.lastIndexOf('/') + 1, Location.length());
// Setup GET request for document info
req = webRes.path(pdfId).path("documentInfo");
// GET document info XML &amp; parse to SvcDocumentInfo object
SvcDocumentInfo docInfo = req.get(SvcDocumentInfo.class);
// Save pages
for (int i=0; i&lt;docInfo.getPageCount(); i++)
{
// Setup request for document page
req = webRes.path(pdfId).path("pages").path(String.valueOf(i));
// GET document page as JPEG
InputStream inStream = req.queryParam("format", "JPEG").
queryParam("res", "300").
queryParam("quality", "0.8").
get(InputStream.class);
// Setup stream to save file
FileOutputStream outStream = null;
fStream = new FileOutputStream("c:/temp/test01_page" + i + ".jpg");
// Copy returned image stream to file
copyStream(inStream, outStream);
fStream.close();
}
// Setup request to delete document from server
req = webRes.path(pdfId);
// DELETE document from server
ClientResponse response = req.delete(ClientResponse.class);

SvcDocumentInfo.java

import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
importjavax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "DocumentInfo")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class SvcDocumentInfo
{
// Storage members
private String _title;
private int _pageCount;
private String _author;
private String _subject;
private String _keywords;
private String _creator;
private String _producer;
private Date _creationDate;
private Date _modDate;
// Constructor: default
public SvcDocumentInfo() { }
// Property: Title
@XmlElement(name = "title")
public String getTitle()
{
return _title;
}
public void setTitle(String value)
{
_title = value;
}
// Property: Author
@XmlElement(name = "author")
public String getAuthor()
{
return _author;
}
public void setAuthor(String value)
{
_author = value;
}
// Property: Subject
@XmlElement(name = "subject")
public String getSubject()
{
return _subject;
}
public void setSubject(String value)
{
_subject = value;
}
// Property: Keywords
@XmlElement(name = "keywords")
public String getKeywords()
{
return _keywords;
}
public void setKeywords(String value)
{
_keywords = value;
}
// Property: Creator
@XmlElement(name = "creator")
public String getCreator()
{
return _creator;
}
public void setCreator(String value)
{
_creator = value;
}
// Property: Producer
@XmlElement(name = "producer")
public String getProducer()
{
return _producer;
}
public void setProducer(String value)
{
_producer = value;
}
// Property: CreationDate
@XmlElement(name = "creationDate")
public Date getCreationDate()
{
return _creationDate;
}
public void setCreationDate(Date value)
{
_creationDate = value;
}
// Property: ModDate
@XmlElement(name = "modDate")
public Date getModDate()
{
return _modDate;
}
public void setModDate(Date value)
{
_modDate = value;
}
// Property: PageCount
@XmlElement(name = "pageCount")
public int getPageCount()
{
return _pageCount;
}
public void setPageCount(int value)
{
_pageCount = value;
}
}

3.3. Other Java Frameworks

There are other Java frameworks which could be used to write software for calling a REST API:

  • Apache HttpClient
  • RestEasy Client
  • Jersey 2.x Client – reference implementation of JAX-RS 2.0 Client API

 

3.4. REST API Reference

 

Command

URI

Query Params

Header Params

Request Body

Response Body

Description

GET /api/version

text/xml

Version info as XML
GET /api/pdfs

<docList> – JSON or XML

Get list of document URIs
POST /api/pdfs

application/pdf

Upload PDF and return {pdfId} in Location header
DELETE /api/pdfs/{pdfId} Delete PDF document
GET /api/pdfs/{pdfId}

application/pdf

Get PDF document
GET /api/pdfs/{pdfId} format=TIFF | TIF
res={# dpi}
comp={type} (below)
stripRows={# rps}
byteOrder= “BIG_ENDIAN” | “LITTLE_ENDIAN”
gray=true | false
quality={# qVal}
dither= “None” | “FLOYD_STEINBERG”

X-pdfpass = {password}

image/tiff

Get PDF as multi-page TIFF
GET /api/pdfs/{pdfId}/documentInfo

X-pdfpass = {password}

<documentInfo> – JSON or XML

Get document info
GET /api/pdfs/{pdfId}/pages/{pageId}

X-pdfpass = {password}

application/pdf

Get single-page PDF
GET /api/pdfs/{pdfId}/pages/{pageId} format=GIF
res={dpi}

X-pdfpass = {password}

image/gif

Get PDF page as GIF image
GET /api/pdfs/{pdfId}/pages/{pageId} format=JPEG | JPG
res={dpi}
quality={qVal}

X-pdfpass = {password}

image/jpeg

Get PDF page as JPEG image
GET /api/pdfs/{pdfId}/pages/{pageId} format=PNG
res={dpi}

X-pdfpass = {password}

image/png

Get PDF page as PNG image
GET /api/pdfs/{pdfId}/pages/{pageId} format=TIFF | TIF
res={# dpi}
comp={type} (below)
stripRows={# rps}
byteOrder= “BIG_ENDIAN” | “LITTLE_ENDIAN”
gray=true | false
quality={# qVal}
dither= “None” | “FLOYD_STEINBERG”

X-pdfpass = {password}

image/tiff

Get PDF page as TIFF image

 

Supported TIFF Compression values for {comp}

  • None (i.e. empty string)
  • Deflate
  • CCITT_RLE
  • CCITT_T4
  • CCITT_T6
  • FAX_GROUP3
  • FAX_GROUP4
  • JPEG
  • LZW
  • Packbits
  • ZLib

 

Contact us if you need any help.