Java COM Automation with Jacob and JBuilder - by Yuri Marx

By: Yuri Gomes

Abstract: JACOB is a JAVA-COM Bridge that allows calling COM Automation components from Java. It uses JNI to make native calls into the COM and Win32 libraries. Learn to use Jacob with JBuilder and call any DLL or ActiveX control.

Java COM Automation with Jacob and JBuilder

Introduction

JACOB is a JAVA-COM Bridge that allows calling COM Automation components from Java. It uses JNI to make native calls into the COM and Win32 libraries. Thus, Java Classes can be combined to any DLL or ActiveX control, extending the functionalities of resident components in applications (e.g.: Word, Excel, PowerPoint and which want other systems that use components COM or DLLs). JACOB abstracts the complexity of the JNI, offering one complete framework for communication with components COM/DLL through code-source. This paper it offers the possibility to explore the functionalities of the JACOB, as well as presents practical examples of as to use this framework.

Download and Install Procedures

JACOB framework is an open-source project located in Sourceforge.net website. To have access to the project it has access the Jacob Website. Two options of download exist:

  • Download jacob_x.x_src.zip to get the code source (if customizations in the framework will be necessary)
  • Download jacob_x.x.zip to only get the binary code. (if it will be only to use)

The current version has only 229k, this exactly, very small. Open zip file and unpacks the same where to desire.
To use framework it includes the jacob.jar file in classpath of your project and jacob.dll in the Windows system directory (e.g. c:windowssystem32 or equivalent).
To get more information on the Jacob it looks at in the docs Jacob folder.

The Framework Packages and Classes

The First Example - Microsoft Word

This example is based in source-code provided in an article written by Ruhl, K., 2003.

  1. Open JBuilder.
  2. Create a New Project. Go to in File > New Project > Set a name to the Project (e.g.: JacobProject) > Click in the Next button.
  3. Config the Jacob Library Path. Go to the Required Libraries Tab > Click in the Add... button > In the Library Tab, click int the New... button (if not the library included yet) > Set Jacob in the Name field > Click in the Add... button > Select the Jacob.jar file, installed in the your local disk. (e.g.: c:jacob_1.9jacob.jar) > Click Ok > Click Ok > Click Ok > Click in the Finish button.
  4. Create a new Class. Go to File > New Class > Set a name to the Class (e.g.: Word) > Click Ok.
  5. Create two new .doc files. c:jacob_1.9file_in.doc for the strInputDoc and c:jacob_1.9file_out.doc (you do set other name, if prefers). These files will be used in the example.
  6. Implement below code to the class and run it.
package jacobproject;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Variant;
import com.jacob.com.Dispatch;

public class Word {

    String strDir = "c:jacob_1.9";
    String strInputDoc = strDir + "file_in.doc";
    String strOutputDoc = strDir + "file_out.doc";
    String strOldText = "[label:import:1]";
    String strNewText =
            "I am some horribly long sentence, so long that [insert anything]";
    boolean isVisible = true;
    boolean isSaveOnExit = true;

    public Word() {
        ActiveXComponent oWord = new ActiveXComponent("Word.Application");
        oWord.setProperty("Visible", new Variant(isVisible));
        Dispatch oDocuments = oWord.getProperty("Documents").toDispatch();
        Dispatch oDocument = Dispatch.call(oDocuments, "Open", strInputDoc).
                             toDispatch();
        Dispatch oSelection = oWord.getProperty("Selection").toDispatch();
        Dispatch oFind = oWord.call(oSelection, "Find").toDispatch();
        Dispatch.put(oFind, "Text", strOldText);
        Dispatch.call(oFind, "Execute");
        Dispatch.put(oSelection, "Text", strNewText);
        Dispatch.call(oSelection, "MoveDown");
        Dispatch.put(oSelection, "Text",
                     "nSo we got the next line including BR.n");

        Dispatch oFont = Dispatch.get(oSelection, "Font").toDispatch();
        Dispatch.put(oFont, "Bold", "1");
        Dispatch.put(oFont, "Italic", "1");
        Dispatch.put(oFont, "Underline", "0");

        Dispatch oAlign = Dispatch.get(oSelection, "ParagraphFormat").
                          toDispatch();
        Dispatch.put(oAlign, "Alignment", "3");
        Dispatch oWordBasic = (Dispatch) Dispatch.call(oWord, "WordBasic").
                              getDispatch();
        Dispatch.call(oWordBasic, "FileSaveAs", strOutputDoc);
        Dispatch.call(oDocument, "Close", new Variant(isSaveOnExit));
        oWord.invoke("Quit", new Variant[0]);
    }

    public static void main(String[] args) {
        Word word = new Word();
    }
}

Ready! Now, open the file c:jacob_1.9file_out.doc for view the results!

This example shows the use of the COM Server of the Microsoft Word. To learn to use the API of a COM Server it is necessary to study its TLB archive or the technical documentation supplied for the manufacturer. The use of the Jacob in itself is explained to follow.

The Package Structure

The Jacob has two packages:

  • com.jacob.activeX: package that contains the ActiveXComponent class.
  • com.jacob.com: It contains all the other classes and elements of the framework.

The Jacob Classes

