diff --git a/src/main/java/org/olat/commons/calendar/ICalServlet.java b/src/main/java/org/olat/commons/calendar/ICalServlet.java
index 77e2a552c482f27f78c0addea319aa906f6e81df..42879439b156ddad66e5df0e306839d98e703c73 100644
--- a/src/main/java/org/olat/commons/calendar/ICalServlet.java
+++ b/src/main/java/org/olat/commons/calendar/ICalServlet.java
@@ -56,12 +56,12 @@ import org.olat.core.util.StringHelper;
 import org.olat.core.util.i18n.I18nManager;
 
 import net.fortuna.ical4j.data.CalendarBuilder;
-import net.fortuna.ical4j.data.CalendarOutputter;
 import net.fortuna.ical4j.data.ParserException;
 import net.fortuna.ical4j.model.Calendar;
 import net.fortuna.ical4j.model.Component;
 import net.fortuna.ical4j.model.ComponentList;
 import net.fortuna.ical4j.model.Parameter;
+import net.fortuna.ical4j.model.Property;
 import net.fortuna.ical4j.model.PropertyList;
 import net.fortuna.ical4j.model.ValidationException;
 import net.fortuna.ical4j.model.component.VEvent;
@@ -83,13 +83,15 @@ import net.fortuna.ical4j.util.Strings;
  * Initial Date:  June 1, 2008
  *
  * @author Udit Sajjanhar
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
  */
 public class ICalServlet extends HttpServlet {
 
 	private static final long serialVersionUID = -155266285395912535L;
 	private static final OLog log = Tracing.createLoggerFor(ICalServlet.class);
 	
-	private final int cacheAge = 60 * 60 * 12;
+	private static final int TTL_HOURS = 6;
+	private static final int cacheAge = 60 * 60 * TTL_HOURS;//6 Hours
 	private static final ConcurrentMap<String,VTimeZone> outlookVTimeZones = new ConcurrentHashMap<>();
 	
 	/** collection of iCal feed prefixs **/
@@ -226,9 +228,8 @@ public class ICalServlet extends HttpServlet {
 			} else {
 				// read and return the calendar file
 				Calendar calendar = calendarManager.readCalendar(calendarType, calendarID);
-				updateUrlProperties(calendar);
 				DBFactory.getInstance().commitAndCloseSession();
-				new CalendarOutputter(false).output(calendar, response.getOutputStream());
+				outputCalendar(calendar, request, response);
 			}
 		} else {
 			response.sendError(HttpServletResponse.SC_NOT_FOUND, requestUrl);
@@ -241,6 +242,59 @@ public class ICalServlet extends HttpServlet {
 	    httpResponse.setHeader("Cache-Control", "max-age="+ cacheAge);
 	}
 	
+	private void outputCalendar(Calendar calendar, HttpServletRequest request, HttpServletResponse response)
+	throws ValidationException, IOException {
+		boolean outlook = isOutlook(request);
+		updateUrlProperties(calendar);
+		
+		Writer out = response.getWriter();
+		out.write(Calendar.BEGIN);
+		out.write(':');
+		out.write(Calendar.VCALENDAR);
+		out.write(Strings.LINE_SEPARATOR);
+		out.write(Version.VERSION_2_0.toString());
+		
+		boolean calScale = false;
+		for (Iterator<?> propIter = calendar.getProperties().iterator(); propIter.hasNext();) {
+			Object pobject = propIter.next();
+			if(pobject instanceof Property) {
+				Property property = (Property)pobject;
+				if(Version.VERSION.equals(property.getName())) {
+					//we force version 2.0
+				} else if(Version.CALSCALE.equals(property.getName())) {
+					out.write(property.toString());
+					calScale = true;
+				} else {
+					out.write(property.toString());
+				}
+			}
+		}
+		
+		if(!calScale) {
+			out.write(CalScale.GREGORIAN.toString());
+		}
+
+		outputTTL(out);
+
+		Set<String> timezoneIds = new HashSet<>();
+		outputCalendarComponents(calendar, out, outlook, timezoneIds);
+		if(outlook) {
+			outputTimeZoneForOutlook(timezoneIds, out);
+		}
+		
+		out.write(Calendar.END);
+		out.write(':');
+		out.write(Calendar.VCALENDAR);
+	}
+	
+	/**
+	 * Collect all the calendars, update the URL properties and the UUID.
+	 * 
+	 * @param identity
+	 * @param request
+	 * @param response
+	 * @throws IOException
+	 */
 	private void generateAggregatedCalendar(Identity identity, HttpServletRequest request, HttpServletResponse response) throws IOException {
 		PersonalCalendarManager homeCalendarManager = CoreSpringFactory.getImpl(PersonalCalendarManager.class);
 		if(identity == null) {
@@ -257,6 +311,8 @@ public class ICalServlet extends HttpServlet {
 			out.write(Strings.LINE_SEPARATOR);
 			out.write(Version.VERSION_2_0.toString());
 			out.write(CalScale.GREGORIAN.toString());
+			
+			outputTTL(out);
 
 			Set<String> timezoneIds = new HashSet<>();
 			int numOfFiles = iCalFiles.size();
@@ -281,6 +337,22 @@ public class ICalServlet extends HttpServlet {
 		return false;
 	}
 	
+	/**
+	 * Append TTL:<br>
+	 * @see http://stackoverflow.com/questions/17152251/specifying-name-description-and-refresh-interval-in-ical-ics-format
+	 * @see http://tools.ietf.org/html/draft-daboo-icalendar-extensions-06
+	 * 
+	 * @param out
+	 * @throws IOException
+	 */
+	private void outputTTL(Writer out)
+	throws IOException {
+		out.write("X-PUBLISHED-TTL:PT" + TTL_HOURS + "H");
+		out.write(Strings.LINE_SEPARATOR);
+		out.write("REFRESH-INTERVAL;VALUE=DURATION:PT" + TTL_HOURS + "H");
+		out.write(Strings.LINE_SEPARATOR);
+	}
+	
 	private void outputTimeZoneForOutlook(Set<String> timezoneIds,  Writer out) {
 		for(String timezoneId:timezoneIds) {
 			if(StringHelper.containsNonWhitespace(timezoneId)) {
@@ -306,6 +378,15 @@ public class ICalServlet extends HttpServlet {
 			String prefix = fileInfos.getType() + "-" + fileInfos.getCalendarId() + "-";
 			updateUUID(calendar, prefix);
 			
+			outputCalendarComponents(calendar, out, outlook, timezoneIds);
+		} catch (IOException | OLATRuntimeException e) {
+			log.error("", e);
+		}
+	}
+	
+	private void outputCalendarComponents(Calendar calendar, Writer out, boolean outlook, Set<String> timezoneIds)
+	throws IOException {
+		try {
 			ComponentList events = calendar.getComponents();
 			for (final Iterator<?> i = events.iterator(); i.hasNext();) {
 				Object comp = i.next();
diff --git a/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java b/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java
index c1bc899822387f506ba22c16da5621c799ae230a..78faf4d14556d021efe529f44879ea6f1a70ce8f 100644
--- a/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java
+++ b/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java
@@ -244,9 +244,10 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea
 		return cal;
 	}
 
-  /**
-   * Internal read calendar file from filesystem
-   */
+	/**
+	 * Internal read calendar file from filesystem. It doesn't
+	 * use the cache and return a not shared calendar.
+	 */
 	@Override
 	public Calendar readCalendar(String type, String calendarID) {
 		if(log.isDebug()) {
diff --git a/src/test/java/org/olat/selenium/page/course/GroupTaskConfigurationPage.java b/src/test/java/org/olat/selenium/page/course/GroupTaskConfigurationPage.java
index 5baaa29cb2941639ba1b9843ce7a3e2633672ec6..a40e53ece3b7914fa7cd2263e225c35eb72136b8 100644
--- a/src/test/java/org/olat/selenium/page/course/GroupTaskConfigurationPage.java
+++ b/src/test/java/org/olat/selenium/page/course/GroupTaskConfigurationPage.java
@@ -65,6 +65,7 @@ public class GroupTaskConfigurationPage {
 		By chooseGroupBy = By.cssSelector("a.o_form_groupchooser");
 		browser.findElement(chooseGroupBy).click();
 		OOGraphene.waitBusy(browser);
+		OOGraphene.waitModalDialog(browser);
 		return this;
 	}
 	
@@ -72,6 +73,7 @@ public class GroupTaskConfigurationPage {
 		By createGroupBy = By.cssSelector("div.o_button_group_right a");
 		browser.findElement(createGroupBy).click();
 		OOGraphene.waitBusy(browser);
+		OOGraphene.waitModalDialog(browser);
 		
 		//fill the form
 		By nameBy = By.cssSelector(".o_sel_group_edit_title input[type='text']");