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.
hai Filippo,
Sorry to post here . But were you able to do what you intended ? If u did could you help me out ?
Actually i am almost in the same situation. I need to see whether it is possible to connect to a remote open office server without
local office installation. This i was able to do . But when i connect the UI actually pops up in the remote open office server .
I would want that to be shown in my system where open office is not installed..Hoping i didnt confuse u all
Thx Vouter It’s great work !!! – I use your tutorial in my work.
Hi, I find very useful what you describe in this tutorial. However I’ve a question. I see the OOoBeanViewer example in the developer’s guide and I would like to know wether it’s possible to embed an OpenOffice gui into a java program connecting to a remote OpenOffice server. For the moment I tryed to customize the chapter 6 Desk example but I didn’t achieve any result.
Could anyone help me?
Thanks a lot
Filippo
Hi,
This is the first time i am working on office API and i am having a tough time in getting the configurations right. I have been to a number of forum on the oooforum but nothing seems to be working out.
This is what i intend to do, which was supposed to be a very simple thing to do. I want to creat a simple hello world application.
And the error i am getting is like many like me that is “No office executable found!” i have windows XP, and i am using Eclipse IDE, i have made a seperate folder for the Lib files and put all the files mentioned in the article including sandbox in the lib but i do not know how can i add the path of the soffice.exe(D:\OpenOffice.org 2.0\program) in the classpath as it is not a zip/jar file. I presume this is my problem.
If you could help me and tell me how to include the soffice.exe in the path i guess i might get lucky in getting this thing to work.
Best Regards
Hi!
I receive a message “no office executable found!” when juh.jar is not in the same
directory as the office executable.
Beacuse of portabillity, I want juh.jar in my lib folder.
Is there any solution to solve this?
Thanks
Hm… this OO-API is really infernal ;>… no, it didn’t work… there should be a way actually to figure out what thing it is, that NetBeans is doing automatically whereas it has to be done manually on the commandline…
What possibilities of diagnostics are there to know more about the cause of the problem? Would it help to download the sourcecode to see where its getting stuck exactly?
*g* By the way – this might be a very interesting fourth chapter: Diagnostics of OOo-API – Tools that help you to know where the problems are. I’d like to contribute. ;>
Hi Ingo,
It looks to me like your CLASSPATH isn’t correct. Yuo write
CLASSPATH=
/usr/lib/ooo-2.0/program/classes/java_uno.jar:
/usr/lib/ooo-2.0/program/classes/juh.jar:
/usr/lib/ooo-2.0/program/classes/jurt.jar:
/usr/lib/ooo-2.0/program/classes/jut.jar:
/usr/lib/ooo-2.0/program/classes/ridl.jar:
/usr/lib/ooo-2.0/program/classes/unoil.jar:
/usr/lib/ooo-2.0/program/classes/unoloader.jar:
/usr/lib/ooo-2.0/program/soffice
export CLASSPATH
but I think the one but last line should read
/usr/lib/ooo-2.0/program
Please note that the path to the directory holding the soffice executable should be on the CLASSPATH, not the path to the executable itself.
Regarding your second comment, about starting OOo in listening mode, this only helps if your client connects to the host and port that OOo is listening on. By the fact that you still get the “no office executable found” message I think you still try to start OOo locally.
HTH, Wouter
PS: I tried now to start OOo with the parameter
-accept=”socket,host=localhost,port=8100;urp;”
In the Java-Code the UnoUrl is
“uno:socket,host=localhost,port=8100;urp;StarOffice.ServiceManager”;
The netstat-tool shows, that office indeed is listening… but there’s still the message:
“no office executable found!”
Hi Folks!
First: my compliments about these three Tutorial-parts.
I’ve got the problem, that I can access OOo via Netbeans perfectly, but it doesn’t work when I try it via console.
My CLASSPATH-Variable in /etc/profile.local looks like that (one single string in the file, here I use linebreaks to make checking easier):
CLASSPATH=
/usr/lib/ooo-2.0/program/classes/java_uno.jar:
/usr/lib/ooo-2.0/program/classes/juh.jar:
/usr/lib/ooo-2.0/program/classes/jurt.jar:
/usr/lib/ooo-2.0/program/classes/jut.jar:
/usr/lib/ooo-2.0/program/classes/ridl.jar:
/usr/lib/ooo-2.0/program/classes/unoil.jar:
/usr/lib/ooo-2.0/program/classes/unoloader.jar:
/usr/lib/ooo-2.0/program/soffice
export CLASSPATH
I use SuSE-LInux 10.1, Java 1.5.0_07 and OpenOffice 2.02.
Tnx for your help.
Cu,
Ingo
Hi Auio,
The “no office executable found” error usually arises when either the path to the directory the office executable (soffice.exe on Windows, soffice on other OSes) is not on the classpath, or juh.jar is not in the same directory as the office executable. Can you tell me a bit more about the OS and the OOo version and install that you’re using? Perhaps my third article about OOo,
http://technology.amis.nl/blog/?p=1284
might help you?
Greets, Wouter
Hi,
I cannot connect to OO from a JSP under Tomcat.
Using the bootstrap call:
xContext = com.sun.star.comp.helper.Bootstrap.bootstrap();
I receive the following error:
com.sun.star.comp.helper.BootstrapException: no office executable found!
I can run the same code directly, from a test “main” java application.
Does anyone know what needs to be set for this to work from a servlet container, specifically Tomcat?
Thanks,
Hi Vekaz,
Thanks for the tip about adding OOoInstallDir/program to libraries. I wasn’t aware of that but it works like a charm!
As for having an OOo document inside a JFrame, have a look athe OfficeBean component. See
http://api.openoffice.org/docs/DevelopersGuide/OfficeBean/OfficeBean.xhtml
By the way, are you aware of the NetBeans plugin that integrates OOo into NetBeans? See
http://blogs.sun.com/roller/page/geertjan?entry=star_office_inside_netbeans_ide
Greets, Wouter
Wouter, I want to thank you for your help again. I almost quit on OOo SDK, it was so frustrating.
Without much explanation, this is what I did on Ubuntu to make the above code work:
– Create a new project,
– Add libs as you described above,
– Add OOoInstalDir/program to libraries (this is what fixed ‘no Office executable found!’, seems to be Debian-specific problem. Read this thread for details: http://www.mail-archive.com/dev@openoffice.org/msg02913.html)
And that’s all.
Note that it is not necessary to use Loader class and change Netbeans default run settings, even on Linux. Just make sure you do that third step.
Now, it would be great to know how to have a OOo document inside a JFrame in my app 🙂
Hi Vekaz,
Just checking to be sure: you did add the library to your project (it should be under Libraries -> Compile) and you did set the project properties under Run to reflect what I described in the article right? Is this is the case, please send a tar ball of your project to me (wouter DOT van DOT reeven AT amis DOT nl) and let me see what’s going on.
Greets, Wouter
Hi Wouter. Thank you for the reply.
The classes folder is already added to Libraries in Netbeans, and I can see Loader.class there, so it must be something else that is causing the error. Any other suggestions? I am running Netbeans 5 on Ubuntu Dapper and 1.5 JDK.
Sorry, the path is truncated by the blog software. It should be <SDK install>\classes on Windows and <SDK install> on Debian Linux.
Wouter
Hi Vekaz,
The com.sun.star.lib.loader.Loader class is in \classes on Windows and in Debian Linux. So the directory containing that package should be on your classpath. Can you explain what you’re trying to do exactly?
Wouter
Hi,
Thanks for the tutorial.
I can not get this to work, however.
I keep getting ClassDefNotFound: com/sun…/Loader