Friday, September 01, 2006

Using Adobe's XPAAJ.jar via Line Command on Mac OSX (Intel chipset)

For those of you who have been not using the XPAAJ.jar library only because you are Mac based, you may want to read this post. While the library does not claim to be supported on Mac, I did manage to get it to work but had to re-tweak a few things in the sample code and also study my Unix-Java Command line syntax. The tweaked code is at the bottom.

Adobe's XPAAJ:

XPAAJ is an API library from Adobe for PDF documents. The acronym means Adobe® XML/PDF Access API for Java™ (XPAAJ). It can now be downloaded freely from the Adobe Developer Network at Once you download the zip, unzip it to a directory where you will work on it. The directory structure will be as follows:

|-- xpaaj.jar

Open a terminal and navigate to the /xpaaj_sdk/samples/command-line/ConsoleSample/ directory. There you will see some sample classes and a test.pdf file. I did not have luck with all the sample files so I opened PDFExtract and modified it a bit.

For the record, my java –version is:
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-112)
Java HotSpot(TM) Client VM (build 1.5.0_06-64, mixed mode, sharing)
Mac is OSX 10.4.7 on the MacBook Pro.

If you want to run some samples, I recommend cutting and pasting the text at the end of this blog and saving it as the file “” on your hard drive. One thing you also might want to consider is to also copy the xpaaj.jar file to the ~/ConsoleSample directory to make it easier to use to compile and run the DuanePDFClass1 class since you can simply cut and paste the line commands below.

From that directory, compile the sample by typing in the following:

javac -classpath ./XPAAJ.jar

It should compile. Try typing ls –la to make sure that the resulting class file exists and that it is executable. To run it, type:

java -classpath ./xpaaj.jar: DuanePDFClass1 test.pdf

test.pdf is the argument for the test file that it will open, tell you a few tings about and save. You should see the following appear in your line command window:

duane-nickulls-computer:~/code/xpaaj_sdk/samples/command-line/ConsoleSample nickull$ java -classpath ./xpaaj.jar: DuanePDFClass1 test.pdf

Opening PDF with DuanePDFClass1...
test.pdf was successfully opened.
PDF version = %PDF-1.5
Number of pages = 1

Saving document ...
Document was saved to file : test_saved_by_DuanePDFClass1.pdf

Execution of DuanePDFClass1 has finished.

Anyhow, that is all for now. I will be demonstrating this during the Adobe Developer Week in London, UK next Wednesday. Here is the classfile text (use at your own risk, no guarantees blah blah blah....):

import java.util.*;
import java.awt.image.DataBuffer;
import com.adobe.pdf.*;

public class DuanePDFClass1 {

public static void main(String[] args)
throws FileNotFoundException, IOException
String inPdfName;
if(args.length != 1 )
System.out.println("\nCommand line format: java DuanePDFClass1 pdf-file");
inPdfName = new String(args[0]);

public static void PDFExtract(String inPdfName)
throws FileNotFoundException, IOException
System.out.println("\nOpening PDF with DuanePDFClass1...");
PDFDocument doc = null;
boolean b = false;
FileInputStream inPdfFile = new FileInputStream(inPdfName);
try {
doc = PDFFactory.openDocument(inPdfFile);
} catch (IOException e) {
System.out.println("Error opening PDF file :" + inPdfName);
if(doc == null)
System.out.println("Cannot open PDF file : " + inPdfName);
System.out.println( inPdfName + " was successfully opened.");

/* Try some methods here */
System.out.println ("PDF version = " + doc.getVersion());

System.out.println ("Number of pages = " + doc.getNumberOfPages());

/*Save PDF to file*/
System.out.println ("\nSaving document ... ");
int j = inPdfName.lastIndexOf(".");
String outPdfName = inPdfName.substring(0, j) + "_saved_by_DuanePDFClass1" + ".pdf";
InputStream inputStream;
inputStream =;
b = false;
try {
b = saveFile(inputStream, outPdfName);
} catch (Exception e) {
System.out.println("Error saving PDF file.");
if(b == true)
System.out.println ("Document was saved to file : " + outPdfName);
System.out.println("Document was not saved to file.");

System.out.println("\nExecution of DuanePDFClass1 has finished.");

method to save InputStream to a file.
public static boolean saveFile(InputStream is, String filePath)
throws Exception
boolean retVal=false;
byte[] buffer = new byte[10240];
FileOutputStream outStream = null;
outStream = new FileOutputStream(filePath);
int len=0;
while (true)
len =;
if (len == -1)
outStream.write(buffer, 0, len);
retVal = true;
catch (IOException io)
System.out.println("Writing the array of bytes into the file "
+ filePath + " failed.");
throw new Exception(
"Writing the array of bytes into the file "+ filePath +
" failed in saveFile");
return retVal;
/* TODO: add some more methods here?? */

Wednesday, August 30, 2006

The Emperor, his attire and a Genius

David Chappell has had a long history of stating the obvious. It sounds like an easy task but it is not when an industry tends to embrace FUD rather than fact. His ability to cut to the chase and put things in context really made me a big fan (something that does not come easily).

David’s latest post exposes a few similarities with a popular activity a decade or so ago and SOA. In 1996, everything was an “Object” and if you didn’t make your IT infrastructure into objects, you were doomed. Well, its’ ten years later and many are claiming the same thing with SOA and services. Zapthink’s book also puts this into perspective (good reading – I encourage you to take a look).

Rather than repeat David’s article, I whole heartedly encourage you to read it. It should stimulate some thinking on SOA. Some of my thoughts follow.

Rather than pitch “reuse”, I like to think of “re-purpose” as the goal of SOA. Reuse means you simply use something again where re-purposing it has far stronger business connotations. Juxtaposing reuse with repurpose, I prefer the latter for accuracy’s sake but want to clarify that I did infer the meaning in David’s Opiniari.

David asks a very pragmatic question – “If an organization reuses only one in five of its services, why is it building the other four?”. Do you like my new services / clothes? What do you mean I am naked?

There is of course the business driver of isolation. Using a service as an action boundary that cleanly separates two systems or pieces of functionality does make it easier to maintain those two pieces. The service isolates the functionality behind it and the consumer on the other side of it in a concept called Managed Transparency, a core component of Chris Kurt’s Web Services Architecture book. As long as a new piece of functionality replaces the existing one AND supports the service interface, you should be able to replace it or amalgamate it with another system without ripple effects on the other side of the service. Many business people have touted this as a win scenario to me. David and I are not alone, other great thinkers like the brains from Redmonk also see this pattern.

I think David’s article can be summarized in one sentence – “Think about what you are doing before doing it”. Like the carpenter’s axiom “measure twice cut once”, IT shops have to start looking at the layers above and below [ pick one: {objects || services || web services || API’s || whatever_we_call_it_tomorrow }]. Some of this starts with business process analysis. If a corporate analyzes their processes and discovers several use the same functionality (like single sign on), that is often a good candidate for “re-purposing” and might make a great service. Others, such as finding a specific telephone number for an employee’s cell phone, are probably too specialized and easy to solve via other means and would not be ideally suited for building into a service. A more generalized service to find any employee’s phone number of “number-type” might be a better consideration.

To those of you who are panicking to make everything a service, heed David’s words about the object craze. Slow down, think about what you are doing. To those of you who are advocating everything should be a service, look in the mirror to make sure you not naked.