Friday, November 30, 2012

Google Calendar API

Why do we care about Google Calendar API?


Reuse

Development is expensive. Let's face it. Hacking through all kind of development issues takes time and time costs, quite a lot. One of the solutions to this problem is reusing.

Developers reuse all the time - libraries, application servers, even "Googling" for errors. Using remote API is quite the same, but in larger scale.

Integrate

Using publicly available service API has one important feature that makes it different from library - integration. Probably you are not the only one who integrates with that service. You join the community.

Nowadays, most popular web resources offer remote APIs. Google is one of them. It offers wide range of services that people use in everyday life, covering many trivial and not so trivial tasks that might be required in your project. And guess what? Google wants to share it with you! For this purpose they offer impressive amount of different APIs. One of them is Google Calendar API and today we are going to focus on that. If you are not that interested in calendar, this blog still might give you some hints about other APIs, because there are many things in common.

What can you do with it?

Once upon a time we had a research project. It was not about remote APIs. It was about using HTML5 for mobile development. At the same time, we wanted to make something useful. That's how Conference App was born.

Idea behind this application is to make a convenient conference schedule for mobile devices. Idea comes from personal experience, as many people from our company visit conferences and some even organize them. Usually, schedule printed on paper is either informative or compact, but not both at the same time.

Some time ago I used Google calendar for storing conference schedule and it worked. I was able to enter all events on my laptop, I was able to check the schedule on my Android device and I was able to share this calendar. However, it was a bit inconvenient. Mainly because of the way how many events happening at the same time are displayed.



Our application was supposed to take all the good stuff, fix the bad stuff and put it into conference context. Google Calendar desktop UI can handle lot's of complex stuff, but it comes with a price. We removed all the complexity and left only what is need for current task.


This is a screenshot from conference app. It shows exactly the same calendar.

How does it work?

Now we are done with introduction and will move to stuff that should interest developers a bit more. Let's see some technical details.

REST

Google Calendar API 3 uses REST. Payload is JSON. It replaced Atom based GData protocol. Old version 2 API is still there, but I'm not sure if it will be discarded at some point. Actually, initially our Conference App was using version 2 and I migrated it to version 3 only when started preparing this blog post. Migration to new version is not very tricky. There is a nice migration guide. If you are still using API v2 - migrate.

Client libraries

REST API assumes that you can make requests to it using any HTTP capable tool and format of requests and responses is described in details in reference documentation. However, Google APIs are quite complex and it is highly recommended to use client libraries. Client libraries are available for quite a large amount of languages and frameworks.



Python is in the center, because this is the only library that does not have "alpha" or "beta" status. Libraries above Python have "beta" status and libraries below have "alpha" status. We used Java library and did not have any significant issues, even though it has "beta" status.

Collections

As any other well structured REST API, Google Calendar API is split into collections of resources.
  • ACL
  • CalendarList
  • Calendars
  • Colors
  • Events
  • Freebusy
  • Settings
Most of those collections support CRUD operations. Some support only a subset of CRUD. Some have extra operations. This is a typical set:
  • delete
  • get
  • list
  • insert
  • update
  • patch
  • ...


Putting it all together

This is a Java sample that takes event summary from each item in "Events" collection. Parameter to "list" method is not a real calendar id, so sample will not work.

Events events = calendar
 .events()
 .list("eimems5@group.calendar.google.com")
 .execute();

for (Event event : events.getItems()) {
event.getSummary();
}

Quite easy. If someone has seen second version of this API, he will notice, that now it takes much less code.

Authorization

It's quite obvious, that remote API access has to be secure. All requests to Google Calendar API require OAuth2 authorization. Actually, not only Calendar API. Other APIs use same process. 

Idea behind OAuth2 authorization is quite simple and elegant, but implementation is not always that obvious and it is another reason for using client libraries.

By the way, there is a simpler OAuth version 1 that you can use, but version 2 is preferred.

Different applications (and even different devices) require different authorization flows and Google has something to offer.

Client-side applications

JavaScript-centric applications. These applications may access a Google API while the user is present at the application.

Web server applications



These applications may access a Google API while the user is present at the application or after the user has left the application. This type of access to a Google API is called offline, since the user does not have to be present at the browser.

Installed application

These applications are distributed to individual machines. These applications may access a Google API while the user is present at the application or when the application is running in the background for long periods of time without direct interaction with the user. Like email checking in Android device.

