Integrate your Java agenda and ICalendar clients (Outlook) with iCal4jIntroduction This post concerns integrating a calendar/agenda you created in your Java application with external clients. This integration is a relevant feature, because applications are not released in a void, but in a world where people already use several applications, among which often there is a beloved calendar client, typically Microsoft Outlook. Then there are all the non-Microsoft people, with several different clients and tools (see here for a list). So if you build a group calendar management, by making it interact with the agenda clients you will be considerably lowering the adoption barrier for your groupware.
What's nice of the presented solution is that
- it works with most clients, through the ICalendar standard,
- is compatible with the presence of a calendar group server,
- its very light: we just use e-mail headers and a simple textual standard (ICalendar).
In particular this solution requires just development effort, but no investment in expensive components.
Your Java applicationWe assume that you have built a solution to keep track in Java of your team's calendar; in the following, we will at times refer to our implementation, which is embedded in Teamwork, a groupware/project management solution.
Your implementation will have to manage recurrent events of the different kinds; this is a non trivial task: you have to manage daily, weekly, monthly and yearly recurrences; here some screenshots of Teamwork's editor (notice also that this is a natural example where to apply Ajax in your web editor to reload the different editing combinations):
SINGLE

DAILY

WEEKLY

MONTHLY

YEARLY

One of the hardest parts to develop is answering (fast!) to questions like "when will the two appointments 'all 4th of month' and 'every Tuesday every two weeks' next intersect? Outlook does all of this, so you too need to provide a formalization in your app in order to be able to synch with it. Our basic interface is the following:
Schedule.java
... public interface Schedule { Date getStartDate(); Date getEndDate(); long getDurationInMillis();
int getFrequency(); int getRepetitions();
boolean contains(Date date); boolean overlap(Period p); Collection getPeriods(Period p, boolean trim);
Date getNextDateAfter(Date afterTime); Date getPreviousDateBefore(Date beforeTime); } ...
Your code will have to mix usage of database queries and algorithmic calculations, all optimized for best performance. Brute force is bound to fail, given that there may be hundreds (or thousands) of events scheduled without an end.
Start and end dates are used for first filtering candidates events when querying the database, then for example with getPeriods you can extract for a given week the atomic events intersecting it.
The schedule interface has Single, Daily, Weekly, Monthly and Yearly implementations.
People (or "resources") involved in the appointments will be identified by their e-mail in the synch process, and actually this is what Outlook does when you "invite" resources to join meetings.
iCal4jA basic free tool which you could use is the iCal4j API, through which you can generate Java objects modeling ICalendar messages. In our implementation, we had to add a "fake" property to the set provided by iCal4j because of problems with the "CN=..." format, but this is a side detail.
ActionThe flow of group meetings creation, editing and approval can go in several directions, and you have to handle all of them. We consider a few cases.
Create event in Teamwork and send copy to clientsFor this, after saving its internal event, your application must send an e-mail to every participant, containing the V-event generated with iCal4J. You should insert in the V-event the organizer and the attendees. Set as "UID" of the V-event your event id. To make Outlook recognize it as a calendar event, set in the e-mail header
"text/calendar;method=REQUEST;charset="UTF-8"
and Outlook will recognize it, presenting the mail received as in the picture.

The appointment will be put in Outlook's calendar when received, and it will be possible to accept it or not. Recall to test receiving events also in Outlook 2007, as there the compatibility with ICalendar has been extended, and so the handling of the Organizer is different; in particular if you want to receive your events as subscribable ones in a 2007 client, ironically you must not be set as organizer of those events, otherwise the client will (rightly, from its point of view) not allow you to add them to your local calendar, assuming that the event already exists. Notice that if you update an event in your app, and resend it, Outlook will recognize it as an instance of the preceding event, and automatically update it - very nice! This you get by setting the UID field.
Create event in Outlook and make your app aware of thisWe did this simply by making our application capable of downloading e-mail. Hence when you create your appointment in Outlook, you just "send" it to your app, by having among the attendees the e-mail of it. If for example your app downloads e-mail at the sample@infoq.com address, put this e-mail among the attendees:

You need to have a scheduled e-mail download (and hence a job handler), and to parse the received relevant string body part in a V-event, which too is provided by the Ical4j API. To recognize the e-mail received as one relative to calendar, look at the content type which will be "text/calendar". Once you've built your ICalendar instance
CalendarBuilder cb = new CalendarBuilder(); Calendar iCalendar = cb.build((InputStream)message.getContent());
you have to consider the cases Method.REQUEST.equals(iCalendar.getMethod()) ...
and by working on the V-event UID you can decide whether to create or update an event in your app, which will be the final step.
Notice that you will also receive "DECLINED" events, in which case you must remove that attendee from your event.
ConclusionThe outline above can proceed further by handling people who want to remove themselves from events, it all works by handling correctly the UID field. Then it is natural to proceed in the integration by exporting contacts from the mail client to your application; this is exactly how we proceeded in Teamwork's case, but this is another matter.
Sources of our current Java implementation of the agenda (embedded in Teamwork) which may inspire you will be published on Sourceforge in the forthcoming release of Teamwork (3.2.0) due by the end of June (2007 ;-)).
ContactsAuthors: Roberto Bicchierai and Pietro Polsinelli E-mail: info@twproject.com
Microsoft Outlook and Exchange Server are (c) Microsoft Corporation. Mozilla Thunderbird is (c) the Mozilla Corporation. iCal4J is Copyright (c) 2006, Ben Fortuna. See http://ical4j.sourceforge.net/.
|