Google Calendar (http://www.google.com/calendar) is one of the many services offered by Google. It allows users to manage a personal or shared agenda on line, from the comfort of their own browser. In an easy to use web interface, agenda entries can be created and edited. Google Calendar can also send notifcations for events, as email, SMS or popup.
One of the nice things about Google Calendar is the fact that it offers an API: a programmtic interface that we can access to retrieve information about Calendar Entries, and also to create, update and delete entries or their details. This means for example that we can integrate the Calendar into our own applications, presenting Agenda entries in any format we desire.
In this article, I will describe how I linked up an Oracle ADF Web Application – created in JDeveloper 11g Technical Preview 2 (I had an issue getting it to run properly in TP3) – with Google Calendar and used the ADF Rich Faces Data Visualization component Gantt Chart for an alternative presentation of the Calendar entries.
Note: eventually, when the Gantt Chart component can be used to manipulate tasks as well as just present them, we should be able to extend this application and manipulate the Google Calendar data from it as well.
The steps to take:
- download the Google Calendar API Java Client API
- create a new JDeveloper application and project; add Google Calendar API libraries to it
- create a class GoogleAgendaManager that accesses Google Calendar to return the entries for a specific Calendar; implement a main method that displays the agenda entries so we can easily test this class
- create classes EventManager and Event; the first one can be used as a Business Service (interface) to return collections of the second; these can be acquired using GoogleAgendaManager but could also come from somewhere else
- create an ADF DataControl for class EventManager
At this point, we can start the Web part of the application, the ADF Faces application that leverages this Data Control and indirectly Google Calendar. Note that the Web Application needs to know nothing about Google Calendar.
- create a Web project; add ADF Faces and Data Visualization tag libraries
- create a new JSF page
- drag EventManager DataControl to this page; drop it as a Gantt Chart (schedule); configure the Gantt Chart data properties
- run the page
And we have done it! The browser displays the ADF Faces Gantt Chart component with the Calendar Entries retrieved from Google Calendar:
Here is our ADF Faces application:
And here the original overview in the Google Calendar Web View
There is a lot we can do to enhance, tune, refine the presentation of the agenda entries in the ADF application. This article is primarily meant as a proof of the concept.
Step by Step getting it to work
1. Download the Google Calendar API Java Client API
Go to http://code.google.com/apis/calendar/developers_guide_java.html , read the instructions and download the libraries at http://code.google.com/p/gdata-java-client/downloads/list (for example the file gdata.java-1.15.2.zip). Extract the zip-file to a temporary directory.
2. Create a new JDeveloper application and project; add Google Calendar API libraries to it
Create a new application, for example GoogleCalendarWebFrontend with an empty project – for example CalendarClientAndService. Create a lib directory under this project and copy the jar files in subdirectory googleCalendar\gdata\java\lib to this lib directory. Next add these jar-files, or at least these:
to the project.
3. Create a class GoogleAgendaManager that accesses Google Calendar to return the entries for a specific Calendar; implement a main method that displays the agenda entries so we can easily test this class
A very simple implementation of this class that retrieves all entries from a private calendar – note that you have to provide your own Google account’s username and password – looks like this:
package nl.amis.googleCalendar;
import com.google.gdata.client.calendar.CalendarService; import com.google.gdata.data.calendar.CalendarEventEntry; import com.google.gdata.data.calendar.CalendarEventFeed; import com.google.gdata.data.extensions.When; import com.google.gdata.util.AuthenticationException; import com.google.gdata.util.ServiceException;
import java.io.IOException;
import java.net.MalformedURLException; import java.net.URL;
import java.util.ArrayList; import java.util.Date; import java.util.List;
import nl.amis.events.Event;
public class CalendarManager { public CalendarManager() { }
public void showEvents() throws AuthenticationException, MalformedURLException, IOException, ServiceException { // Create a CalenderService and authenticate CalendarService myService = new CalendarService("AMIS-GoogleCalendarManager-1"); myService.setUserCredentials("your.account@gmail.com", "yoursecretpassword");
// Send the request and print the response URL feedUrl = new URL("http://www.google.com/calendar/feeds/your.account@gmail.com/private/full"); CalendarEventFeed resultFeed = myService.getFeed(feedUrl, CalendarEventFeed.class); for (int i = 0; i < resultFeed.getEntries().size(); i++) { CalendarEventEntry entry = resultFeed.getEntries().get(i); System.out.println("\t" + entry.getTitle().getPlainText()); List<When> times= entry.getTimes(); for (When when:times) { System.out.println(when.getStartTime()+" - "+when.getEndTime() ); } } }
public static void main(String[] args) throws AuthenticationException, MalformedURLException, IOException, ServiceException { CalendarManager calendarManager = new CalendarManager(); calendarManager.showEvents(); } }
When I run this class, the output looks like:
4. Create classes EventManager and Event; the first one can be used as a Business Service (interface) to return collections of the second; these can be acquired using GoogleAgendaManager but could also come from somewhere else
EventManager: (I cheated a little on the exception catching for brevity)
package nl.amis.events;
import com.google.gdata.util.AuthenticationException; import com.google.gdata.util.ServiceException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List;
import nl.amis.googleCalendar.CalendarManager;
public class EventManager { public EventManager() { }
public List<Event> getEvents() { CalendarManager calendarManager = new CalendarManager(); List<Event> events = new ArrayList(); events = calendarManager.retrieveEvents(); Collections.sort(events); return events; } }
and Event:
package nl.amis.events;
import java.util.Date;
public class Event implements Comparable { String title; Date startTime; Date endTime; String id; public Event() { }
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
public void setStartTime(Date startTime) { this.startTime = startTime; }
public Date getStartTime() { return startTime; }
public void setEndTime(Date endTime) { this.endTime = endTime; }
public Date getEndTime() { return endTime; }
public void setId(String id) { this.id = id; }
public String getId() { return id; }
public int compareTo(Object o) { return startTime.compareTo( ((Event)o).getStartTime()); } }
I also add the following method to the CalendarManager class, in order to make a list Events available to the event manager:
public List<Event> retrieveEvents() throws AuthenticationException, MalformedURLException, IOException, ServiceException { // Create a CalenderService and authenticate CalendarService myService = new CalendarService("AMIS-GoogleCalendarManager-1"); myService.setUserCredentials("your.account@gmail.com", "yoursecretpassword");
URL feedUrl = new URL("http://www.google.com/calendar/feeds/your.account@gmail.com/private/full"); CalendarEventFeed resultFeed = myService.getFeed(feedUrl, CalendarEventFeed.class); List<Event> events = new ArrayList(); for (int i = 0; i < resultFeed.getEntries().size(); i++) { CalendarEventEntry entry = resultFeed.getEntries().get(i); Event event = new Event(); event.setId(i); event.setTitle(entry.getTitle().getPlainText()); List<When> times= entry.getTimes(); for (When when:times) { event.setStartTime( new Date( when.getStartTime().getValue())); event.setEndTime( new Date( when.getEndTime().getValue())); } events.add(event); }// for return events; }
5. Create an ADF DataControl for class EventManager
The effect is the creation of a number of XML files that together define the EventManager Data Control
The Web Application
1. Create a Web project; add ADF Faces and Data Visualization tag libraries
2. Create a new JSF page – for example GoogleCalendarGantt
3. Drag EventManager DataControl to this page; drop it as a Gantt Chart (schedule); configure the Gantt Chart data properties
Edit the Task Settings for the Gantt Chart (note we do not deal with Subtasks, Split Tasks and Dependent Tasks for the moment).
4. Run the page
Note: when I tried to do the same thing in JDeveloper 11g TP3, I ran into issues: after deploying the application, it seemed that the Google Calendar API Service could not be reached (debugging showed that everything went as planned right up until the moment the Google service was accessed). I have asked for help on the JDeveloper 11g TP Forum, since I do not know what is causing this issue.
Hi,
Thx for the interesting article…
I just wanted to let you know that the example works fine in TP3 …
no problems whatsoever
Kind regards
Bert
Nice work. Is there a way to accomplish the same functionality with ADF 10g?