Device applications

Applications that run on devices with limited input capabilities (e.g. game consoles, video cameras, printers) may access an API on behalf of a user, but the user must have separate access to a computer or device with richer input capabilities.

Service accounts


Service accounts can be used on behalf of an application when it does not access user information or accesses publicly available information. Used to identify application. Our application uses this scenario.

Scopes

Each authorization request provides scope that it want's to access. In other words, application might have a permission to read your calendar events, but without modification option.
Google will ask the user if he agrees with requested permissions.

Limits

Almost all Google APIs have limits, which is quite logical. For example, Calendar API has a limit of 10000 requests/day. In some cases it is possible to exceed the limits for extra fee according to the price list. In case of Calendar API there is no price list, only a form that you can fill to request quota changes. Not sure how it works, never tried. 10000 requests per day was more than enough for our project due to long time caching and the fact that we are using only one calendar. Basically this means that we are making only about 144 requests per day.

In case if your app is accessing user calendars, then amount of requests will depend on the amount of users. For this case, there is another limit that you can set in Google API Console - requests/second/user. Default is 5, but you can set it yourself. Personally, I think that you should use this feature only as a last resort and control it in application.


Other services

As I said before, Google offers APIs for quite a large range of services. Here are some of them. Don't be confused with font sizes in this cloud. Bigger font means my personal interest. Hope you can find something interesting for yourself!

Friday, November 16, 2012

Eclipse hint

I'm sure you had situations when Eclipse was behaving strange. Probably your first attempt is to clean and refresh the project. Sometimes it's not enough, but luckily there is a "brute force" method:

1) Delete project from workspace (don't delete it from filesystem)
2) Delete .settings, .project and .classpath and target (assuming that you use Maven)
3) Import project into workspace

There you go. Fresh checkout is another option, but does not work very well if you have uncommitted changes.

Tuesday, November 6, 2012

Continuous delivery with Jenkins and Gradle


www.ignite.ee


  To my mind, continuous delivery is a great thing that gives real value. However, it seems that setting up a proper build pipeline to support it is not a trivial task.

  My first attempt to make a build pipeline was based on Maven. I was using FOSS Jenkins instance, provided by CloudBees.

  Pipeline steps that interested me were:
  1. snapshot - runs unit tests and creates build artifact (WAR in my case)
  2. REST integration tests - deploys WAR and tests it's REST interfaces
  3. UI tests - deploys WAR and tests it's UI in different browsers
  4. release - updates versions and puts tags in SCM
  5. ... endless amount of other pipeline tasks
Some other requirements were:
  1. Use same SCM code version for all steps in pipeline
  2. Use only those Jenkins plugins which are available for free on CloudBees
  It was pretty easy to compile all required tasks in Maven life cycle and run them in sequence. However, as soon as I've started configuring jobs in Jenkins, it became clear that Maven life cycle does not match my pipeline. Simple "mvn install" turned into "mvn clean deploy -DskipITs" and "mvn failsafe:integration-test -P selenium". It was especially hard to configure jobs in the middle on the pipeline, because Maven tends to execute all preceding life cycle phases.

  You can find some of my attempts here: https://reference.ci.cloudbees.com/. In the end, I got it working but it did not feel right for sure.

  On June 14th I've visited conference called GeekOut, where Hans Dockter was showing Gradle. At first it seemed pretty much like Maven, but it had some features that looked quite promising to me:
  1. Gradle plugins provide Maven simplicity
  2. At the same time, it's incredibly easy to customize life cycle
  3. Incremental builds
  Here are my attempts to make a pipeline with Gradle: https://reference.ci.cloudbees.com/view/gradle/. Thanks to flexibility of Gradle I was able to fix life cycle according to my needs and incremental builds took care of skipping preceding steps. "mvn failsafe:integration-test -P selenium" becomes "gradle cleanUiTest uiTest". Now it does feel right!

  Some hints:
  1. If you want to start incremental build in one Jenkins job and resume it in other - make sure that absolute path to workspace stays the same. Otherwise, Gradle will start build all over. For example, if first job uses workspace /scratch/jenkins/workspace/1-snapshot-gradle and the second one uses /scratch/jenkins/workspace/2-rest-test-gradle, second job will not resume incremental build.