From 3de66837ff5a7d3878bb6430047389892ffb5e9f Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Wed, 12 Oct 2011 14:11:50 +0200
Subject: [PATCH] FXOLAT-282: slay the zombies

--HG--
branch : FXOLAT-282-virtualclassroom
---
 .../olat/course/nodes/ViteroCourseNode.java   |   2 +-
 .../vitero/ViteroPeekViewController.java      |  15 +-
 .../vitero/_i18n/LocalStrings_de.properties   |  16 +
 .../com/frentix/olat/vitero/ViteroModule.java |  64 ++
 .../olat/vitero/ViteroTimezoneIDs.java        | 127 +++
 .../olat/vitero/_spring/viteroContext.xml     |   8 +-
 .../olat/vitero/manager/ViteroManager.java    | 767 ++++++++++--------
 .../olat/vitero/manager/ViteroTestMain.java   |  20 +-
 .../vitero/manager/ViteroZombieSlayerJob.java |  33 +
 .../manager/VmsNotAvailableException.java     |  54 ++
 .../ui/ViteroBookingEditController.java       |  42 +-
 .../ui/ViteroBookingsAdminController.java     |  27 +-
 .../vitero/ui/ViteroBookingsController.java   |  62 +-
 .../ui/ViteroBookingsEditController.java      |  23 +-
 .../ui/ViteroConfigurationController.java     |  44 +-
 .../ui/ViteroUserToGroupController.java       |  43 +-
 .../ui/_i18n/LocalStrings_de.properties       |   2 +
 .../bps/course/nodes/vc/_spring/vcContext.xml |   2 +-
 .../resources/serviceconfig/olat.properties   |   2 +
 19 files changed, 929 insertions(+), 424 deletions(-)
 create mode 100644 src/main/java/com/frentix/olat/vitero/ViteroTimezoneIDs.java
 create mode 100644 src/main/java/com/frentix/olat/vitero/manager/ViteroZombieSlayerJob.java
 create mode 100644 src/main/java/com/frentix/olat/vitero/manager/VmsNotAvailableException.java

diff --git a/src/main/java/com/frentix/olat/course/nodes/ViteroCourseNode.java b/src/main/java/com/frentix/olat/course/nodes/ViteroCourseNode.java
index dbf0e33bbba..8807a4fda65 100644
--- a/src/main/java/com/frentix/olat/course/nodes/ViteroCourseNode.java
+++ b/src/main/java/com/frentix/olat/course/nodes/ViteroCourseNode.java
@@ -160,6 +160,6 @@ public class ViteroCourseNode extends AbstractAccessableCourseNode {
 		ViteroManager provider = (ViteroManager)CoreSpringFactory.getBean("viteroManager");
 		// remove meeting
 		OLATResourceable ores = OresHelper.createOLATResourceableInstance(course.getResourceableTypeName(), course.getResourceableId());
-		provider.deleteBookings(null, ores);
+		provider.deleteAll(null, ores);
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/com/frentix/olat/course/nodes/vitero/ViteroPeekViewController.java b/src/main/java/com/frentix/olat/course/nodes/vitero/ViteroPeekViewController.java
index 9497c14c712..b204d03ba5a 100644
--- a/src/main/java/com/frentix/olat/course/nodes/vitero/ViteroPeekViewController.java
+++ b/src/main/java/com/frentix/olat/course/nodes/vitero/ViteroPeekViewController.java
@@ -38,6 +38,7 @@ import org.olat.course.CourseModule;
 import org.olat.course.run.userview.UserCourseEnvironment;
 
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 import com.frentix.olat.vitero.model.StartBookingComparator;
 import com.frentix.olat.vitero.model.ViteroBooking;
 import com.frentix.olat.vitero.ui.FilterBookings;
@@ -62,10 +63,16 @@ public class ViteroPeekViewController extends BasicController {
 		OLATResourceable ores = OresHelper.createOLATResourceableInstance(CourseModule.class,
 				userCourseEnv.getCourseEnvironment().getCourseResourceableId());
 		
-		List<ViteroBooking> bookings = viteroManager.getBookings(null, ores);
-		List<ViteroBooking> myBookings = viteroManager.getBookingInFutures(getIdentity());
-		FilterBookings.filterMyFutureBookings(bookings, myBookings);
-		Collections.sort(bookings, new StartBookingComparator());
+		List<ViteroBooking> bookings;
+		try {
+			bookings = viteroManager.getBookings(null, ores);
+			List<ViteroBooking> myBookings = viteroManager.getBookingInFutures(getIdentity());
+			FilterBookings.filterMyFutureBookings(bookings, myBookings);
+			Collections.sort(bookings, new StartBookingComparator());
+		} catch (VmsNotAvailableException e) {
+			bookings = Collections.emptyList();
+			showError(VmsNotAvailableException.I18N_KEY);
+		}
 
 		TableGuiConfiguration tableConfig = new TableGuiConfiguration();
 		tableConfig.setTableEmptyMessage(translate("vc.table.empty"));
diff --git a/src/main/java/com/frentix/olat/course/nodes/vitero/_i18n/LocalStrings_de.properties b/src/main/java/com/frentix/olat/course/nodes/vitero/_i18n/LocalStrings_de.properties
index 85f5bb42c33..af592e6d547 100644
--- a/src/main/java/com/frentix/olat/course/nodes/vitero/_i18n/LocalStrings_de.properties
+++ b/src/main/java/com/frentix/olat/course/nodes/vitero/_i18n/LocalStrings_de.properties
@@ -1,3 +1,19 @@
+vc.vmsNotAvailable=$com.frentix.olat.vitero.ui\:vc.vmsNotAvailable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 pane.tab.accessibility=Zugang
 pane.tab.vcconfig=Konfiguration
 condition.accessibility.title=Zugang
diff --git a/src/main/java/com/frentix/olat/vitero/ViteroModule.java b/src/main/java/com/frentix/olat/vitero/ViteroModule.java
index b5b6897e541..0fda3bdc6ad 100644
--- a/src/main/java/com/frentix/olat/vitero/ViteroModule.java
+++ b/src/main/java/com/frentix/olat/vitero/ViteroModule.java
@@ -21,6 +21,7 @@
 package com.frentix.olat.vitero;
 
 import java.net.URI;
+import java.text.ParseException;
 
 import javax.ws.rs.core.UriBuilder;
 
@@ -28,6 +29,13 @@ import org.olat.core.configuration.AbstractOLATModule;
 import org.olat.core.configuration.ConfigOnOff;
 import org.olat.core.configuration.PersistedProperties;
 import org.olat.core.util.StringHelper;
+import org.quartz.CronTrigger;
+import org.quartz.JobDetail;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+
+import com.frentix.olat.vitero.manager.ViteroZombieSlayerJob;
+import com.ibm.icu.util.Calendar;
 
 /**
  * 
@@ -48,6 +56,7 @@ public class ViteroModule extends AbstractOLATModule implements ConfigOnOff {
 	private static final String ADMIN_LOGIN = "adminLogin";
 	private static final String ADMIN_PASSWORD = "adminPassword";
 	private static final String CUSTOMER_ID = "customerId";
+	private static final String OLAT_TIMEZONE_ID = "olatTimeZoneId";
 	
 	private boolean enabled;
 	private String displayName;
@@ -58,6 +67,14 @@ public class ViteroModule extends AbstractOLATModule implements ConfigOnOff {
 	private String adminLogin;
 	private String adminPassword;
 	private int customerId;
+	private String olatTimeZoneId;
+	
+	private String cronExpression;
+	private final Scheduler scheduler;
+	
+	public ViteroModule(Scheduler scheduler) {
+		this.scheduler = scheduler;
+	}
 	
 	@Override
 	public void init() {
@@ -94,6 +111,12 @@ public class ViteroModule extends AbstractOLATModule implements ConfigOnOff {
 		if(StringHelper.containsNonWhitespace(customerIdObj)) {
 			customerId = Integer.parseInt(customerIdObj);
 		}
+		String olatTimeZoneIdObj = getStringPropertyValue(OLAT_TIMEZONE_ID, true);
+		if(StringHelper.containsNonWhitespace(olatTimeZoneIdObj)) {
+			olatTimeZoneId = olatTimeZoneIdObj;
+		}
+		
+		initCronJob();
 	}
 
 	@Override
@@ -106,6 +129,7 @@ public class ViteroModule extends AbstractOLATModule implements ConfigOnOff {
 		adminLogin = getStringConfigParameter(ADMIN_LOGIN, "admin", false);
 		adminPassword = getStringConfigParameter(ADMIN_PASSWORD, "007", false);
 		customerId = Integer.parseInt(getStringConfigParameter(CUSTOMER_ID, "1", false));
+		olatTimeZoneId = getStringConfigParameter(OLAT_TIMEZONE_ID, "Africa/Ceuta", false);
 	}
 
 	@Override
@@ -113,11 +137,39 @@ public class ViteroModule extends AbstractOLATModule implements ConfigOnOff {
 		init();
 	}
 	
+	private void initCronJob() {
+		try {
+			if(scheduler.getTrigger("Vitero_Cleaner_Cron_Job", Scheduler.DEFAULT_GROUP) == null) {
+				JobDetail jobDetail = new JobDetail("Vitero_Cleaner_Cron_Job", Scheduler.DEFAULT_GROUP, ViteroZombieSlayerJob.class);
+				CronTrigger trigger = new CronTrigger();
+				
+				Calendar cal = Calendar.getInstance();
+				cal.add(Calendar.SECOND, 30);
+				trigger.setStartTime(cal.getTime());
+				trigger.setName("Vitero_Cleaner_Cron_Trigger");
+				trigger.setCronExpression(cronExpression);
+				scheduler.scheduleJob(jobDetail, trigger);
+			}
+		} catch (ParseException e) {
+			logError("Cannot start the Quartz Job which clean the Vitero rooms", e);
+		} catch (SchedulerException e) {
+			logError("Cannot start the Quartz Job which clean the Vitero rooms", e);
+		}
+	}
+	
 	@Override
 	public void setPersistedProperties(PersistedProperties persistedProperties) {
 		this.moduleConfigProperties = persistedProperties;
 	}
 	
+	public String getCronExpression() {
+		return cronExpression;
+	}
+
+	public void setCronExpression(String cronExpression) {
+		this.cronExpression = cronExpression;
+	}
+
 	public URI getVmsURI() {
 		UriBuilder builder = UriBuilder.fromUri(getProtocol() + "://" + getBaseUrl());
 		if(getPort() > 0) {
@@ -150,6 +202,18 @@ public class ViteroModule extends AbstractOLATModule implements ConfigOnOff {
 	public void setEnabled(boolean enabled) {
 		setBooleanProperty(ENABLED, enabled, true);
 	}
+	
+	/**
+	 * Return the time zone of OLAT within the IDS allowed by Vitero
+	 * @return
+	 */
+	public String getTimeZoneId() {
+		return olatTimeZoneId;
+	}
+	
+	public void setTimeZoneId(String timeZoneId) {
+		setStringProperty(OLAT_TIMEZONE_ID, timeZoneId, true);
+	}
 
 	public String getProtocol() {
 		return protocol;
diff --git a/src/main/java/com/frentix/olat/vitero/ViteroTimezoneIDs.java b/src/main/java/com/frentix/olat/vitero/ViteroTimezoneIDs.java
new file mode 100644
index 00000000000..0039138913f
--- /dev/null
+++ b/src/main/java/com/frentix/olat/vitero/ViteroTimezoneIDs.java
@@ -0,0 +1,127 @@
+/**
+ * OLAT - Online Learning and Training<br>
+ * http://www.olat.org
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Copyright (c) frentix GmbH<br>
+ * http://www.frentix.com<br>
+ * <p>
+ */
+package com.frentix.olat.vitero;
+
+/**
+ * 
+ * Description:<br>
+ * the list of Time Zone which Vitero accepts
+ * 
+ * <P>
+ * Initial Date:  12 oct. 2011 <br>
+ *
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class ViteroTimezoneIDs {
+
+	public static final String[] TIMEZONE_IDS = {
+		"Pacific/Apia",
+		"Pacific/Fakaofo",
+		"America/Adak",
+		"Pacific/Marquesas",
+		"Pacific/Gambier",
+		"America/Anchorage",
+		"America/Ensenada",
+		"Pacific/Pitcairn",
+		"America/Dawson",
+		"America/Chihuahua",
+		"America/Boise",
+		"America/Dawson_Creek",
+		"America/Belize",
+		"Pacific/Easter",
+		"America/Chicago",
+		"America/Cancun",
+		"America/Havana",
+		"America/Detroit",
+		"America/Atikokan",
+		"America/Caracas",
+		"America/Glace_Bay",
+		"America/Campo_Grande",
+		"America/Goose_Bay",
+		"America/Anguilla",
+		"America/Asuncion",
+		"America/Santiago",
+		"Atlantic/Stanley",
+		"America/St_Johns",
+		"America/Montevideo",
+		"America/Miquelon",
+		"America/Sao_Paulo",
+		"America/Godthab",
+		"America/Argentina/Buenos_Aires",
+		"America/Araguaina",
+		"America/Noronha",
+		"Atlantic/Cape_Verde",
+		"America/Scoresbysund",
+		"Africa/Abidjan",
+		"Atlantic/Canary",
+		"Africa/Windhoek",
+		"Africa/Algiers",
+		"Africa/Ceuta",
+		"Africa/Tunis",
+		"Africa/Cairo",
+		"Asia/Amman",
+		"Asia/Gaza",
+		"Asia/Beirut",
+		"Asia/Jerusalem",
+		"Europe/Kaliningrad",
+		"Asia/Damascus",
+		"Asia/Istanbul",
+		"Africa/Blantyre",
+		"Africa/Addis_Ababa",
+		"Europe/Moscow",
+		"Asia/Riyadh87",
+		"Asia/Tehran",
+		"Asia/Dubai",
+		"Asia/Baku",
+		"Indian/Mauritius",
+		"Asia/Yerevan",
+		"Asia/Kabul",
+		"Asia/Aqtau",
+		"Asia/Yekaterinburg",
+		"Asia/Calcutta",
+		"Asia/Katmandu",
+		"Asia/Novosibirsk",
+		"Asia/Almaty",
+		"Asia/Rangoon",
+		"Asia/Bangkok",
+		"Asia/Krasnoyarsk",
+		"Asia/Brunei",
+		"Asia/Irkutsk",
+		"Australia/Eucla",
+		"Asia/Dili",
+		"Asia/Yakutsk",
+		"Australia/Darwin",
+		"Australia/Adelaide",
+		"Asia/Sakhalin",
+		"Australia/Brisbane",
+		"Australia/ACT",
+		"Australia/LHI",
+		"Pacific/Efate",
+		"Asia/Magadan",
+		"Pacific/Norfolk",
+		"Asia/Anadyr",
+		"Pacific/Fiji",
+		"Pacific/Auckland",
+		"Pacific/Chatham",
+		"Pacific/Enderbury",
+		"Pacific/Kiritimati"
+	};
+}
diff --git a/src/main/java/com/frentix/olat/vitero/_spring/viteroContext.xml b/src/main/java/com/frentix/olat/vitero/_spring/viteroContext.xml
index cb54e37e179..b283ab93f39 100644
--- a/src/main/java/com/frentix/olat/vitero/_spring/viteroContext.xml
+++ b/src/main/java/com/frentix/olat/vitero/_spring/viteroContext.xml
@@ -13,6 +13,9 @@
 
 	<!-- Definition of the providers -->
 	<bean id="viteroModule" class="com.frentix.olat.vitero.ViteroModule">
+		<constructor-arg index="0" ref="schedulerFactoryBean"/>
+		<property name="cronExpression" value="*/15 * * * * ?" />
+		
 		<property name="persistedProperties">
 	  	<bean class="org.olat.core.configuration.PersistedProperties" scope="prototype" init-method="init" destroy-method="destroy" 
 	  		depends-on="coordinatorManager,org.olat.core.util.WebappHelper">
@@ -37,6 +40,7 @@
 				adminLogin=${vc.vitero.adminlogin}
 				adminPassword=${vc.vitero.adminpassword}
 				customerId=${vc.vitero.customerid}
+				olatTimeZoneId=${vc.vitero.olatTimeZoneId}
 			</value>
 		</property>
 	</bean>
@@ -58,7 +62,5 @@
 			</list>
 		</property>
 		<property name="order" value="39" />
-	</bean> 
-
-	
+	</bean>
 </beans>
\ No newline at end of file
diff --git a/src/main/java/com/frentix/olat/vitero/manager/ViteroManager.java b/src/main/java/com/frentix/olat/vitero/manager/ViteroManager.java
index 7b99f66ca06..ebdc05bf608 100644
--- a/src/main/java/com/frentix/olat/vitero/manager/ViteroManager.java
+++ b/src/main/java/com/frentix/olat/vitero/manager/ViteroManager.java
@@ -29,8 +29,9 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
-import java.util.TimeZone;
+import java.util.Set;
 import java.util.UUID;
 
 import javax.activation.DataHandler;
@@ -39,6 +40,7 @@ import javax.annotation.PostConstruct;
 import javax.ws.rs.core.UriBuilder;
 
 import org.apache.axis2.AxisFault;
+import org.apache.commons.httpclient.ConnectTimeoutException;
 import org.olat.basesecurity.Authentication;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.core.id.Identity;
@@ -94,6 +96,7 @@ public class ViteroManager extends BasicManager {
 	
 	private static final String VMS_PROVIDER = "VMS";
 	private static final String VMS_CATEGORY = "vitero-category";
+	private static final String VMS_CATEGORY_ZOMBIE = "vitero-category-zombie";
 	
 	@Autowired
 	private ViteroModule viteroModule;
@@ -120,31 +123,13 @@ public class ViteroManager extends BasicManager {
 		this.viteroModule = module;
 	}
 	
-	public void getLicence(Date begin, Date end) {
-		try {
-			LicenceServiceStub licenceWs = getLicenceWebService();
-			LicenceServiceStub.GetBookableRoomsForGroupRequest request = new LicenceServiceStub.GetBookableRoomsForGroupRequest();
-			LicenceServiceStub.Grouprequesttype groupRequest = new LicenceServiceStub.Grouprequesttype();
-			groupRequest.setStart(format(begin));
-			groupRequest.setEnd(format(end));
-			
-			request.setGetBookableRoomsForGroupRequest(groupRequest);
-
-			LicenceServiceStub.GetBookableRoomsForGroupResponse response = licenceWs.getBookableRoomsForGroup(request);
-			Rooms_type0 rooms = response.getRooms();
-			int[] roomSize = rooms.getRoomsize();
-			System.out.println(roomSize);
-		} catch (RemoteException e) {
-			logError("", e);
-		}
-	}
-	
 	public List<ViteroBooking> getBookingByDate(Date start, Date end) {
 		try {
 			BookingServiceStub bookingWs = getBookingWebService();
 			BookingServiceStub.GetBookingListByDateRequest dateRequest = new BookingServiceStub.GetBookingListByDateRequest();
 			dateRequest.setStart(format(start));
 			dateRequest.setEnd(format(end));
+			dateRequest.setTimezone(viteroModule.getTimeZoneId());
 			BookingServiceStub.GetBookingListByDateResponse response = bookingWs.getBookingListByDate(dateRequest);
 			
 			BookingServiceStub.Bookinglist bookingList = response.getGetBookingListByDateResponse();
@@ -177,58 +162,21 @@ public class ViteroManager extends BasicManager {
 		return false;
 	}
 	
-	public List<ViteroBooking> getBookingInFutures(Identity identity) {
-		int userId = getVmsUserId(identity);
-		Booking[] bookings = getBookingInFutureByCustomerId(userId);
-		return convert(bookings);
-	}
-	
-	public List<ViteroBooking> getBookings() {
-		List<Property> properties = propertyManager.listProperties(null, null, null, VMS_CATEGORY, null);
-		List<ViteroBooking> bookings = new ArrayList<ViteroBooking>();
-		for(Property property:properties) {
-			String bookingStr = property.getTextValue();
-			ViteroBooking booking = deserializeViteroBooking(bookingStr);
-			bookings.add(booking);
-		}
-		return bookings;
-	}
-	
-	public List<ViteroBooking> getBookings(BusinessGroup group, OLATResourceable ores) {
-		List<Property> properties = propertyManager.listProperties(null, group, ores, VMS_CATEGORY, null);
-		List<ViteroBooking> bookings = new ArrayList<ViteroBooking>();
-		for(Property property:properties) {
-			String bookingStr = property.getTextValue();
-			ViteroBooking booking = deserializeViteroBooking(bookingStr);
-			bookings.add(booking);
-		}
-		return bookings;
-	}
-	
-	public String getURLToBooking(Identity identity, ViteroBooking booking) {
+	public String getURLToBooking(Identity identity, ViteroBooking booking)
+	throws VmsNotAvailableException {
 		String sessionCode = createSessionCode(identity, booking);
 		String url = getStartPoint(sessionCode);
 		return url;
 	}
 	
-	public String serializeViteroBooking(ViteroBooking booking) {
-		StringWriter writer = new StringWriter();
-		xStream.marshal(booking, new CompactWriter(writer));
-		writer.flush();
-		return writer.toString();
-	}
-	
-	public ViteroBooking deserializeViteroBooking(String booking) {
-		return (ViteroBooking)xStream.fromXML(booking);
-	}
-	
 	/**
 	 * Create a session code with a one hour expiration date
 	 * @param identity
 	 * @param booking
 	 * @return
 	 */
-	protected String createSessionCode(Identity identity, ViteroBooking booking) {
+	protected String createSessionCode(Identity identity, ViteroBooking booking)
+	throws VmsNotAvailableException {
 		try {
 			int userId = getVmsUserId(identity);
 			SessionCodeServiceStub sessionCodeWs = this.getSessionCodeWebService();
@@ -237,6 +185,7 @@ public class ViteroManager extends BasicManager {
 			SessionCodeServiceStub.Sessioncode_type2 code = new SessionCodeServiceStub.Sessioncode_type2();
 			code.setBookingid(booking.getBookingId());
 			code.setUserid(userId);
+			code.setTimezone(viteroModule.getTimeZoneId());
 		
 			Calendar cal = Calendar.getInstance();
 			cal.setTime(new Date());
@@ -249,29 +198,25 @@ public class ViteroManager extends BasicManager {
 			Codetype myCode = response.getCreatePersonalBookingSessionCodeResponse();
 			return myCode.getCode();
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>303</errorCode>")) {
-				logError("Invalid attribute", f);
-			} else if(msg.contains("<errorCode>304</errorCode>")) {
-				logError("Invalid time zone", f);
-			} else if(msg.contains("<errorCode>53</errorCode>")) {
-				logError("User does not exist", f);
-			} else if(msg.contains("<errorCode>506</errorCode>") || msg.contains("<errorCode>509</errorCode>")) {
-				logError("Booking does not exist", f);
-			} else if(msg.contains("<errorCode>153</errorCode>")) {
-				logError("User not assigned to group!", f);
-			} else {
-				logError(msg, f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 53: logError("User does not exist.", f); break;
+				case 153: logError("User not assigned to group.", f); break;
+				case 303: logError("Invalid attribute.", f); break; 
+				case 304: logError("Invalid time zone.", f); break;
+				case 506:
+				case 509: logError("Booking does not exist.", f); break;
+				default: logAxisError("Cannot create session code.", f);
 			}
-			logError(msg, f);
 			return null;
 		} catch (RemoteException e) {
-			logError("", e);
+			logError("Cannot create session code.", e);
 			return null;
 		}
 	}
 	
-	public List<Identity> getIdentitiesInBooking(ViteroBooking booking) {
+	public List<Identity> getIdentitiesInBooking(ViteroBooking booking) 
+	throws VmsNotAvailableException {
 		Usertype[] vmsUsers = getVmsUsersByGroup(booking.getGroupId());
 		List<Identity> identities = new ArrayList<Identity>();
 		if(vmsUsers != null) {
@@ -286,7 +231,8 @@ public class ViteroManager extends BasicManager {
 		return identities;
 	}
 	
-	protected Usertype[] getVmsUsersByGroup(int groupId) {
+	protected Usertype[] getVmsUsersByGroup(int groupId)
+	throws VmsNotAvailableException {
 		try {
 			UserServiceStub userWs = getUserWebService();
 			UserServiceStub.GetUserListByGroupRequest listRequest = new UserServiceStub.GetUserListByGroupRequest();
@@ -296,16 +242,19 @@ public class ViteroManager extends BasicManager {
 			Usertype[] userTypes = userList.getUser();
 			return userTypes;
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			logError(msg, f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				default: logAxisError("Cannot get the list of users in group: " + groupId, f);
+			}
 			return null;
 		} catch (RemoteException e) {
-			logError("Cannot get the lsit of users in group: " + groupId, e);
+			logError("Cannot get the list of users in group: " + groupId, e);
 			return null;
 		}
 	}
 	
-	public int getVmsUserId(Identity identity) {
+	protected int getVmsUserId(Identity identity) 
+	throws VmsNotAvailableException {
 		int userId;
 		Authentication authentication = securityManager.findAuthentication(identity, VMS_PROVIDER);
 		if(authentication == null) {
@@ -319,7 +268,8 @@ public class ViteroManager extends BasicManager {
 		return userId;
 	}
 	
-	protected int createVmsUser(Identity identity) {
+	protected int createVmsUser(Identity identity)
+	throws VmsNotAvailableException {
 		try {
 			UserServiceStub userWs = getUserWebService();
 			UserServiceStub.CreateUserRequest createRequest = new UserServiceStub.CreateUserRequest();
@@ -340,6 +290,7 @@ public class ViteroManager extends BasicManager {
 			//optional
 			user.setLocale("en");
 			user.setPcstate("NOT_TESTED");
+			user.setTimezone(viteroModule.getTimeZoneId());
 			
 			String street = olatUser.getProperty(UserConstants.STREET, null);
 			if(StringHelper.containsNonWhitespace(street)) {
@@ -370,15 +321,10 @@ public class ViteroManager extends BasicManager {
 			if(StringHelper.containsNonWhitespace(phoneOffice)) {
 				user.setPhone(phoneOffice);
 			}
-			
 			/*
 			user.setTitle("");
 			user.setCompany("");
-			user.setTimezone("");
 			*/
-			TimeZone.getDefault().getID();
-			
-			
 			user.setTechnicalnote("Generated by OpenOLAT");
 			
 			createRequest.setUser(user);
@@ -386,17 +332,22 @@ public class ViteroManager extends BasicManager {
 			Userid userId = response.getCreateUserResponse();
 			
 			storePortrait(identity, userId.getUserid());
-
 			return userId.getUserid();
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				default: logAxisError("Cannot create vms user.", f);
+			}
+			return -1;
 		} catch (RemoteException e) {
 			logError("Cannot create vms user.", e);
 			return -1;
 		}
 	}
 	
-	protected boolean storePortrait(Identity identity, int userId) {
+	protected boolean storePortrait(Identity identity, int userId)
+	throws VmsNotAvailableException {
 		try {
-
 			File portraitDir = DisplayPortraitManager.getInstance().getPortraitDir(identity);
 			File portrait = new File(portraitDir, DisplayPortraitManager.PORTRAIT_BIG_FILENAME);
 			if(portrait.exists()) {
@@ -417,48 +368,20 @@ public class ViteroManager extends BasicManager {
 				return true;
 			}
 			return false;
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				default: logAxisError("Cannot store the portrait of " + userId, f);
+			}
+			return false;
 		} catch (RemoteException e) {
-			logError("", e);
+			logError("Cannot store the portrait of " + userId, e);
 			return false;
 		}
 	}
 	
-	public ViteroBooking createBooking() {
-		ViteroBooking booking = new ViteroBooking();
-		
-		booking.setBookingId(-1);
-		booking.setGroupId(-1);
-		
-		Calendar cal = Calendar.getInstance();
-		int minute = cal.get(Calendar.MINUTE);
-		if(minute < 10) {
-			cal.set(Calendar.MINUTE, 15);
-		} else if (minute < 25) {
-			cal.set(Calendar.MINUTE, 30);
-		} else if (minute < 40) {
-			cal.set(Calendar.MINUTE, 45);
-		} else {
-			cal.add(Calendar.HOUR, 1);
-			cal.set(Calendar.MINUTE, 0);
-		}
-
-		cal.set(Calendar.SECOND, 0);
-		cal.set(Calendar.MILLISECOND, 0);
-		
-		booking.setStart(cal.getTime());
-		booking.setStartBuffer(0);
-		cal.add(Calendar.HOUR, 1);
-		booking.setEnd(cal.getTime());
-		booking.setEndBuffer(0);
-		
-		List<Integer> roomSizes = getLicencedRoomSizes();
-		if(!roomSizes.isEmpty()) {
-			booking.setRoomSize(roomSizes.get(0));
-		}
-		return booking;
-	}
-	
-	public List<Integer> getLicencedRoomSizes() {
+	public List<Integer> getLicencedRoomSizes() 
+	throws VmsNotAvailableException {
 		List<Integer> roomSizes = new ArrayList<Integer>();
 		try {
 			LicenceServiceStub licenceWs = getLicenceWebService();
@@ -476,13 +399,51 @@ public class ViteroManager extends BasicManager {
 					}
 				}
 			}
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 303: logError("ids <=0 or invalid attributs", f); break;
+				default: logAxisError("Cannot get licence for customer: " + viteroModule.getCustomerId(), f);
+			}
 		} catch (RemoteException e) {
 			logError("Cannot get licence for customer: " + viteroModule.getCustomerId(), e);
 		}
 		return roomSizes;
 	}
 	
-	public int createGroup() {
+	public List<Integer> getLicenceForAvailableRooms(Date begin, Date end) 
+	throws VmsNotAvailableException {
+		List<Integer> roomSizes = new ArrayList<Integer>();
+		try {
+			LicenceServiceStub licenceWs = getLicenceWebService();
+			LicenceServiceStub.GetBookableRoomsForGroupRequest request = new LicenceServiceStub.GetBookableRoomsForGroupRequest();
+			LicenceServiceStub.Grouprequesttype groupRequest = new LicenceServiceStub.Grouprequesttype();
+			groupRequest.setStart(format(begin));
+			groupRequest.setEnd(format(end));
+			
+			request.setGetBookableRoomsForGroupRequest(groupRequest);
+
+			LicenceServiceStub.GetBookableRoomsForGroupResponse response = licenceWs.getBookableRoomsForGroup(request);
+			Rooms_type0 rooms = response.getRooms();
+			for(int roomSize : rooms.getRoomsize()) {
+				if(!roomSizes.contains(roomSize)) {
+					roomSizes.add(roomSize);
+				}
+			}
+			
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				default: logAxisError("Cannot get licence for available room by dates.", f);
+			}
+		} catch (RemoteException e) {
+			logError("Cannot get licence for available room by dates.", e);
+		}
+		return roomSizes;
+	}
+	
+	public int createGroup()
+	throws VmsNotAvailableException {
 		try {
 			GroupServiceStub groupWs = getGroupWebService();
 			GroupServiceStub.CreateGroupRequest createRequest = new GroupServiceStub.CreateGroupRequest();
@@ -495,13 +456,44 @@ public class ViteroManager extends BasicManager {
 			GroupServiceStub.Groupid groupId = response.getCreateGroupResponse();
 			
 			return groupId.getGroupid();
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				default: logAxisError("Cannot create a group",f);
+			}
+			return -1;
 		} catch (RemoteException e) {
 			logError("Cannot create a group.", e);
 			return -1;
 		}
 	}
 	
-	public boolean addToRoom(ViteroBooking booking, Identity identity, GroupRole role) {
+	public boolean deleteGroup(ViteroBooking vBooking)
+	throws VmsNotAvailableException {
+		try {
+			GroupServiceStub groupWs = getGroupWebService();
+			GroupServiceStub.DeleteGroupRequest deleteRequest = new GroupServiceStub.DeleteGroupRequest();
+			GroupServiceStub.Groupid groupId = new GroupServiceStub.Groupid();
+			groupId.setGroupid(vBooking.getGroupId());
+			deleteRequest.setDeleteGroupRequest(groupId);
+			groupWs.deleteGroup(deleteRequest);
+			return true;
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 151: logError("Group doesn't exist!", f); break;
+				case 303: logError("Group id <= 0!", f);
+				default: logAxisError("Cannot delete group: " + vBooking.getGroupId(), f);
+			}
+			return false;
+		} catch (RemoteException e) {
+			logError("Cannot delete group: " + vBooking.getGroupId(), e);
+			return false;
+		}
+	}
+	
+	public boolean addToRoom(ViteroBooking booking, Identity identity, GroupRole role)
+	throws VmsNotAvailableException {
 		try {
 			int userId = getVmsUserId(identity);
 			if(userId < 0) {
@@ -528,17 +520,13 @@ public class ViteroManager extends BasicManager {
 			
 			return true;
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>53</errorCode>")) {
-				logError("The user doesn ́t exist!", f);
-			} else if(msg.contains("<errorCode>103</errorCode>")) {
-				logError("The user is not attached to the customer (to which this group belongs)", f);
-			} else if(msg.contains("<errorCode>151</errorCode>")) {
-				logError("The group doesn ́t exist", f);
-			}  else if(msg.contains("<errorCode>303</errorCode>")) {
-				logError("An id <= 0", f);
-			} else {
-				logError(msg, f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 53: logError("The user doesn ́t exist!", f); break;
+				case 103: logError("The user is not attached to the customer (to which this group belongs)", f); break;
+				case 151: logError("The group doesn ́t exist", f); break;
+				case 303: logError("An id <= 0", f); break;
+				default: logAxisError("Cannot add an user to a group", f);
 			}
 			return false;
 		} catch (RemoteException e) {
@@ -547,7 +535,8 @@ public class ViteroManager extends BasicManager {
 		}
 	}
 	
-	public boolean removeFromRoom(ViteroBooking booking, Identity identity) {
+	public boolean removeFromRoom(ViteroBooking booking, Identity identity)
+	throws VmsNotAvailableException {
 		try {
 			int userId = getVmsUserId(identity);
 			if(userId < 0) {
@@ -563,39 +552,58 @@ public class ViteroManager extends BasicManager {
 			groupWs.removeUserFromGroup(removeRequest);
 			return true;
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>53</errorCode>")) {
-				logError("The user doesn ́t exist!", f);
-			} else if(msg.contains("<errorCode>151</errorCode>")) {
-				logError("The group doesn ́t exist", f);
-			}  else if(msg.contains("<errorCode>303</errorCode>")) {
-				logError("An id <= 0", f);
-			} else {
-				logError(msg, f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 53: logError("The user doesn ́t exist!", f); break;
+				case 151: logError("The group doesn ́t exist", f); break;
+				case 303: logError("An id <= 0", f); break;
+				default: logAxisError("Cannot remove an user from a group", f);
 			}
 			return false;
 		} catch (RemoteException e) {
-			logError("Cannot add an user to a group", e);
+			logError("Cannot remove an user from a group", e);
 			return false;
 		}
 	}
 	
-	public ViteroBooking updateBooking(BusinessGroup group, OLATResourceable ores, ViteroBooking vBooking) {
-		Bookingtype bookingType = getBookingById(vBooking.getBookingId());
-		if(bookingType == null) {
-			logInfo("Booking doesn't exist: " + vBooking.getBookingId());
-			return null;
+	public ViteroBooking createBooking()
+	throws VmsNotAvailableException {
+		ViteroBooking booking = new ViteroBooking();
+		
+		booking.setBookingId(-1);
+		booking.setGroupId(-1);
+		
+		Calendar cal = Calendar.getInstance();
+		int minute = cal.get(Calendar.MINUTE);
+		if(minute < 10) {
+			cal.set(Calendar.MINUTE, 15);
+		} else if (minute < 25) {
+			cal.set(Calendar.MINUTE, 30);
+		} else if (minute < 40) {
+			cal.set(Calendar.MINUTE, 45);
+		} else {
+			cal.add(Calendar.HOUR, 1);
+			cal.set(Calendar.MINUTE, 0);
 		}
+
+		cal.set(Calendar.SECOND, 0);
+		cal.set(Calendar.MILLISECOND, 0);
 		
-		Booking booking = bookingType.getBooking();
-		//set the vms values
-		update(vBooking, booking);
-		//update the property
-		updateProperty(group, ores, vBooking);
-		return vBooking;
+		booking.setStart(cal.getTime());
+		booking.setStartBuffer(0);
+		cal.add(Calendar.HOUR, 1);
+		booking.setEnd(cal.getTime());
+		booking.setEndBuffer(0);
+		
+		List<Integer> roomSizes = getLicencedRoomSizes();
+		if(!roomSizes.isEmpty()) {
+			booking.setRoomSize(roomSizes.get(0));
+		}
+		return booking;
 	}
 
-	public boolean createBooking(BusinessGroup group, OLATResourceable ores, ViteroBooking vBooking) {
+	public boolean createBooking(BusinessGroup group, OLATResourceable ores, ViteroBooking vBooking)
+	throws VmsNotAvailableException {
 		Bookingtype booking = getBookingById(vBooking.getBookingId());
 		if(booking != null) {
 			logInfo("Booking already exists: " + vBooking.getBookingId());
@@ -637,10 +645,8 @@ public class ViteroManager extends BasicManager {
 			newBooking.setPcstateokrequired(false);
 			newBooking.setRepetitionpattern("once");
 			newBooking.setRepetitionenddate("");
-			
 			*/
-			//newBooking.setTimezone("Africa/Ceuta");
-			newBooking.setTimezone("Africa/Ceuta");
+			newBooking.setTimezone(viteroModule.getTimeZoneId());
 			
 			createRequest.setBooking(newBooking);
 
@@ -656,30 +662,48 @@ public class ViteroManager extends BasicManager {
 			}
 			return false;
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>502</errorCode>")) {
-				logError("Invalid module selection!", f);
-			} else if(msg.contains("<errorCode>505</errorCode>")) {
-				logError("Booking in the past!", f);
-			} else if(msg.contains("<errorCode>505</errorCode>")) {
-				logError("Booking in the past!", f);
-			} else if(msg.contains("<errorCode>501</errorCode>")) {
-				logError("Booking collision!", f);
-			} else if(msg.contains("<errorCode>703</errorCode>")) {
-				logError("License/customer expired!", f);
-			} else if(msg.contains("<errorCode>304</errorCode>")) {
-				logError("Invalid time zone!", f);
-			} else {
-				logError(msg, f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 304: logError("Invalid time zone!", f); break;
+				case 501: logError("Booking collision!", f); break;
+				case 502: logError("Invalid module selection!", f); break;
+				case 505: logError("Booking in the past!", f); break;
+				case 703: logError("License/customer expired!", f); break;
+				default: logAxisError("Cannot create a booking.", f);
 			}
 			return false;
 		} catch (RemoteException e) {
-			logError("", e);
+			logError("Cannot create a booking.", e);
 			return false;
 		}
 	}
 	
-	public boolean deleteBooking(ViteroBooking vBooking) {
+	/**
+	 * There is not update on vms. We can only update some OLAT specific options.
+	 * @param group
+	 * @param ores
+	 * @param vBooking
+	 * @return
+	 * @throws VmsNotAvailableException
+	 */
+	public ViteroBooking updateBooking(BusinessGroup group, OLATResourceable ores, ViteroBooking vBooking)
+	throws VmsNotAvailableException {
+		Bookingtype bookingType = getBookingById(vBooking.getBookingId());
+		if(bookingType == null) {
+			logInfo("Booking doesn't exist: " + vBooking.getBookingId());
+			return null;
+		}
+		
+		Booking booking = bookingType.getBooking();
+		//set the vms values
+		update(vBooking, booking);
+		//update the property
+		updateProperty(group, ores, vBooking);
+		return vBooking;
+	}
+	
+	public boolean deleteBooking(ViteroBooking vBooking)
+	throws VmsNotAvailableException {
 		try {
 			BookingServiceStub bookingWs = getBookingWebService();
 			BookingServiceStub.DeleteBookingRequest deleteRequest = new BookingServiceStub.DeleteBookingRequest();
@@ -691,91 +715,212 @@ public class ViteroManager extends BasicManager {
 			deleteProperty(vBooking);
 			return state != null;
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>509</errorCode>") || msg.contains("<errorCode>506</errorCode>")) {
-				//why is vms sending this error if it deletes the room???
-				deleteGroup(vBooking);
-				deleteProperty(vBooking);
-			} else {
-				logError(f.getFaultDetailElement().toString(), f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 506:
+				case 509: {
+					deleteGroup(vBooking);
+					deleteProperty(vBooking);
+					break;
+				}
+				default: {
+					logAxisError("Cannot delete a booking.", f);
+				}
 			}
 			return false;
 		} catch (RemoteException e) {
-			logError("", e);
+			logError("Cannot delete a booking.", e);
 			return false;
 		}
 	}
 	
-	public boolean deleteGroup(ViteroBooking vBooking) {
+	public void deleteAll(BusinessGroup group, OLATResourceable ores) {
 		try {
-			GroupServiceStub groupWs = getGroupWebService();
-			GroupServiceStub.DeleteGroupRequest deleteRequest = new GroupServiceStub.DeleteGroupRequest();
-			GroupServiceStub.Groupid groupId = new GroupServiceStub.Groupid();
-			groupId.setGroupid(vBooking.getGroupId());
-			deleteRequest.setDeleteGroupRequest(groupId);
-			groupWs.deleteGroup(deleteRequest);
-			return true;
-		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>151</errorCode>")) {
-				logError("Group doesn't exist!", f);
-			} else if(msg.contains("<errorCode>303</errorCode>")) {
-				logError("Group id <= 0!", f);
-			} else {
-				logError(msg, f);
+			List<Property> properties = propertyManager.listProperties(null, group, ores, VMS_CATEGORY, null);
+			for(Property property:properties) {
+				String bookingStr = property.getTextValue();
+				ViteroBooking booking = deserializeViteroBooking(bookingStr);
+				deleteBooking(booking);
 			}
-			return false;
-		} catch (RemoteException e) {
-			logError("Cannot delete group: " + vBooking.getGroupId(), e);
-			return false;
+		} catch (VmsNotAvailableException e) {
+			logError("", e);
+			markAsZombie(group, ores);
 		}
-		
 	}
 	
-	public void deleteBookings(BusinessGroup group, OLATResourceable ores) {
-		
+	private final void markAsZombie(BusinessGroup group, OLATResourceable ores) {
+		List<Property> properties = propertyManager.listProperties(null, group, ores, VMS_CATEGORY, null);
+		for(Property property:properties) {
+			property.setName(VMS_CATEGORY_ZOMBIE);
+			propertyManager.updateProperty(property);
+		}
 	}
 	
-	protected void deleteProperty(ViteroBooking vBooking) {
-		String bookingId = Integer.toString(vBooking.getBookingId());
-		propertyManager.deleteProperties(null, null, null, VMS_CATEGORY, bookingId);
+	public void slayZombies() {
+		List<Property> properties = propertyManager.listProperties(null, null, null, VMS_CATEGORY_ZOMBIE, null);
+		for(Property property:properties) {
+			try {
+				String bookingStr = property.getTextValue();
+				ViteroBooking booking = deserializeViteroBooking(bookingStr);
+				deleteBooking(booking);
+			} catch (VmsNotAvailableException e) {
+				//try later
+				logDebug("Cannot clean-up vitero room, vms not available");
+			} catch (Exception e) {
+				logError("", e);
+			}
+		}
 	}
 	
-	public String getTimeZoneId() {
-		return "Africa/Ceuta";
+	public List<ViteroBooking> getBookingInFutures(Identity identity)
+	throws VmsNotAvailableException {
+		int userId = getVmsUserId(identity);
+		Booking[] bookings = getBookingInFutureByCustomerId(userId);
+		return convert(bookings);
+	}
+	
+	/**
+	 * Return the 
+	 * @param group The group (optional)
+	 * @param ores The OLAT resourceable (of the course) (optional)
+	 * @return
+	 */
+	public List<ViteroBooking> getBookings(BusinessGroup group, OLATResourceable ores) {
+		List<Property> properties = propertyManager.listProperties(null, group, ores, VMS_CATEGORY, null);
+		List<ViteroBooking> bookings = new ArrayList<ViteroBooking>();
+		for(Property property:properties) {
+			String bookingStr = property.getTextValue();
+			ViteroBooking booking = deserializeViteroBooking(bookingStr);
+			bookings.add(booking);
+		}
+		return bookings;
 	}
 	
-	protected Booking[] getBookingInFutureByCustomerId(int userId) {
+	protected Booking[] getBookingInFutureByCustomerId(int userId)
+	throws VmsNotAvailableException {
 		try {
 			BookingServiceStub bookingWs = getBookingWebService();
 			BookingServiceStub.GetBookingListByUserInFutureRequest request = new BookingServiceStub.GetBookingListByUserInFutureRequest();
 			request.setUserid(userId);
-			request.setTimezone(getTimeZoneId());
+			request.setTimezone(viteroModule.getTimeZoneId());
 			
 			BookingServiceStub.GetBookingListByUserInFutureResponse response = bookingWs.getBookingListByUserInFuture(request);
 			Bookinglist bookingList = response.getGetBookingListByUserInFutureResponse();
 			
 			return bookingList.getBooking();
 		} catch(AxisFault f) {
-			String msg = f.getFaultDetailElement().toString();
-			if(msg.contains("<errorCode>304</errorCode>")) {
-				logError("Invalid time zone!", f);
-			} else if(msg.contains("<errorCode>53</errorCode>")) {
-				logError("The user does not exist!", f);
-			} else if(msg.contains("<errorCode>303</errorCode>")) {
-				logError("ids <= 0!", f);
-			} else {
-				logError(msg, f);
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 53: logError("The user does not exist!", f); break;
+				case 303: logError("ids <= 0!", f); break;
+				case 304: logError("Invalid time zone!", f); break;
+				default: logAxisError("Cannot get booking in future for custom: " + userId, f);
 			}
-			logError(msg, f);
 			return null;
 		} catch (RemoteException e) {
-			logError("", e);
+			logError("Cannot get booking in future for custom: " + userId, e);
+			return null;
+		}
+	}
+
+	protected Bookingtype getBookingById(int id)
+	throws VmsNotAvailableException {
+		if(id < 0) return null;
+		
+		try {
+			BookingServiceStub bookingWs = getBookingWebService();
+			BookingServiceStub.GetBookingByIdRequest bookingByIdRequest = new BookingServiceStub.GetBookingByIdRequest();
+			BookingServiceStub.Bookingid bookingId = new BookingServiceStub.Bookingid();
+			bookingId.setBookingid(id);
+			bookingByIdRequest.setGetBookingByIdRequest(bookingId);
+			BookingServiceStub.GetBookingByIdResponse response = bookingWs.getBookingById(bookingByIdRequest);
+			Bookingtype booking = response.getGetBookingByIdResponse();
+			return booking;
+		} catch(AxisFault f) {
+			int code = handleAxisFault(f);
+			switch(code) {
+				case 303: logError("ids <= 0", f); break;
+				case 506: logError("The booking does not exist", f); break;
+				default: logAxisError("Cannot get booking by id: " + id, f);
+			}
+			return null;
+		} catch (RemoteException e) {
+			logError("Cannot get booking by id: " + id, e);
 			return null;
 		}
 	}
 	
-	protected List<ViteroBooking> convert(Booking[] bookings) {
+	public boolean checkConnection() {
+		try {
+			return checkConnection(viteroModule.getVmsURI().toString(), viteroModule.getAdminLogin(), 
+					viteroModule.getAdminPassword(), viteroModule.getCustomerId());
+		} catch (VmsNotAvailableException e) {
+			return false;
+		}
+	}
+	
+	public boolean checkConnection(String url, String login, String password, int customerId)
+	throws VmsNotAvailableException {
+		try {
+			CustomerServiceStub customerWs = new CustomerServiceStub(url + "/services");
+			SecurityHeader.addAdminSecurityHeader(login, password, customerWs);
+			
+			CustomerServiceStub.GetCustomerRequest cRequest = new CustomerServiceStub.GetCustomerRequest();
+			CustomerServiceStub.Customerid id = new CustomerServiceStub.Customerid();
+			id.setCustomerid(customerId);
+			cRequest.setGetCustomerRequest(id);
+			CustomerServiceStub.GetCustomerResponse response = customerWs.getCustomer(cRequest);
+			if(response == null) return false;
+			CustomerServiceStub.Customer customer = response.getGetCustomerResponse();
+			if(customer == null) return false;
+			CustomerServiceStub.Customertype customerType = customer.getCustomer();
+			if(customerType == null) return false;
+			return customerType.getId() > -1;
+		} catch(AxisFault f) {
+			handleAxisFault(f);
+			return false;
+		} catch (Exception e) {
+			logWarn("Error checking connection", e);
+			return false;
+		}
+	}
+	
+	//Utilities
+	private final int handleAxisFault(final AxisFault f) 
+	throws VmsNotAvailableException {
+		if(f.getFaultDetailElement() != null) {
+			String msg = f.getFaultDetailElement().toString();
+			int beginIndex = msg.indexOf("<errorCode>");
+			int endIndex = msg.indexOf("</errorCode>");
+			String errorCode = msg.substring(beginIndex + "<errorCode>".length(), endIndex);
+			int code = Integer.parseInt(errorCode);
+			return code;
+		} else if (f.getCause() instanceof ConnectTimeoutException) {
+			throw new VmsNotAvailableException(f);
+		}
+		return -1;
+	}
+	
+	private void logAxisError(String message, AxisFault f) {
+		StringBuilder sb = new StringBuilder();
+		if(StringHelper.containsNonWhitespace(message)) {
+			sb.append(message);
+		}
+		
+		if(f.getFaultDetailElement() != null) {
+			if(sb.length() > 0) sb.append(" -> ");
+			sb.append(f.getFaultDetailElement().toString());
+		}
+		
+		if(StringHelper.containsNonWhitespace(f.getMessage())) {
+			if(sb.length() > 0) sb.append(" -> ");
+			sb.append(f.getMessage());
+		}
+
+		logError(sb.toString(), f);
+	}
+	
+	private final List<ViteroBooking> convert(Booking[] bookings) {
 		List<ViteroBooking> viteroBookings = new ArrayList<ViteroBooking>();
 		
 		if(bookings != null && bookings.length > 0) {
@@ -787,12 +932,12 @@ public class ViteroManager extends BasicManager {
 		return viteroBookings;
 	}
 	
-	protected ViteroBooking convert(Booking booking) {
+	private final ViteroBooking convert(Booking booking) {
 		ViteroBooking vb = new ViteroBooking();
 		return update(vb, booking);
 	}
 	
-	protected ViteroBooking update(ViteroBooking vb, Booking booking) {
+	private final ViteroBooking update(ViteroBooking vb, Booking booking) {
 		vb.setBookingId(booking.getBookingid());
 		vb.setGroupId(booking.getGroupid());
 		vb.setRoomSize(booking.getRoomsize());
@@ -803,12 +948,13 @@ public class ViteroManager extends BasicManager {
 		return vb;
 	}
 	
-	protected Property getProperty(final BusinessGroup group, final OLATResourceable courseResource, final ViteroBooking booking) {
+	//Properties
+	private final Property getProperty(final BusinessGroup group, final OLATResourceable courseResource, final ViteroBooking booking) {
 		String propertyName = Integer.toString(booking.getBookingId());
 		return propertyManager.findProperty(null, group, courseResource, VMS_CATEGORY, propertyName);
 	}
 	
-	protected Property getOrCreateProperty(final BusinessGroup group, final OLATResourceable courseResource, final ViteroBooking booking) {
+	private final Property getOrCreateProperty(final BusinessGroup group, final OLATResourceable courseResource, final ViteroBooking booking) {
 		Property property = getProperty(group, courseResource, booking);
 		if(property == null) {
 			property = createProperty(group, courseResource, booking);
@@ -817,7 +963,7 @@ public class ViteroManager extends BasicManager {
 		return property;
 	}
 	
-	protected Property updateProperty(final BusinessGroup group, final OLATResourceable courseResource, ViteroBooking booking) {
+	private final Property updateProperty(final BusinessGroup group, final OLATResourceable courseResource, ViteroBooking booking) {
 		Property property = getProperty(group, courseResource, booking);
 		if(property == null) {
 			property = createProperty(group, courseResource, booking);
@@ -830,126 +976,79 @@ public class ViteroManager extends BasicManager {
 		return property;
 	}
 	
-	protected Property createProperty(final BusinessGroup group, final OLATResourceable courseResource, ViteroBooking booking) {
+	private final Property createProperty(final BusinessGroup group, final OLATResourceable courseResource, ViteroBooking booking) {
 		String serialized = serializeViteroBooking(booking);
 		String bookingId = Integer.toString(booking.getBookingId());
 		Long groupId = new Long(booking.getGroupId());
 		return propertyManager.createPropertyInstance(null, group, courseResource, VMS_CATEGORY, bookingId, null, groupId, null, serialized);
 	}
 	
-	protected Bookingtype getBookingById(int id) {
-		if(id < 0) return null;
-		
-		try {
-			BookingServiceStub bookingWs = getBookingWebService();
-			BookingServiceStub.GetBookingByIdRequest bookingByIdRequest = new BookingServiceStub.GetBookingByIdRequest();
-			BookingServiceStub.Bookingid bookingId = new BookingServiceStub.Bookingid();
-			bookingId.setBookingid(id);
-			bookingByIdRequest.setGetBookingByIdRequest(bookingId);
-			BookingServiceStub.GetBookingByIdResponse response = bookingWs.getBookingById(bookingByIdRequest);
-			Bookingtype booking = response.getGetBookingByIdResponse();
-			return booking;
-		} catch (RemoteException e) {
-			logError("Cannot get booking by id: " + id, e);
-			return null;
-		}
+	private final void deleteProperty(ViteroBooking vBooking) {
+		String bookingId = Integer.toString(vBooking.getBookingId());
+		propertyManager.deleteProperties(null, null, null, VMS_CATEGORY, bookingId);
 	}
 	
-	public boolean checkConnection(String url, String login, String password, int customerId) {
-		try {
-			CustomerServiceStub customerWs = new CustomerServiceStub(url + "/services");
-			SecurityHeader.addAdminSecurityHeader(login, password, customerWs);
-			
-			CustomerServiceStub.GetCustomerRequest cRequest = new CustomerServiceStub.GetCustomerRequest();
-			CustomerServiceStub.Customerid id = new CustomerServiceStub.Customerid();
-			id.setCustomerid(customerId);
-			cRequest.setGetCustomerRequest(id);
-			CustomerServiceStub.GetCustomerResponse response = customerWs.getCustomer(cRequest);
-			if(response == null) return false;
-			CustomerServiceStub.Customer customer = response.getGetCustomerResponse();
-			if(customer == null) return false;
-			CustomerServiceStub.Customertype customerType = customer.getCustomer();
-			if(customerType == null) return false;
-			return customerType.getId() > -1;
-		} catch (Exception e) {
-			logWarn("Error checking connection", e);
-			return false;
-		}
+	private final String serializeViteroBooking(ViteroBooking booking) {
+		StringWriter writer = new StringWriter();
+		xStream.marshal(booking, new CompactWriter(writer));
+		writer.flush();
+		return writer.toString();
 	}
 	
-	protected BookingServiceStub getBookingWebService() {
-		try {
-			BookingServiceStub bookingWs = new BookingServiceStub(getVmsEndPoint());
-			SecurityHeader.addAdminSecurityHeader(viteroModule, bookingWs);
-			return bookingWs;
-		} catch (AxisFault e) {
-			logError("Cannot create booking ws.", e);
-			return null;
-		}
+	private final ViteroBooking deserializeViteroBooking(String booking) {
+		return (ViteroBooking)xStream.fromXML(booking);
 	}
 	
-	protected LicenceServiceStub getLicenceWebService() {
-		try {
-			LicenceServiceStub licenceWs = new LicenceServiceStub(getVmsEndPoint());
-			SecurityHeader.addAdminSecurityHeader(viteroModule, licenceWs);
-			return licenceWs;
-		} catch (AxisFault e) {
-			logError("Cannot create licence ws.", e);
-			return null;
-		}
+	//Factories for service stubs
+	private final  BookingServiceStub getBookingWebService() 
+	throws AxisFault {
+		BookingServiceStub bookingWs = new BookingServiceStub(getVmsEndPoint());
+		SecurityHeader.addAdminSecurityHeader(viteroModule, bookingWs);
+		return bookingWs;
 	}
 	
-	protected GroupServiceStub getGroupWebService() {
-		try {
-			GroupServiceStub groupWs = new GroupServiceStub(getVmsEndPoint());
-			SecurityHeader.addAdminSecurityHeader(viteroModule, groupWs);
-			return groupWs;
-		} catch (AxisFault e) {
-			logError("Cannot create group ws.", e);
-			return null;
-		}
+	private final LicenceServiceStub getLicenceWebService()
+	throws AxisFault {
+		LicenceServiceStub licenceWs = new LicenceServiceStub(getVmsEndPoint());
+		SecurityHeader.addAdminSecurityHeader(viteroModule, licenceWs);
+		return licenceWs;
 	}
 	
-	protected UserServiceStub getUserWebService() {
-		try {
-			UserServiceStub userWs = new UserServiceStub(getVmsEndPoint());
-			SecurityHeader.addAdminSecurityHeader(viteroModule, userWs);
-			return userWs;
-		} catch (AxisFault e) {
-			logError("Cannot create user ws.", e);
-			return null;
-		}
+	private final GroupServiceStub getGroupWebService()
+	throws AxisFault {
+		GroupServiceStub groupWs = new GroupServiceStub(getVmsEndPoint());
+		SecurityHeader.addAdminSecurityHeader(viteroModule, groupWs);
+		return groupWs;
 	}
 	
-	protected MtomServiceStub getMtomWebService() {
-		try {
-			MtomServiceStub mtomWs = new MtomServiceStub(getVmsEndPoint());
-			SecurityHeader.addAdminSecurityHeader(viteroModule, mtomWs);
-			return mtomWs;
-		} catch (AxisFault e) {
-			logError("Cannot create user ws.", e);
-			return null;
-		}
+	private final UserServiceStub getUserWebService()
+	throws AxisFault {
+		UserServiceStub userWs = new UserServiceStub(getVmsEndPoint());
+		SecurityHeader.addAdminSecurityHeader(viteroModule, userWs);
+		return userWs;
 	}
 	
-	protected SessionCodeServiceStub getSessionCodeWebService() {
-		try {
-			SessionCodeServiceStub sessionCodeWs = new SessionCodeServiceStub(getVmsEndPoint());
-			SecurityHeader.addAdminSecurityHeader(viteroModule, sessionCodeWs);
-			return sessionCodeWs;
-		} catch (AxisFault e) {
-			logError("Cannot create user ws.", e);
-			return null;
-		}
+	private final MtomServiceStub getMtomWebService() 
+	throws AxisFault {
+		MtomServiceStub mtomWs = new MtomServiceStub(getVmsEndPoint());
+		SecurityHeader.addAdminSecurityHeader(viteroModule, mtomWs);
+		return mtomWs;
+	}
+	
+	private final SessionCodeServiceStub getSessionCodeWebService()
+	throws AxisFault {
+		SessionCodeServiceStub sessionCodeWs = new SessionCodeServiceStub(getVmsEndPoint());
+		SecurityHeader.addAdminSecurityHeader(viteroModule, sessionCodeWs);
+		return sessionCodeWs;
 	}
 
-	protected String getVmsEndPoint() {
+	private final String getVmsEndPoint() {
 	    UriBuilder builder = UriBuilder.fromUri(viteroModule.getVmsURI());
 	    builder.path("services");
 	    return builder.build().toString();
 	}
 	
-	protected String getStartPoint(String sessionCode) {
+	private final String getStartPoint(String sessionCode) {
 		UriBuilder builder = UriBuilder.fromUri(viteroModule.getVmsURI() );
 	    builder.path("start.html");
 	    if(StringHelper.containsNonWhitespace(sessionCode)) {
@@ -958,11 +1057,11 @@ public class ViteroManager extends BasicManager {
 	    return builder.build().toString();
 	}
 	
-	protected synchronized String format(Date date) {
+	private final synchronized String format(Date date) {
 		return dateFormat.format(date);
 	}
 	
-	protected synchronized Date parse(String dateString) {
+	private final synchronized Date parse(String dateString) {
 		try {
 			return dateFormat.parse(dateString);
 		} catch (ParseException e) {
diff --git a/src/main/java/com/frentix/olat/vitero/manager/ViteroTestMain.java b/src/main/java/com/frentix/olat/vitero/manager/ViteroTestMain.java
index bd4b4bca2cd..d5c9fc69420 100644
--- a/src/main/java/com/frentix/olat/vitero/manager/ViteroTestMain.java
+++ b/src/main/java/com/frentix/olat/vitero/manager/ViteroTestMain.java
@@ -20,8 +20,6 @@
  */
 package com.frentix.olat.vitero.manager;
 
-import java.util.Date;
-
 import com.frentix.olat.vitero.ViteroModule;
 import com.frentix.olat.vitero.manager.stubs.BookingServiceStub.Bookingtype;
 
@@ -40,7 +38,7 @@ public class ViteroTestMain {
 	private final ViteroManager manager;
 	
 	public ViteroTestMain() {
-		module = new ViteroModule();
+		module = new ViteroModule(null);
 		module.setAdminLogin("admin");
 		module.setAdminPassword("007");
 		module.setProtocol("http");
@@ -63,14 +61,22 @@ public class ViteroTestMain {
 	}
 	
 	public void testGetBookingById(int id) {
-		Bookingtype type = manager.getBookingById(id);
-		System.out.println(type.getBooking().getBookingid());
+		try {
+			Bookingtype type = manager.getBookingById(id);
+			System.out.println(type.getBooking().getBookingid());
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
 	}
 	
 	public void testGetLicense() {
 		
-		manager.getLicence(new Date(), new Date());
-		System.out.println("Licence");
+		try {
+			manager.getLicencedRoomSizes();
+			System.out.println("Licence");
+		} catch (VmsNotAvailableException e) {
+			e.printStackTrace();
+		}
 	}
 	
 
diff --git a/src/main/java/com/frentix/olat/vitero/manager/ViteroZombieSlayerJob.java b/src/main/java/com/frentix/olat/vitero/manager/ViteroZombieSlayerJob.java
new file mode 100644
index 00000000000..991ea4d999c
--- /dev/null
+++ b/src/main/java/com/frentix/olat/vitero/manager/ViteroZombieSlayerJob.java
@@ -0,0 +1,33 @@
+package com.frentix.olat.vitero.manager;
+
+import org.olat.core.CoreSpringFactory;
+import org.olat.core.commons.scheduler.JobWithDB;
+import org.quartz.JobExecutionContext;
+
+import com.frentix.olat.vitero.ViteroModule;
+
+/**
+ * 
+ * Description:<br>
+ * Quartz job which try to slay the meeting zombies from deleted
+ * resources/groups. Make is slayer's job only if the module
+ * is enabled and a connection with the vms is possible.
+ * 
+ * <P>
+ * Initial Date:  12 oct. 2011 <br>
+ *
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class ViteroZombieSlayerJob extends JobWithDB  {
+
+	@Override
+	public void executeWithDB(JobExecutionContext arg0) {
+		ViteroModule module = (ViteroModule)CoreSpringFactory.getBean("viteroModule");
+		if(!module.isEnabled()) return;
+
+		ViteroManager viteroManager = (ViteroManager)CoreSpringFactory.getBean("viteroManager");
+		if(viteroManager.checkConnection()) {
+			viteroManager.slayZombies();
+		}
+	}
+}
diff --git a/src/main/java/com/frentix/olat/vitero/manager/VmsNotAvailableException.java b/src/main/java/com/frentix/olat/vitero/manager/VmsNotAvailableException.java
new file mode 100644
index 00000000000..c5e4d2b45f3
--- /dev/null
+++ b/src/main/java/com/frentix/olat/vitero/manager/VmsNotAvailableException.java
@@ -0,0 +1,54 @@
+/**
+ * OLAT - Online Learning and Training<br>
+ * http://www.olat.org
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); <br>
+ * you may not use this file except in compliance with the License.<br>
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing,<br>
+ * software distributed under the License is distributed on an "AS IS" BASIS, <br>
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
+ * See the License for the specific language governing permissions and <br>
+ * limitations under the License.
+ * <p>
+ * Copyright (c) frentix GmbH<br>
+ * http://www.frentix.com<br>
+ * <p>
+ */
+package com.frentix.olat.vitero.manager;
+
+/**
+ * 
+ * Description:<br>
+ * 
+ * <P>
+ * Initial Date:  12 oct. 2011 <br>
+ *
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ */
+public class VmsNotAvailableException extends Exception {
+	
+	private static final long serialVersionUID = 3260533359384969602L;
+	
+	public static final String I18N_KEY = "vc.vmsNotAvailable";
+
+	public VmsNotAvailableException() {
+		//
+	}
+	
+	public VmsNotAvailableException(String message) {
+		super(message);
+	}
+	
+	public VmsNotAvailableException(String message, Exception cause) {
+		super(message, cause);
+	}
+	
+	public VmsNotAvailableException(Exception cause) {
+		super(cause);
+	}
+
+}
diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingEditController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingEditController.java
index 9b409e6c1d2..f3a73ca98f3 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingEditController.java
+++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingEditController.java
@@ -20,6 +20,7 @@
  */
 package com.frentix.olat.vitero.ui;
 
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -38,6 +39,7 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.group.BusinessGroup;
 
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 import com.frentix.olat.vitero.model.ViteroBooking;
 
 /**
@@ -78,14 +80,20 @@ public class ViteroBookingEditController extends FormBasicController {
 		this.booking = booking;
 		viteroManager = (ViteroManager)CoreSpringFactory.getBean("viteroManager");
 		
-		List<Integer> sizes = viteroManager.getLicencedRoomSizes();
+		List<Integer> sizes;
+		try {
+			sizes = viteroManager.getLicencedRoomSizes();
+			
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
+			sizes = Collections.emptyList();
+		}
 		roomSizes = new String[sizes.size()];
 		
 		int i=0;
 		for(Integer size:sizes) {
 			roomSizes[i++] = size.toString();
 		}
-		
 		autoSignInValues = new String[]{ translate("enabled") };
 		
 		initForm(ureq);
@@ -212,21 +220,25 @@ public class ViteroBookingEditController extends FormBasicController {
 		boolean auto = autoSignIn.isMultiselect() && autoSignIn.isSelected(0);
 		booking.setAutoSignIn(auto);
 		
-		if(booking.getBookingId() >= 0) {
-			ViteroBooking updatedBooking = viteroManager.updateBooking(group, ores, booking);
-			if(updatedBooking != null) {
-				showInfo("vc.check.ok");
-				fireEvent(ureq, Event.DONE_EVENT);
-			} else {
-				showError("vc.check.nok");
-			}
-		} else {
-			if(viteroManager.createBooking(group, ores, booking)) {
-				showInfo("vc.check.ok");
-				fireEvent(ureq, Event.DONE_EVENT);
+		try {
+			if(booking.getBookingId() >= 0) {
+				ViteroBooking updatedBooking = viteroManager.updateBooking(group, ores, booking);
+				if(updatedBooking != null) {
+					showInfo("vc.check.ok");
+					fireEvent(ureq, Event.DONE_EVENT);
+				} else {
+					showError("vc.check.nok");
+				}
 			} else {
-				showError("vc.check.nok");
+				if(viteroManager.createBooking(group, ores, booking)) {
+					showInfo("vc.check.ok");
+					fireEvent(ureq, Event.DONE_EVENT);
+				} else {
+					showError("vc.check.nok");
+				}
 			}
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
 
 	}
diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsAdminController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsAdminController.java
index b1d839030ce..b56ff727586 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsAdminController.java
+++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsAdminController.java
@@ -39,6 +39,7 @@ import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.gui.media.RedirectMediaResource;
 
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 import com.frentix.olat.vitero.model.ViteroBooking;
 
 /**
@@ -118,12 +119,16 @@ public class ViteroBookingsAdminController extends BasicController {
 	}
 	
 	protected void deleteBooking(UserRequest ureq, ViteroBooking booking) {
-		if( viteroManager.deleteBooking(booking)) {
-			showInfo("vc.table.delete");
-		} else {
-			showError("vc.table.delete");
+		try {
+			if( viteroManager.deleteBooking(booking)) {
+				showInfo("vc.table.delete");
+			} else {
+				showError("vc.table.delete");
+			}
+			reloadModel();
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
-		reloadModel();
 	}
 	
 	protected void confirmDeleteVitero(UserRequest ureq, ViteroBooking booking) {
@@ -134,13 +139,17 @@ public class ViteroBookingsAdminController extends BasicController {
 	}
 	
 	protected void openVitero(UserRequest ureq, ViteroBooking booking) {
-		String url = viteroManager.getURLToBooking(ureq.getIdentity(), booking);
-		RedirectMediaResource redirect = new RedirectMediaResource(url);
-		ureq.getDispatchResult().setResultingMediaResource(redirect);
+		try {
+			String url = viteroManager.getURLToBooking(ureq.getIdentity(), booking);
+			RedirectMediaResource redirect = new RedirectMediaResource(url);
+			ureq.getDispatchResult().setResultingMediaResource(redirect);
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
+		}
 	}
 	
 	protected void reloadModel() {
-		List<ViteroBooking> bookings = viteroManager.getBookings();
+		List<ViteroBooking> bookings = viteroManager.getBookings(null, null);
 		ViteroBookingDataModel tableModel = new ViteroBookingDataModel(bookings);
 		tableCtr.setTableDataModel(tableModel);
 	}
diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsController.java
index 639e76c8eaf..5642256b9bd 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsController.java
+++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsController.java
@@ -40,6 +40,7 @@ import org.olat.core.id.OLATResourceable;
 import org.olat.group.BusinessGroup;
 
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 import com.frentix.olat.vitero.model.StartBookingComparator;
 import com.frentix.olat.vitero.model.ViteroBooking;
 
@@ -126,37 +127,56 @@ public class ViteroBookingsController extends BasicController {
 	}
 	
 	protected void loadModel() {
-		List<ViteroBooking> bookings = viteroManager.getBookings(group, ores);
-		List<ViteroBooking> myBookings = viteroManager.getBookingInFutures(getIdentity());
-		FilterBookings.filterMyFutureBookings(bookings, myBookings);
-		Collections.sort(bookings, new StartBookingComparator());
-		TableDataModel tableData = new ViteroBookingDataModel(bookings, myBookings);
-		tableCtr.setTableDataModel(tableData);
+		try {
+			List<ViteroBooking> bookings = viteroManager.getBookings(group, ores);
+			List<ViteroBooking> myBookings = viteroManager.getBookingInFutures(getIdentity());
+			FilterBookings.filterMyFutureBookings(bookings, myBookings);
+			Collections.sort(bookings, new StartBookingComparator());
+			TableDataModel tableData = new ViteroBookingDataModel(bookings, myBookings);
+			tableCtr.setTableDataModel(tableData);
+		} catch (VmsNotAvailableException e) {
+			TableDataModel tableData = new ViteroBookingDataModel();
+			tableCtr.setTableDataModel(tableData);
+			showError(VmsNotAvailableException.I18N_KEY);
+		}
 	}
 	
 	protected void signInVitero(UserRequest ureq, ViteroBooking booking) {
-		boolean ok = viteroManager.addToRoom(booking, ureq.getIdentity(), null);
-		if(ok) {
-			showInfo("signin.ok");
-		} else {
-			showError("signin.nok");
+		try {
+			boolean ok = viteroManager.addToRoom(booking, ureq.getIdentity(), null);
+			if(ok) {
+				showInfo("signin.ok");
+			} else {
+				showError("signin.nok");
+			}
+			loadModel();
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
-		loadModel();
+		
 	}
 	
 	protected void signOutVitero(UserRequest ureq, ViteroBooking booking) {
-		boolean ok = viteroManager.removeFromRoom(booking, ureq.getIdentity());
-		if(ok) {
-			showInfo("signout.ok");
-		} else {
-			showError("signout.nok");
+		try {
+			boolean ok = viteroManager.removeFromRoom(booking, ureq.getIdentity());
+			if(ok) {
+				showInfo("signout.ok");
+			} else {
+				showError("signout.nok");
+			}
+			loadModel();
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
-		loadModel();
 	}
 	
 	protected void openVitero(UserRequest ureq, ViteroBooking booking) {
-		String url = viteroManager.getURLToBooking(ureq.getIdentity(), booking);
-		RedirectMediaResource redirect = new RedirectMediaResource(url);
-		ureq.getDispatchResult().setResultingMediaResource(redirect); 
+		try {
+			String url = viteroManager.getURLToBooking(ureq.getIdentity(), booking);
+			RedirectMediaResource redirect = new RedirectMediaResource(url);
+			ureq.getDispatchResult().setResultingMediaResource(redirect);
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
+		} 
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsEditController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsEditController.java
index de9eb4bcaa0..460716364c4 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsEditController.java
+++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroBookingsEditController.java
@@ -44,6 +44,7 @@ import org.olat.course.editor.NodeEditController;
 import org.olat.group.BusinessGroup;
 
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 import com.frentix.olat.vitero.model.ViteroBooking;
 
 /**
@@ -174,12 +175,16 @@ public class ViteroBookingsEditController extends FormBasicController {
 	}
 	
 	protected void deleteBooking(UserRequest ureq, ViteroBooking booking) {
-		if( viteroManager.deleteBooking(booking)) {
-			showInfo("vc.table.delete");
-		} else {
-			showError("vc.table.delete");
+		try {
+			if( viteroManager.deleteBooking(booking)) {
+				showInfo("vc.table.delete");
+			} else {
+				showError("vc.table.delete");
+			}
+			reloadModel();
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
-		reloadModel();
 	}
 
 	protected void confirmDeleteBooking(UserRequest ureq, BookingDisplay bookingDisplay) {
@@ -190,8 +195,12 @@ public class ViteroBookingsEditController extends FormBasicController {
 	}
 	
 	protected void newBooking(UserRequest ureq) {
-		ViteroBooking viteroBooking = viteroManager.createBooking();
-		editBooking(ureq, viteroBooking);
+		try {
+			ViteroBooking viteroBooking = viteroManager.createBooking();
+			editBooking(ureq, viteroBooking);
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
+		}
 	}
 	
 	protected void editBooking(UserRequest ureq, ViteroBooking viteroBooking) {
diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroConfigurationController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroConfigurationController.java
index 77d94be9dd4..70c292b1ad9 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/ViteroConfigurationController.java
+++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroConfigurationController.java
@@ -22,6 +22,7 @@ package com.frentix.olat.vitero.ui;
 
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.TimeZone;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
@@ -29,6 +30,7 @@ import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
+import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
@@ -39,7 +41,9 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.util.StringHelper;
 
 import com.frentix.olat.vitero.ViteroModule;
+import com.frentix.olat.vitero.ViteroTimezoneIDs;
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 
 /**
  * 
@@ -61,8 +65,9 @@ public class ViteroConfigurationController extends FormBasicController {
 	private TextElement passwordEl;
 	private TextElement customerIdEl;
 	private MultipleSelectionElement viteroEnabled;
+	private SingleSelection timeZoneEl;
 
-	private static String[] enabledKeys = new String[]{"on"};
+	private static final String[] enabledKeys = new String[]{"on"};
 	private String[] enabledValues;
 	
 	public ViteroConfigurationController(UserRequest ureq, WindowControl wControl, ViteroModule viteroModule) {
@@ -92,6 +97,22 @@ public class ViteroConfigurationController extends FormBasicController {
 			//spacer
 			uifactory.addSpacerElement("Spacer", moduleFlc, false);
 			
+			String[] timeZoneKeys = ViteroTimezoneIDs.TIMEZONE_IDS;
+			String[] timeZoneValues = new String[timeZoneKeys.length];
+			int i=0;
+			for(String timeZoneKey:timeZoneKeys) {
+				TimeZone timezone = TimeZone.getTimeZone(timeZoneKey);
+				if(timezone == null) {
+					timeZoneValues[i++] = timeZoneKey;
+				} else {
+					String value = timezone.getDisplayName(false, TimeZone.LONG);
+					timeZoneValues[i++] = value;
+				}
+			}
+
+			timeZoneEl = uifactory.addDropdownSingleselect("vc.olatTimeZone", moduleFlc, timeZoneKeys, timeZoneValues, null);
+			timeZoneEl.select(viteroModule.getTimeZoneId(), true);
+			
 			//account configuration
 			String vmsUri = viteroModule.getVmsURI().toString();
 			urlEl = uifactory.addTextElement("vitero-url", "vc.vitero.baseurl", 255, vmsUri, moduleFlc);
@@ -130,6 +151,11 @@ public class ViteroConfigurationController extends FormBasicController {
 			
 			String customerId = customerIdEl.getValue();
 			viteroModule.setCustomerId(Integer.parseInt(customerId));
+			
+			if(timeZoneEl.isOneSelected()) {
+				String timeZoneId = timeZoneEl.getSelectedKey();
+				viteroModule.setTimeZoneId(timeZoneId);
+			}
 		} catch (URISyntaxException e) {
 			logError("", e);
 			urlEl.setErrorKey("vc.check.url.invalid", null);
@@ -207,11 +233,17 @@ public class ViteroConfigurationController extends FormBasicController {
 		String password = passwordEl.getValue();
 		String customerId = customerIdEl.getValue();
 
-		boolean ok = viteroManager.checkConnection(url, login, password, Integer.parseInt(customerId));
-		if(ok) {
-			showInfo("vc.check.ok");
-		} else {
-			showError("vc.check.nok");
+		try {
+			boolean ok = viteroManager.checkConnection(url, login, password, Integer.parseInt(customerId));
+			if(ok) {
+				showInfo("vc.check.ok");
+			} else {
+				showError("vc.check.nok");
+			}
+		} catch (NumberFormatException e) {
+			showError("vc.check.customer.invalid");
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java b/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java
index d22120c02aa..b7cfe308574 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java
+++ b/src/main/java/com/frentix/olat/vitero/ui/ViteroUserToGroupController.java
@@ -47,12 +47,11 @@ import org.olat.course.CourseFactory;
 import org.olat.course.ICourse;
 import org.olat.course.groupsandrights.CourseGroupManager;
 import org.olat.group.BusinessGroup;
-import org.olat.group.BusinessGroupManager;
-import org.olat.group.BusinessGroupManagerImpl;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryManager;
 
 import com.frentix.olat.vitero.manager.ViteroManager;
+import com.frentix.olat.vitero.manager.VmsNotAvailableException;
 import com.frentix.olat.vitero.model.GroupRole;
 import com.frentix.olat.vitero.model.ViteroBooking;
 
@@ -135,28 +134,40 @@ public class ViteroUserToGroupController extends BasicController {
 	}
 	
 	private void signIn(UserRequest ureq, Identity identity) {
-		ResourceMembers members = ((UserToGroupDataModel)tableCtlr.getTableDataModel()).getMembers();
-		boolean upgrade = members.getCoaches().contains(identity) || members.getOwners().contains(identity);
-		GroupRole role = upgrade ? GroupRole.teamleader : null;
-		if(viteroManager.addToRoom(booking, identity, role)) {
-			showInfo("signin.ok");
-		} else {
-			showInfo("signin.nok");
+		try {
+			ResourceMembers members = ((UserToGroupDataModel)tableCtlr.getTableDataModel()).getMembers();
+			boolean upgrade = members.getCoaches().contains(identity) || members.getOwners().contains(identity);
+			GroupRole role = upgrade ? GroupRole.teamleader : null;
+			if(viteroManager.addToRoom(booking, identity, role)) {
+				showInfo("signin.ok");
+			} else {
+				showInfo("signin.nok");
+			}
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
 	}
 	
 	private void signOut(UserRequest ureq, Identity identity) {
-		if(viteroManager.removeFromRoom(booking, identity)) {
-			showInfo("signout.ok");
-		} else {
-			showInfo("signout.nok");
+		try {
+			if(viteroManager.removeFromRoom(booking, identity)) {
+				showInfo("signout.ok");
+			} else {
+				showInfo("signout.nok");
+			}
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
 		}
 	}
 
 	private void loadModel() {
-		List<Identity> identitiesInGroup = viteroManager.getIdentitiesInBooking(booking);
-		ResourceMembers members = getIdentitiesInResource();
-		tableCtlr.setTableDataModel(new UserToGroupDataModel(members, identitiesInGroup));
+		try {
+			List<Identity> identitiesInGroup = viteroManager.getIdentitiesInBooking(booking);
+			ResourceMembers members = getIdentitiesInResource();
+			tableCtlr.setTableDataModel(new UserToGroupDataModel(members, identitiesInGroup));
+		} catch (VmsNotAvailableException e) {
+			showError(VmsNotAvailableException.I18N_KEY);
+		}
 	}
 	
 	private ResourceMembers getIdentitiesInResource() {
diff --git a/src/main/java/com/frentix/olat/vitero/ui/_i18n/LocalStrings_de.properties b/src/main/java/com/frentix/olat/vitero/ui/_i18n/LocalStrings_de.properties
index a64c3338d7d..65db69d62cc 100644
--- a/src/main/java/com/frentix/olat/vitero/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/com/frentix/olat/vitero/ui/_i18n/LocalStrings_de.properties
@@ -18,6 +18,8 @@ vc.booking.new=Neu Booking
 vc.bookings.intro=Termine f\u00fcr Meetings
 vc.booking.roomsOverview=Current rooms
 
+vc.vmsNotAvailable=Vitero Server ist nicht verfügbar
+vc.olatTimeZone=OLAT Time Zone
 
 vc.vitero.baseurl=URL
 vc.vitero.adminlogin=Login
diff --git a/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml b/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml
index 77364f757ff..a9284f97c8d 100644
--- a/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml
+++ b/src/main/java/de/bps/course/nodes/vc/_spring/vcContext.xml
@@ -73,7 +73,7 @@
 	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
 		<property name="triggers">
 			<list>
-				<!-- <ref local="adobeCleanupJob" /> -->
+				<!--  <ref local="adobeCleanupJob" /> -->
 			</list>
 		</property>
 	</bean>
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index b33286f894b..acf30dcdb13 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -595,5 +595,7 @@ vc.vitero.contextPath=vitero
 vc.vitero.adminlogin=admin
 vc.vitero.adminpassword=007
 vc.vitero.customerid=1
+vc.vitero.olatTimeZoneId=Africa/Ceuta
+vc.vitero.olatTimeZoneId.values=c.f. listing of Vitero
 
 
-- 
GitLab