Getting started with the OpenOffice.org API part I : connecting to OpenOffice.org

OpenOffice.org is an open source office suite available for Windows, Mac, Linux and Unix. Despite several small issues, OpenOffice.org (OOo) is capable of opening, modifying and saving Microsoft Office (MSO) documents. Besides that, OOo has a very powerfull PDF exporter.For Java developers, the most interesting part of OOo may be the SDK that comes with it. The SDK exposes almost all OOo functionality and capabilities to Java through an API.
In a series of several blogs I will describe a part of this API. What part I will describe depends on my interest, my working together with Geertjan Wielenga of NetBeans and possibly whatever requests I get.

This is part I of the series. In this blog I will describe what is necessary to connect to OOo, what pitfalls you may encounter and how to prevent them. I will do my best to describe everything for both Windows and Linux, since I work on Windows but have my PC at home on Debian Linux. Also, my main developing IDE at home is NetBeans, but I’ll try to make everything as IDE independent as possible.

....

What do you need? 

In order to be able to connect to OOo via Java you need to components. First of all, you’ll need the OOo SDK. You can download the SDK from the main OOo website. At the time of this writing the OOo website seems to be undergoing some upgrades, so you may have to wait some time before it’s back up again.
On Windows, the installer that contains the SDK will prompt you for a location to install. I chose C:\java\OpenOffice.org_2.0_SDK but of course the location is up to you and it doesn’t really matter, as long as you remember where you put it.
On Linux, the OOo SDK should be avalable via your disti’s online install repositories. For Debian Linux, the package you need is called openoffice.org-dev and this will install all files into /usr/share/java/openoffice.

Besides the SDK you’ll need a few jar files. These jar files are shipped with OOo and can be found in <OOo install dir>\program\classes. On windows, the default install location is C:\Program files\OpenOffice.org 2.0 and on Debian Linux it is /usr/lib/openoffice. However, you DON’T need a complete OOo install in order to make use of it! Or rather, you don’t need a LOCAL installation of OOo to be able to use it. OOo can be started in server mode, listening to a port on a remote server through which you can connect. More on this later.
The jar files from <OOo install dir>\program\classes that need to be in your classpath are juh.jar, jurt.jar, ridl.jar and unoil.jar. Besides that, in some cases sandbox.jar also is needed though it is unclear to me at this moment when and why. The other jar files are needed for more exotic stuff that I won’t touch (yet).

Making a local connection

Let’s first try to connect to OOo locally. Reall that this needs both the SDK and OOo to be installed on your hard drive. First, define a library in your favourite IDE and call it OpenOffice.org. Make sure the four jars mentioned above (juh.jar, jurt.jar, ridl.jar and unoil.jar) are in it. That should be enough on Windows.
On Linux, however, it’s not. First of all, some classes that are shipped with the SDK need to be in the classpath as well. These classes can be found in <SDK install dir> and can be recognised by their package, which is com.sun.star.lib.loader. So, in your library definition also make sure ton include <SDK install dir>.
Second of all, the IDE (well, Java actually) also needs to be able to find the soffice.exe (on Windows) or soffice (on Linux) executable. On Windows this all happens automagically (one of the few benefits of Windows IMHO) but not on Linux unfortunately. Modify the project settings in your IDE in such a way, that the main class that is executed is

com.sun.star.lib.loader.Loader

that this class gets your main class (the one with the main method that is) as argument. Also, make sure the JVM get this property set as well:

-Dcom.sun.star.lib.loader.unopath="<OOo install dir>"

On Debian Linux, this line looks like this

-Dcom.sun.star.lib.loader.unopath="/usr/lib/openoffice/program"

If you’d like to run your app from the command line, make sure the CLASSPATH variable contains the four jar files (juh.jar, jurt.jar, ridl.jar and unoil.jar) and <SKD install dir> and issue

java -Dcom.sun.star.lib.loader.unopath="/usr/lib/openoffice/program" com.sun.star.lib.loader.Loader <your package>.<your class>

