User Guide for the JOGI APImurphee, last modified 31st January 2004 (updated for 0.0.4EA release)
The JOGI API allows you to access the functionality provided by an OpenGroupware.org installation. Currently this is achieved by using the XML-RPC interface of OpenGroupware.org ("currently" because the API definition does not depend on XML-RPC and future versions might use other means (CORBA, direct connection of Java to ObjectiveC code,...) to provide the functionality).
Use the source...
As you're probably a developer, you will appreciate sample source much more than a long introduction. Well, here it is:
1: XmlRpcCaller caller = new ApacheXmlRpcCaller("http://localhost:20001/RPC2", "username", "password"); 2: XmlRpcConnection conn = new XmlRpcConnection(caller); 3: OpenGroupWare ogo = conn.getOpenGroupWareInstance(); 4: Date d = ogo.getSystem().getServerTime(); 5: ContactManager conMan = ogo.getContactManager(); 6: Iterator results = conMan.fetchPersons(new FetchSpecification("name like 'foobar'")); 7: // ... do stuff 8: conn.closeConnection();
This code opens an XmlRpcConnection to a server where (hopefully) an OpenGroupware.org server is running in the lines 1-2. In line 3 an instance of OpenGroupWare is fetched from the XmlRpcConnection, which of course only works if the connection was successfully opened. With the OpenGroupWare object, you can access the functionality of the server. Eg. in line 4 the servers current time is fetched. Line 5 fetches the ContactManager instance for this connection. The ContactManager allows you to manage the contacts (Person or Enterprise entries) on the server. Line 6 shows how to get all Person objects that have a name like "foobar". The result of this call is a java.util.Iterator that allows to access the Person objects of the result or null if none were found.
The fetch() methods (and all methods that might return a lot of data) return Iterators and not Lists. This comes from the fact that most of the time, programmers need to iterate over all or some of the results, which they will do with an Iterator anyway. The other, more important, reason is to allow future implementations to make better use of streaming XML-RPC. The problem with returning a List is, that the whole data needs to be in the memory. For big amounts of result data, this can prove to be a problem. Some solutions, like having a List implementation that would allow lazy loading in the background, would of course be possible, but as stated above, most programmers would use an Iterator anyway, so this should not be a problem. If you have comments or an diverging opinion on this, please refer to Opengroupware.orgs XmlRpc MailingList Archive, which contains the discussion that lead to this design decision.
And, last and least, on line 8 the connection is closed; this should only be done if you do not need any of the objects fetchedanymore. You will still be able to access some data, but many calls need a connection to the server and will cause a flurry of Exceptions if you use them after having called close().
Well, after this sample, lets get into some details.
The XmlRpcCaller interface
This Java interface allows to exchange the XML-RPC library used. This is necessary, as there are several XML-RPC libraries out there that expose their functionality in (slightly) different ways. JOGI invokes XML-RPC calls solely through an object with the XmlRpcCaller interface, and thereby allows the developer to use an XML-RPC library of his own choice. This also allows to have more control over the XML-RPC library that is used. For example, if secure communication is desired, the developer can simply write an object implementing XmlRpcCaller that sets the XML-RPC library up to use an SSL connection
ApacheXmlRpcCallerJOGI comes with the org.opengroupware.jogi.connect.xmlrpc.ApacheXmlRpcCaller class that uses the Apache XML-RPC library. You can use this class if you do not have any special requirements for XML-RPC. The required library (.jar file) is also included in the JOGI distribution.
Rolling your own XML-RPC Adapter
Writing an own implementation of XmlRpcCaller is actually trivial. One point is implementing the invoke() method(s) (the current release comes with 3 overloaded invoke() methods, this might change in the future). This comes with the name of the function to call and a java.util.List containing the arguments. The arguments in the List might be any Wrapper objects for Primitives or Java Collection classes (anything implementing List or Map).
The other methods are the setter and getter methods for User and Password. Please make sure you fully implement them, as they might be used by the JOGI API. (The reason for this is the stateless nature of XML-RPC. This means, that each function call is a new HTTP request that must be authenticated using BasicAuthentification. Now, if the password of the Account (that is used to access the server) is changed during the XmlRpcConnection, there must be a way to tell this to the XmlRpcCaller so it can use the new password. If that would not be possible, future function calls would simply fail (as authentification fails).).
This class doesn't really do much but provide you access to the OpenGroupWare object after the connection was sucessfully established. The raison d'etre for this class is future support for different connection types.
You access all the data and functionality of OpenGroupware.org using one of the *Manager classes. They provide access to the data on the OpenGroupware.org installation. They are singletons (at least relative to a specific XmlRpcConnection), ie. each call to one of the get*Manager() methods of the OpenGroupWare object will return the same object.
One thing the Managers have in common is the fetch* methods that allow to query the objects that a Manager contains using a simple query, as can be seen in the sample above. For more information about the syntax of these queries, please refer to the OpenGroupware.org documentation. It must be noted, that the objects returned by the Managers are Singletons as well; ie. if an data object has already been fetched from the server, then subsequent queries or fetch calls (that return this object) will always return the reference to this object which will be updated with new data (if its content have changed on the server). This means you can check for equality with then == operator.
Please refer to the JOGI API documentation for more detailed information on the functionality offered by the Managers.
JOGI accesses OG.o using XmlRpc, probably using a TCP/IP network; this is risky and all kinds of bad things can happen to a lonely little request: the XmlRpc encoding fails, the network is not available or fails in some other way, OG.o does not like a request and throws an exception itself,... You get the idea. After initial experiences with JOGI and user feedback, the need for proper error reporting was seen.
The decision to use exceptions was an easy one, as they native to Java. The use of checked exceptions (ie. exceptions, that
must be handled and cannot be ignored, unlike unchecked exceptions like
NullPointerException) is the
result of long consideration and a lot of research. Checked exceptions were chosen, because JOGI uses potentially
dangerous operations (I/O, networking,...) and Javas standard library also uses checked exceptions for them.
This exception is thrown, when the OG.o server, that is accessed, throws some error or exception in response to the request.
If something happens on the way between JOGI and the OG.o server, the ConnectionException is thrown.
If an update fails, an UpdateException is thrown. Updates can go wrong because of connection problems, caching problems or other issues.
This little guide should provide you with enough information to get started with the JOGI API. For further on the classes information consult the Javadoc or drop a mail to the ogojogi-developer mailing list (Note: only questions concerning JOGI; for questions about installing, configuring, etc. of OpenGroupware.org refer to their mailing lists).