Friday, May 18, 2012

Java simple iCalendar iCal4j example

iCalendar is a computer file format which allows Internet users to send meeting requests and tasks to other Internet users, via email, or sharing files with an extension of .ics. iCal4j is an API which is used to modifying existing iCalendar data or creating new iCalendar data. To know more about iCal4j, click here.

About the example

ICalendarExample.java will create a .ics file lets say mycalendar.ics. It will create a calender event, you can customize it according to your requirement. You can send this generated file via email.

For running below example you will need to add below mentioned JAR files in your classpath.
  • ical4j-1.0.3.jar
  • backport-util-concurrent-3.1.jar
  • commons-logging-1.1.1.jar
  • commons-lang-2.6.jar

To download the above JAR file, click here.

/* ICalendarExample.java */

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;

import net.fortuna.ical4j.data.CalendarBuilder;
import net.fortuna.ical4j.data.CalendarOutputter;
import net.fortuna.ical4j.data.ParserException;
import net.fortuna.ical4j.model.Component;
import net.fortuna.ical4j.model.Date;
import net.fortuna.ical4j.model.Property;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.model.component.VEvent;
import net.fortuna.ical4j.model.parameter.Value;
import net.fortuna.ical4j.model.property.CalScale;
import net.fortuna.ical4j.model.property.ProdId;
import net.fortuna.ical4j.model.property.Version;
import net.fortuna.ical4j.util.UidGenerator;

public class ICalendarExample {

 public static void main(String[] args) throws IOException, ValidationException, ParserException {
  
  String calFile = "mycalendar.ics";
  
  //Creating a new calendar
  net.fortuna.ical4j.model.Calendar calendar = new net.fortuna.ical4j.model.Calendar();
  calendar.getProperties().add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
  calendar.getProperties().add(Version.VERSION_2_0);
  calendar.getProperties().add(CalScale.GREGORIAN);
  
  //Creating an event
  java.util.Calendar cal = java.util.Calendar.getInstance();
  cal.set(java.util.Calendar.MONTH, java.util.Calendar.DECEMBER);
  cal.set(java.util.Calendar.DAY_OF_MONTH, 25);

  VEvent christmas = new VEvent(new Date(cal.getTime()), "Christmas Day");
  // initialise as an all-day event..
  christmas.getProperties().getProperty(Property.DTSTART).getParameters().add(Value.DATE);
  
  UidGenerator uidGenerator = new UidGenerator("1");
  christmas.getProperties().add(uidGenerator.generateUid());

  calendar.getComponents().add(christmas);
  
  //Saving an iCalendar file
  FileOutputStream fout = new FileOutputStream(calFile);

  CalendarOutputter outputter = new CalendarOutputter();
  outputter.setValidating(false);
  outputter.output(calendar, fout);
  
  //Now Parsing an iCalendar file
  FileInputStream fin = new FileInputStream(calFile);

  CalendarBuilder builder = new CalendarBuilder();

  calendar = builder.build(fin);
  
  //Iterating over a Calendar
  for (Iterator i = calendar.getComponents().iterator(); i.hasNext();) {
      Component component = (Component) i.next();
      System.out.println("Component [" + component.getName() + "]");

      for (Iterator j = component.getProperties().iterator(); j.hasNext();) {
          Property property = (Property) j.next();
          System.out.println("Property [" + property.getName() + ", " + property.getValue() + "]");
      }
  }//for
 }
}

Console Output :

May 18, 2012 8:02:01 PM net.fortuna.ical4j.util.Configurator 
INFO: ical4j.properties not found.
Component [VEVENT]
Property [DTSTAMP, 20120518T143201Z]
Property [DTSTART, 20121225]
Property [SUMMARY, Christmas Day]
Property [UID, 20120518T141056Z-1@javaxp.com]

mycalendar.ics

BEGIN:VCALENDAR
PRODID:-//Ben Fortuna//iCal4j 1.0//EN
VERSION:2.0
CALSCALE:GREGORIAN
BEGIN:VEVENT
DTSTAMP:20120518T141056Z
DTSTART;VALUE=DATE;VALUE=DATE:20121225
SUMMARY:Christmas Day
UID:20120518T141056Z-1@javaxp.com
END:VEVENT
END:VCALENDAR

Note : I observed below mentioned exceptions while writing this example