In general, if you’re not sure whether Windows or Linux users will use your code, please just make sure your main class is called in this way so everyone can enjoy your app.
Please note on Windows, the com.sun.star.lib.loader package resides in <SDK instal dir>\classes and this directory contains another directory. This directory is called win and contains a DLL called unowinreg.dll and this dll is needed to connect to the OOo API as described above.

So, it’s time for some code. Create a new Java class in your Project and call it MyFirstOOoConnection (or whatever you like). Next, copy and paste this code into the code editor for your class:

 

    public static void main(String[] args) {
        try {
            XComponentContext xLocalContext = Bootstrap.bootstrap();
            XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
            Object desktop = xLocalServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xLocalContext);
            XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);
            PropertyValue[] pPropValues = new PropertyValue[0];
            XComponent xComponent = xComponentLoader.loadComponentFromURL("private:factory/swriter", "_blank", 0, pPropValues);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

 

If all has been setup correctly, running this file should bring up the OOo desktop with an empty Writer document in it. Congrats!

Making a remote connection

Like I wrote before, no local install of OOo is needed to be able to connect to it from Java. Only the four now well known jars, the classes in that now also well known package and the lesser known DLL (only in case of Windows) are needed. But OOo ALWAYS is needed so if you don’t have it locally, you’ll need it remotely.
The soffice(.exe) executable may take several command line options. One of these options is "-accept". To start OOo in listening mode, start it like this

soffice -accept=socket,host=localhost,port=2002;urp;

Linux users: beware of the ; that are in this command line. Put the bit behind the = sign between double quotes. Next, modify the code in your MyFirstOOoConnection class to be

 

    public static void main(String[] args) {
        try {
 &nbs p;    &n bsp;     XComponentContext xLocalContext = com.sun.star.comp.helper.Bootstrap.createInitialComponentContext(null);
            XMultiComponentFactory xLocalServiceManager = xLocalContext.getServiceManager();
            Object urlResolver = xLocalServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", xLocalContext);
            XUnoUrlResolver xUrlResolver = (XUnoUrlResolver) UnoRuntime.queryInterface(XUnoUrlResolver.class, urlResolver);
            Object initialObject = xUrlResolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager");
            XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, initialObject);
            Object context = xPropertySet.getPropertyValue("DefaultContext");
            XComponentContext xRemoteContext = (XComponentContext)UnoRuntime.queryInterface(XComponentContext.class, context);
            XMultiComponentFactory mxRemoteServiceManager = xRemoteContext.getServiceManager();
            Object desktop = mxRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", null);
            XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(XComponentLoader.class, desktop);
            PropertyValue[] pPropValues = new PropertyValue[0];
            XComponent xComponent = xComponentLoader.loadComponentFromURL("private:factory/swriter", "_blank", 0, pPropValues);
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

 

Run the code and you should see an OOo desktop with an empty Writer document again.

Some pitfalls

The remote connection may be a bit of a problem. If you close the Wirter document, the connection is dropped. Also, if the connection fails for some reason (typo for instance) you’ll have to restart the remote OOo server again. Finally, the connection may be dropped due to a buggy network connection or a problem on the other hand of the connection. There is no way to know about this until it’s too late. For a solution to this, see the OOo Developer’s Guide, especially chapter 3.3.1 and the Example: A Connection Aware Client.

Where to go next

Have a good look at the Developer’s Guide. It’s very helpful and gives a lot more info than the API documentation. And keep an eye on this blog site. I’ll be back later this week for part II.

18 Comments

  1. martin joseph August 4, 2009
  2. Tomasz Marcinek November 3, 2007
  3. Filippo June 8, 2007
  4. Abhinav August 21, 2006
  5. Goran August 18, 2006
  6. Ingo Beyerlein August 10, 2006
  7. Wouter van Reeven August 10, 2006
  8. Ingo Beyerlein August 8, 2006
  9. Ingo Beyerlein August 8, 2006
  10. Wouter van Reeven July 20, 2006
  11. Auio July 12, 2006
  12. Wouter van Reeven June 25, 2006
  13. vekaz June 25, 2006
  14. Wouter van Reeven June 25, 2006
  15. vekaz June 25, 2006
  16. Wouter van Reeven June 24, 2006
  17. Wouter van Reeven June 24, 2006
  18. vekaz June 24, 2006