The Jacob is a simple framework. Thus, he has few classes to know itself, looks at:

  • ActiveXComponent Class: This class provides a higher level, more object like, wrapper for top of the Dispatch object and is the base class to create an java object that encapsulates a COM object.
  • Dispatch Class: Object represents MS level dispatch object. Each instance of this, points at some data structure on the MS windows side. This will be the class more used by the programmer, for being the father class of all the other classes of framework. It has the methods also more used, as the methods call, callSub, get, invoke, invokeSub and put. These methods are explained after.
  • Variant Class: The multi-format data type used for all call backs and most communications between Java and COM. It provides a single class that can handle all data types. It maps the COM Variant datatype.
  • ComException Class: Standard exception thrown by COM JNI code when there is a generic problem.
    ComFailException Class: COM Fail Exception class, raise when there is a problem with a call to the COM class.

The Jacob Methods

The methods of the Jacob make the calls to the methods of COM/DLL objects and also they allow set values to the properties of COM/DLL objects. The methods most used are:

  • call method: method of the Dispatch class, is used to call methods of the COM/DLL objects. This method has several implementations that allow you flexibility in their use. It may return the result of the called method in a Variant variable. It must be used in the place of invoke method.
  • callSub method: equal to the method call, however does not return a Variant.
  • get method: used to get the value of a property of the COM object. The value is returned in a Variant variable.
  • put method: used to set the value of a property of the COM object.
  • invoke method: equal to the method call, however it is more difficult to use, prefers method call.
  • invokeSub method: equal to the method callSub, however it is more difficult to use, prefers method callSub.
  • getProperty method: method of the ActiveXComponent class. Retrieves a property and returns it as a Variant.
  • setProperty method: method of the ActiveXComponent class. Set a property of the object.

The second Example – call of a DLL

Creating a DLL

This step was created with Delphi 2005, however is possible to use any tool that has supported the development of DLLs. Open the Delphi Tool.

  1. Create the DLL. Go to File > New > Other > ActiveX > ActiveX Library > Ok.
  2. Save the Project. Go to File > Save All > Choose a Directory and a Filename (e.g.: TestJacob.bdsproj).
  3. Create an Automation Object. File > New > Other… > ActiveX > Automation Object > set JacobObject value to the coClass Name field > Ok.
  4. Save the files. File > Save All > Save the TestJacob.tlb > Save the second file with TestJacob_Unt.pas.
  5. Create the property. Go to View > Type Library > Select IJacobObject > Click with the right button > New > Property > set computerName value to the name of the property > set BSTR value to the type. Delete second property (put property, this property is read only).
  6. Click in the Refresh Implemetation button. Minimize Window.
  7. Go to the implementation unit. Go to View Unit Button (Crtl + F12) > Choose TestJacob_Unt file.
  8. Implement the function Get_computerName, with the below code.
  9. Include the SysUtils and Windows units to the uses clause in the top of the file.
  10. Save the Files. Go to the File > Save All.
  11. Register the DLL. Go to the View Menu > Type Library > Click in the Register Type Library.
function TJacobObject.Get_computerName: WideString;
var
CompName: array[0..256] of Char;
i: DWord;
begin
i:=256;
GetComputerName(CompName, i);
result:=StrPas(CompName);
end;

Observation: to register the DLL in the DOS command is regsvr32 <nome do arquivo> and regsvr /u <nome do arquivo> to unregister

Create the Jacob Java Code that uses the DLL

  1. Open the JBuilder Project used in the first example.
  2. Create a New Class in JBuilder.
  3. Implement the below code and run the program class.
package jacobproject;

import com.jacob.activeX.ActiveXComponent;

public class DLL {
    public DLL() {}

    public static void main(String[] args) {
        ActiveXComponent oWord = new ActiveXComponent("JacobDLL.JacobObject");
        System.out.print(oWord.getProperty("computerName"));
    }
}

Ready! This is example is running!

Alternatives to the Jacob

The are alternatives to the Jacob framewok, look:

  • Jawin: The Java/Win32 integration project (Jawin) is a free, open source architecture for interoperation between Java and components exposed through Microsoft's Component Object Model (COM) or through Win32 Dynamic Link Libraries (DLLs).
  • Java2COM (commercial): is a bi-directional Java-COM bridging tool that enables Java applications to use COM objects and makes possible to expose Java objects as if they were COM objects.
  • JNI: JavaTM Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the JavaTM virtual machine* into native applications.

Conclusion

Framework Jacob is a good option to natively integrate the languages that support DLLs (VB, Net, Delphi, C++, etc) and the Java. Before, the developers had to write all the mapping code and to understand complex interface JNI to carry through a simple call of ActiveX or DLL component. As we saw the Jacob is extremely simple. It is enough to know some basic methods (invoke, call, put, getProperty and setProperty) and two classes (ActiveXComponent and Dispatch).

References

  • Ruhl, K.. Tutorial: Jacob & Microsoft Word. http://www.land-of-kain.de/jacob/. (Jun. 2003).
  • Jacob Official Web Site. http://sourceforge.net/projects/jacob-project.
  • Jawin Official Web Site. http://sourceforge.net/projects/jawinproject
  • JNI Official Web Site. http://java.sun.com/j2se/1.4.2/docs/guide/jni/index.html.
  • Java2COM Official Web Site. http://www.argussoftware.net/products/com_argus_java2com.html


Server Response from: ETNASC03