1.
Exception in thread "main" java.lang.NoClassDefFoundError: edu/emory/mathcs/backport/java/util/concurrent/CopyOnWriteArrayList
 at net.fortuna.ical4j.model.ParameterList.(ParameterList.java:75)
 at net.fortuna.ical4j.model.ParameterList.(ParameterList.java:63)
 at net.fortuna.ical4j.model.Property.(Property.java:367)
 at net.fortuna.ical4j.model.property.ProdId.(ProdId.java:65)
 at com.cal.ICalendarExample.main(ICalendarExample.java:38)
Caused by: java.lang.ClassNotFoundException: edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArrayList
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
 ... 5 more

Add backport-util-concurrent-3.1.jar file in your classpath

2.
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
 at net.fortuna.ical4j.util.Configurator.(Configurator.java:51)
 at net.fortuna.ical4j.util.CompatibilityHints.(CompatibilityHints.java:83)
 at net.fortuna.ical4j.data.AbstractOutputter.(AbstractOutputter.java:75)
 at net.fortuna.ical4j.data.AbstractOutputter.(AbstractOutputter.java:68)
 at net.fortuna.ical4j.data.CalendarOutputter.(CalendarOutputter.java:56)
 at com.cal.ICalendarExample.main(ICalendarExample.java:50)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
 ... 6 more

Add commons-logging-1.1.1.jar file in your classpath

3.
May 18, 2012 6:04:17 PM net.fortuna.ical4j.util.Configurator 
INFO: ical4j.properties not found.
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang/builder/EqualsBuilder
 at net.fortuna.ical4j.model.Property.equals(Property.java:504)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:273)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:257)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:96)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:83)
 at com.cal.ICalendarExample.main(ICalendarExample.java:51)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang.builder.EqualsBuilder
 at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
 ... 6 more

Add commons-lang-2.6.jar file in your classpath

4.
May 18, 2012 6:05:10 PM net.fortuna.ical4j.util.Configurator 
INFO: ical4j.properties not found.
Exception in thread "main" net.fortuna.ical4j.model.ValidationException: Calendar must contain at least one component
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:287)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:257)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:96)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:83)
 at com.cal.ICalendarExample.main(ICalendarExample.java:51)

Add a Component to your Calendar object as shown in above example

5.
Exception in thread "main" net.fortuna.ical4j.model.ValidationException: Property [UID] must be specified once
 at net.fortuna.ical4j.util.PropertyValidator.assertOne(PropertyValidator.java:112)
 at net.fortuna.ical4j.model.component.VEvent.validate(VEvent.java:356)
 at net.fortuna.ical4j.model.Component.validate(Component.java:201)
 at net.fortuna.ical4j.model.Calendar.validateComponents(Calendar.java:500)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:478)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:257)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:96)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:83)
 at com.cal.ICalendarExample.main(ICalendarExample.java:66)

You will need to add property UID in Calendar object as shown below

UidGenerator uidGenerator = new UidGenerator("1");
christmas.getProperties().add(uidGenerator.generateUid());

6.
Exception in thread "main" net.fortuna.ical4j.model.ValidationException: Parameter [VALUE] must only be specified once
 at net.fortuna.ical4j.util.ParameterValidator.assertOneOrLess(ParameterValidator.java:78)
 at net.fortuna.ical4j.model.property.DateProperty.validate(DateProperty.java:223)
 at net.fortuna.ical4j.model.property.DtStart.validate(DtStart.java:194)
 at net.fortuna.ical4j.model.Component.validateProperties(Component.java:219)
 at net.fortuna.ical4j.model.component.VEvent.validate(VEvent.java:472)
 at net.fortuna.ical4j.model.Component.validate(Component.java:201)
 at net.fortuna.ical4j.model.Calendar.validateComponents(Calendar.java:500)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:478)
 at net.fortuna.ical4j.model.Calendar.validate(Calendar.java:257)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:96)
 at net.fortuna.ical4j.data.CalendarOutputter.output(CalendarOutputter.java:83)
 at com.cal.ICalendarExample.main(ICalendarExample.java:81)

When saving an iCalendar file iCal4j will automatically validate your calendar object model to ensure it complies with the RFC2445 specification. If you would prefer not to validate your calendar data you can disable the validation by calling CalendarOutputter.setValidating(false).