Building Bridges with JACOB

JACOB is a JAva-COm Bridge that allows you to call COM automation components from Java. It uses JNI internally to make native calls into COM and Win32 libraries. In simple words, you can now call any of the .dll file functions from Java and use the result in your Java program (provided you know which function to call). This article gives some examples of how you can do this.
Remember that JACOB only implements a generic bridge to call COM components from Java. It is not the Java interface of Microsoft Office nor does it directly support its COM components. And you cannot use it to call Win32 libraries on platforms other than Windows. You can use JACOB to call any of the ActiveX components that you could call in your Visual Basic program; the only difference is that you cannot include the ActiveX component in your Java application as you could do in VB.

The JACOB binary distribution (jacobBin_XX.zip) includes-
1. jacob.jar - a JAR file for the Java classes which you must add to your CLASSPATH. The package names replace com.ms with com.jacob. For example, com.ms.com.Variant, from Microsoft Java SDK, maps to com.jacob.com.Variant.
2. jacob.dll - a small Win32 DLL which you must add to your PATH. And register it with Windows using the Regsvr32 command.
3. samples - provided in Java source and compiled form to demonstrate various features of the product. In particular, a set of wrapper classes for Microsoft ADO are provided as samples.
The source code is available in the JACOB source distribution (jacobSrc_XX.zip), which includes both the Java and C++ code. The source distribution is a superset of the binary one, so you don’t need both.
Since the JACOB classes are based on the com.ms (Microsoft) classes, it would help if you had some knowledge about these classes since you would be using the same coding structure in Java. And this will also help you build good projects that will really help you communicate with the Microsoft applications.
Now, let us start by building a small program that can call Microsoft Word. This code (Code-1) will open Microsoft Word.

Code 1

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.*;
import java.io.*;

public class OpenWord {
private static final Integer wdNewBlankDocument = new Integer(0);
private static final Variant vTrue = new Variant(true);
private static final Variant vFalse = new Variant(false);
private static ActiveXComponent activeXWord = null;
private static Object activeXWordObject = null;

public static void main(String[] args) {
try {
activeXWord = new ActiveXComponent("Word.Application");
activeXWordObject = activeXWord.getObject();
Dispatch.put(activeXWordObject, "Visible", vTrue);

//activeXWordObject = null;

}
catch (Exception e) {
quit();
}
}

public static void quit() {
if (activeXWord != null) {
System.out.println("quit word");
//calls the Quit method of MS Word, this will close MS Word
activeXWord.invoke("Quit", new Variant[] {});
ComThread.Release();
activeXWord.release();
System.out.println("quit word");
}
}
}

To run Code-1, you have to first download JACOB (available in DIQ CDs) and include jacob.jar in your CLASSPATH by using the ‘set classpath’ command or by setting the Windows environment variable, and copy jacob.dll into your C:\Winnt\system32 (for Windows 2000/XP) or C:\Windows\system folder. Now try the following commands. (It is assumed that you have installed Java SDK and the PATH variable has been set properly.)

set classpath=C:\jacob\jacob.jar;.;
javac OpenWord.java
java OpenWord

Surprise! Surprise! You have just opened MS Word from Java. (I hope everything has gone well.) Some Java programmers might be thinking - “What’s the big deal? Can’t we call MS Word using the System.exec function?” Agreed that you can do it, but you can just call the ‘exe’ file and cannot create new files from within Java. Also, we have just created an ActiveX object of MS Word, just like we do in Visual Basic. We can now put this ActiveX object to our own use. All VB programmers know how to use an ActiveX object. Similarly, you can use this Word object in Java to create, save, edit, delete and use many more functions that MS Word supports, and all this from within Java.
Next, let us see how to save text contents into the different file formats that MS Word supports. Take a look at Code-2. This code is from the JACOB-project Yahoo group http://groups.yahoo.com/group/jacob-project. Feel free to test Code-2. I must again say that you will need jacob.jar in your classpath, and of course the jacob.dll file must be registered on your machine.

Code 2

import com.jacob.com.*;
import com.jacob.activeX.*;

public class Word {
public static String extractText(String file) throws Exception {
/* it seems to control the program flow single = STA (SingleThreadApplication) or MTA(?) multi-threaded
*/
ComThread.InitSTA();
/* choose your Microsoft Application -
* example: MsExcel = Excel.Application
* here MsWord
*/
ActiveXComponent xl = new ActiveXComponent("Word.Application");
try {
Object documents = xl.getProperty("Documents").toDispatch();
Object doc1 = Dispatch.call(documents, "Open", file, new Boolean(false), new Boolean(true), new Boolean(true)).toDispatch();
Object content = Dispatch.get(doc1, "Content").toDispatch();
// Get document content
String txt = Dispatch.get(content, "Text").toString();
/* Declaration of the filename -> Put it into a Variant variable -
* because it recognizes what type the entered variable will be -
* here: fileName = String, you can include the path where the file should be generated -
* example "c:\\test"
* fileFormat = Integer(?), several possibilities:
* 0 = document
* 1 = template
* 2 = text
* 3 = text with linebreaks
* 4 = dos text
* 5 = dos text with linebreak
* 6 = rtf
* 7 = encoded text / unicode text
* 8 = html
*/
Variant fileName = new Variant("c:\\Test4");
Variant fileFormat = new Variant(8); //using html file format
/* Dispatch is a call dispatcher number and kind of parameters is
* hard to find out
*/
Dispatch.call(doc1, "SaveAs", fileName,fileFormat);
Dispatch.call(doc1, "Close");
// Returns the text
return txt;
}
catch(Exception e) {
e.printStackTrace();
throw e;
}
finally {
// Quits the application Application.Quit([SaveChanges], [OriginalFormat], [RouteDocument])
xl.invoke("Quit", new Variant[] {});
ComThread.Release();
}
}


public static void main(String args[]) {
try {
String test;
// Here you can select your word-file
System.out.println("Start Here");
test = extractText("c:\\Doc.doc"); // give a document file name
System.out.println("Stop Here");
System.out.println(test);
}
catch (Exception e) {
System.err.println(e);
}
}
}


Jacob Functions

If you are a MS Java developer, then you will know these functions; those who don’t know can get more information about the different functions that Jacob uses from the MS Java SDK help. You can use Jacob’s Dispatch.call() and Dispatch.invoke() methods to call ActiveX Object methods, and Dispatch.put() and Dispatch.get() to access ActiveX Object variables (just as we did in the code listings given above).

How to get the Program ID that you can use to create the ActiveX Object?
What I have done a few times is, first register the dll with the ActiveX server using ‘regsvr32 C:\\somedll.dll’. Then open Word’s VBA IDE or Visual Basic Editor, create a new project and include the dll in your project using the Project References option. Add a reference to the ActiveX server to the project and then make use of IntelliSense to determine the progid. You can also open the Object Browser and check for the progid, and you can use this id. Alternatively, you can register the ocx, then search the registry for ‘dllname.ocx’. One of the entries will contain a progid.

Related Links
·  The main Jacob Site - http://danadler.com/jacob/
·  The JACOB mailing list is hosted at Yahoo groups (support and help): http://groups.yahoo.com/group/jacob-project

The author is a Jr. Java Developer with Idealake Information Technologies, Mumbai. He can be contacted on harish_t79@yahoo.co.in




Added on May 8, 2007 Comment

Comments

Post a comment

Your name:

Comment: