diff --git a/src/main/java/org/olat/admin/sysinfo/UserSessionController.java b/src/main/java/org/olat/admin/sysinfo/UserSessionController.java
index b7a14a3702421254a9dbad9a4ebce1947d8617f5..d3746db85c71d268e8572a2b759b753a28e1b4a6 100644
--- a/src/main/java/org/olat/admin/sysinfo/UserSessionController.java
+++ b/src/main/java/org/olat/admin/sysinfo/UserSessionController.java
@@ -26,6 +26,7 @@
 package org.olat.admin.sysinfo;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 import org.olat.admin.sysinfo.model.UserSessionView;
@@ -112,7 +113,7 @@ public class UserSessionController extends BasicController implements Breadcrumb
 	 * Re-initialize this controller. Fetches sessions again.
 	 */
 	public void reset() {
-		List<UserSession> authUserSessions = new ArrayList<UserSession>(sessionManager.getAuthenticatedUserSessions());
+		Collection<UserSession> authUserSessions = sessionManager.getAuthenticatedUserSessions();
 		List<UserSessionView> authUserSessionViews = new ArrayList<UserSessionView>(authUserSessions.size());
 		for(UserSession authUserSession:authUserSessions) {
 			authUserSessionViews.add(new UserSessionView(authUserSession));
diff --git a/src/main/java/org/olat/admin/sysinfo/manager/SessionStatsManager.java b/src/main/java/org/olat/admin/sysinfo/manager/SessionStatsManager.java
index e6418b5fff007356aabf54f2a4d5096533b675b5..54ad0624e8c12cbd37f54d5b4a1fb5b6a70f7b3f 100644
--- a/src/main/java/org/olat/admin/sysinfo/manager/SessionStatsManager.java
+++ b/src/main/java/org/olat/admin/sysinfo/manager/SessionStatsManager.java
@@ -20,6 +20,7 @@
 package org.olat.admin.sysinfo.manager;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -99,7 +100,7 @@ public class SessionStatsManager implements Sampler {
 	public long getActiveSessions(int numOfSeconds) {
 		long diff = numOfSeconds * 1000;
 		
-		List<UserSession> authUserSessions = new ArrayList<UserSession>(sessionManager.getAuthenticatedUserSessions());
+		Collection<UserSession> authUserSessions = sessionManager.getAuthenticatedUserSessions();
 		long now = System.currentTimeMillis();
 		long counter = 0;
 		for (UserSession usess : authUserSessions) {
diff --git a/src/main/java/org/olat/core/logging/OLogImpl.java b/src/main/java/org/olat/core/logging/OLogImpl.java
index 0a2cd99dd63438388e149b16831d834a26c88a03..809c66f34642c748a8931567cc7212d31442fd96 100644
--- a/src/main/java/org/olat/core/logging/OLogImpl.java
+++ b/src/main/java/org/olat/core/logging/OLogImpl.java
@@ -25,6 +25,8 @@
 */ 
 package org.olat.core.logging;
 
+import org.apache.log4j.Logger;
+
 /**
  * Description:<br>
  * Log Impl class, for method details see Tracing.java in the same package
@@ -34,35 +36,38 @@ package org.olat.core.logging;
  * @author Felix Jost, http://www.goodsolutions.ch
  */
 public class OLogImpl implements OLog {
-	Class loggingClazz;
-	OLogImpl(Class clazz) {
-		this.loggingClazz = clazz;
+	private final Class<?> loggingClazz;
+	private final Logger logger;
+	
+	OLogImpl(Class<?> clazz) {
+		loggingClazz = clazz;
+		logger = Tracing.getLogger(clazz); 
 	}
 	
 	public boolean isDebug() {
-		return Tracing.isDebugEnabled(loggingClazz);
+		return logger.isDebugEnabled();
 	}
 	
 	public void error(String logMsg, Throwable cause) {
-		Tracing.logError(logMsg, cause, loggingClazz);
+		Tracing.logError(logMsg, cause, logger, loggingClazz);
 	}
 
 	public void error(String logMsg) {
-		Tracing.logError(logMsg, loggingClazz);
+		Tracing.logError(logMsg, null, logger, loggingClazz);
 	}
 
 	/**
 	 * See package.html for proper usage!
 	 */
 	public void warn(String logMsg, Throwable cause) {
-		Tracing.logWarn(logMsg, cause, loggingClazz);
+		Tracing.logWarn(logMsg, cause, logger, loggingClazz);
 	}
 
 	/**
  	 * See package.html for proper usage!
 	 */
 	public void warn(String logMsg) {
-		Tracing.logWarn(logMsg, loggingClazz);
+		Tracing.logWarn(logMsg, null, logger, loggingClazz);
 	}
 
 	/**
@@ -72,36 +77,36 @@ public class OLogImpl implements OLog {
 	 * 
 	 */
 	public void debug(String logMsg, String userObj) {
-		Tracing.logDebug(logMsg, userObj, loggingClazz);
+		Tracing.logDebug(logMsg, userObj, logger, loggingClazz);
 	}
 
 	/**
 	 * Add debug log entry
 	 */
 	public void debug(String logMsg) {
-		Tracing.logDebug(logMsg, loggingClazz);
+		Tracing.logDebug(logMsg, null, logger, loggingClazz);
 	}
 
 	public void info(String logMsg, String userObject) {
-		Tracing.logInfo(logMsg, userObject, loggingClazz);
+		Tracing.logInfo(logMsg, userObject, logger, loggingClazz);
 	}
 
 	public void info(String logMsg) {
-		Tracing.logInfo(logMsg, loggingClazz);	
+		Tracing.logInfo(logMsg, null, logger, loggingClazz);	
 	}
 
 	/**
 	 * Add audit log entry.
 	 */
 	public void audit(String logMsg) {
-		Tracing.logAudit(logMsg, loggingClazz);
+		Tracing.logAudit(logMsg, null, logger, loggingClazz);
 	}
 
 	/**
 	 * Add audit log entry with a user object. 
 	 */
 	public void audit(String logMsg, String userObj) {
-		Tracing.logAudit(logMsg, userObj, loggingClazz);
+		Tracing.logAudit(logMsg, userObj, logger, loggingClazz);
 	}
 
 }
diff --git a/src/main/java/org/olat/core/logging/Tracing.java b/src/main/java/org/olat/core/logging/Tracing.java
index fc208c707ba717f0eeaea64f1bbc7065d708fd0e..93b7f8c69f3f5f671d537d35c5d0995e52a15aa6 100644
--- a/src/main/java/org/olat/core/logging/Tracing.java
+++ b/src/main/java/org/olat/core/logging/Tracing.java
@@ -30,8 +30,8 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -106,7 +106,7 @@ public class Tracing {
 	private static long __debugRefNum__ = 0;
 	
 	// VM local cache to have one logger object per class
-	private static final Map<Class<?>, OLog> loggerLookupMap = new ConcurrentHashMap<Class<?>, OLog>();
+	private static final ConcurrentMap<Class<?>, OLog> loggerLookupMap = new ConcurrentHashMap<Class<?>, OLog>();
 
 	/**
 	 * per-thread singleton holding the actual HttpServletRequest which is the
@@ -135,16 +135,14 @@ public class Tracing {
 	public static OLog createLoggerFor(Class<?> loggingClass) {
 		// Share logger object to reduce memory footprint
 		OLog logger = loggerLookupMap.get(loggingClass);
-    if (logger == null) {
-      synchronized (loggerLookupMap) {   
-				logger = loggerLookupMap.get(loggingClass);
-				if (logger == null) {
-					logger = new OLogImpl(loggingClass);
-					loggerLookupMap.put(loggingClass, logger);
-				}
-      }
+		if (logger == null) {
+			OLog newLogger = new OLogImpl(loggingClass);
+			logger = loggerLookupMap.putIfAbsent(loggingClass, newLogger);
+			if(logger == null) {
+				logger = newLogger;
+			}
 		}
-    return logger;
+		return logger;
 	}
 	
 	
@@ -169,6 +167,12 @@ public class Tracing {
 		getLogger(callingClass).error(assembleThrowableMessage(ERROR, 'E',refNum, callingClass, logMsg, cause));
 		return refNum;
 	}
+	
+	public static long logError(String logMsg, Throwable cause, Logger logger, Class<?> callingClass) {
+		long refNum = getErrorRefNum();
+		logger.error(assembleThrowableMessage(ERROR, 'E',refNum, callingClass, logMsg, cause));
+		return refNum;
+	}
 
 	/**
 	 * @param callingClass
@@ -193,6 +197,12 @@ public class Tracing {
 		getLogger(callingClass).warn(assembleThrowableMessage(WARN, 'W', refNum, callingClass, logMsg, cause));
 		return refNum;
 	}
+	
+	protected static long logWarn(String logMsg, Throwable cause, Logger logger, Class<?> callingClass) {
+		long refNum = getWarnRefNum();
+		logger.warn(assembleThrowableMessage(WARN, 'W', refNum, callingClass, logMsg, cause));
+		return refNum;
+	}
 
 	/**
 	 * @param callingClass
@@ -222,6 +232,14 @@ public class Tracing {
 		}
 		return refNum;
 	}
+	
+	protected static long logDebug(String logMsg, String userObj, Logger logger, Class<?> callingClass) {
+		long refNum = getDebugRefNum();
+		if (logger.isDebugEnabled()) {
+			logger.debug(assembleMsg(DEBUG, 'D', refNum, callingClass, userObj, logMsg));
+		}
+		return refNum;
+	}
 
 	/**
 	 * Add debug log entry
@@ -246,6 +264,12 @@ public class Tracing {
 		getLogger(callingClass).info(assembleMsg(INFO, 'I', refNum, callingClass, userObject, logMsg));
 		return refNum;
 	}
+	
+	protected static long logInfo(String logMsg, String userObject, Logger logger, Class<?> callingClass) {
+		long refNum = getInfoRefNum();
+		logger.info(assembleMsg(INFO, 'I', refNum, callingClass, userObject, logMsg));
+		return refNum;
+	}
 
 	/**
 	 * @param callingClass
@@ -284,6 +308,12 @@ public class Tracing {
 		getLogger(callingClass).info(assembleMsg(AUDIT, 'A', refNum, callingClass, userObj, logMsg));
 		return refNum;
 	}
+	
+	protected static long logAudit(String logMsg, String userObj, Logger logger, Class<?> callingClass) {
+		long refNum = getAuditRefNum();
+		logger.info(assembleMsg(AUDIT, 'A', refNum, callingClass, userObj, logMsg));
+		return refNum;
+	}
 
 	/**
 	 * Method getStackTrace returns the first few (stacklen) lines of the
diff --git a/src/main/java/org/olat/core/util/session/UserSessionManager.java b/src/main/java/org/olat/core/util/session/UserSessionManager.java
index 85dd416bac9ebe8ab56cb877fb558632766804ab..fef0bd553d6d0d1215480a2c8eb97c95b8b57fc0 100644
--- a/src/main/java/org/olat/core/util/session/UserSessionManager.java
+++ b/src/main/java/org/olat/core/util/session/UserSessionManager.java
@@ -19,14 +19,13 @@
  */
 package org.olat.core.util.session;
 
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.annotation.PostConstruct;
@@ -76,10 +75,10 @@ public class UserSessionManager implements GenericEventListener {
 	public static final OLATResourceable ORES_USERSESSION = OresHelper.createOLATResourceableType(UserSession.class);
 	public static final String STORE_KEY_KILLED_EXISTING_SESSION = "killedExistingSession";
 
-  //clusterNOK cache ??
-	private static final Set<UserSession> authUserSessions = new HashSet<UserSession>(2500);
-	private static final Set<Long> userNameToIdentity = new HashSet<Long>(2500);
-	private static final Set<Long> authUsersNamesOtherNodes = new HashSet<Long>(2500);
+	//clusterNOK cache ??
+	private static final Set<UserSession> authUserSessions = ConcurrentHashMap.newKeySet();
+	private static final Set<Long> userNameToIdentity = ConcurrentHashMap.newKeySet();
+	private static final Set<Long> authUsersNamesOtherNodes = ConcurrentHashMap.newKeySet();
 
 	private static final AtomicInteger sessionCountWeb = new AtomicInteger();
 	private static final AtomicInteger sessionCountRest = new AtomicInteger();
@@ -107,14 +106,16 @@ public class UserSessionManager implements GenericEventListener {
 	 * @return associated user session
 	 */
 	public UserSession getUserSession(HttpSession session) {
-		UserSession us;
-		synchronized (session) {//o_clusterOK by:fj
-			us = (UserSession) session.getAttribute(USERSESSIONKEY);
-			if (us == null) {
-				us = new UserSession();
-				session.setAttribute(USERSESSIONKEY, us); // triggers the
-				// valueBoundEvent -> nothing
-				// more to do here
+		UserSession us = (UserSession) session.getAttribute(USERSESSIONKEY);
+		if(us == null) {
+			synchronized (session) {//o_clusterOK by:fj
+				us = (UserSession) session.getAttribute(USERSESSIONKEY);
+				if (us == null) {
+					us = new UserSession();
+					session.setAttribute(USERSESSIONKEY, us); // triggers the
+					// valueBoundEvent -> nothing
+					// more to do here
+				}
 			}
 		}
 		//set a possible changed session timeout interval
@@ -148,15 +149,13 @@ public class UserSessionManager implements GenericEventListener {
 			return null;
 		}
 
-		synchronized (session) {//o_clusterOK by:se
-			UserSession us = (UserSession) session.getAttribute(USERSESSIONKEY);
-			if(us != null && us.isAuthenticated()) {
-				session.setMaxInactiveInterval(sessionModule.getSessionTimeoutAuthenticated());
-			} else {
-				session.setMaxInactiveInterval(sessionModule.getSessionTimeout());
-			}
-			return us;
+		UserSession us = (UserSession) session.getAttribute(USERSESSIONKEY);
+		if(us != null && us.isAuthenticated()) {
+			session.setMaxInactiveInterval(sessionModule.getSessionTimeoutAuthenticated());
+		} else {
+			session.setMaxInactiveInterval(sessionModule.getSessionTimeout());
 		}
+		return us;
 	}
 
   /**
@@ -165,42 +164,27 @@ public class UserSessionManager implements GenericEventListener {
  *         on
  */
 	public boolean isSignedOnIdentity(Long identityKey) {
-		synchronized (authUserSessions) {  //o_clusterOK by:fj
-			return userNameToIdentity.contains(identityKey);
-		}
-	}
-	
-	public List<Long> getAuthenticatedIdentityKey() {
-		synchronized (authUserSessions) {  //o_clusterOK by:fj
-			return new ArrayList<Long>(userNameToIdentity);
-		}
+		return userNameToIdentity.contains(identityKey);
 	}
 	
 	/**
 	 * @return set of authenticated active user sessions
 	 */
 	public Set<UserSession> getAuthenticatedUserSessions() {
-		Set<UserSession> copy;
-		synchronized (authUserSessions) {  //o_clusterOK by:fj
-			copy = new HashSet<UserSession>(authUserSessions);
-		}
-		return copy;
+		return new HashSet<UserSession>(authUserSessions);
 	}
 	
 	public int getNumberOfAuthenticatedUserSessions() {
-		synchronized(authUserSessions) {
-			return authUserSessions.size();
-		}
+		return authUserSessions.size();
 	}
 	
 	/**
+	 * This method returns only the number of local sessions.
+	 * 
 	 * @return Returns the userSessionsCnt (Web, WebDAV, REST) from this VM
 	 */
 	public int getUserSessionsCnt() {
-	  //clusterNOK ?? return only number of locale sessions ?
-		synchronized(authUserSessions) {
-			return authUserSessions.size();
-		}
+		return authUserSessions.size();
 	}
 	
 	/**
@@ -211,10 +195,6 @@ public class UserSessionManager implements GenericEventListener {
 		return userSessionCache.size();
 	}
 	
-	public Collection<Long> getUsersOnline() {
-		return userSessionCache.getKeys();
-	}
-	
 	public boolean isOnline(Long identityKey) {
 		return userSessionCache.containsKey(identityKey);
 	}
@@ -246,96 +226,93 @@ public class UserSessionManager implements GenericEventListener {
 	/**
 	 * prior to calling this method, all instance vars must be set.
 	 */
-	public synchronized void signOn(UserSession usess) {
-		//   ^^^^^^^^^^^^ Added synchronized to be symmetric with sign off and to
-		//                fix a possible dead-lock see also OLAT-3390
-		
+	public void signOn(UserSession usess) {
 		boolean isDebug = log.isDebug();
-		if(isDebug) log.debug("signOn() START");
-		if (usess.isAuthenticated()) {
-			throw new AssertException("sign on: already signed on!");
-		}
-		
-		IdentityEnvironment identityEnvironment = usess.getIdentityEnvironment();
-		Identity identity = identityEnvironment.getIdentity();
-		if (identity == null) {
-			throw new AssertException("identity is null in identityEnvironment!");
-		}
-		SessionInfo sessionInfo = usess.getSessionInfo();
-		if (sessionInfo == null) {
-			throw new AssertException("sessionInfo was null for identity " + identity);
-		}
-		//String login = identity.getName();
-		usess.setAuthenticated(true);
-
-		if (sessionInfo.isWebDAV()) {
-			// load user prefs
-			usess.reloadPreferences();
-			synchronized (authUserSessions) {  //o_clusterOK by:se
+		// Added synchronized to be symmetric with sign off and to
+		// fix a possible dead-lock see also OLAT-3390
+		synchronized(usess) {
+			if(isDebug) log.debug("signOn() START");
+			if (usess.isAuthenticated()) {
+				throw new AssertException("sign on: already signed on!");
+			}
+			
+			IdentityEnvironment identityEnvironment = usess.getIdentityEnvironment();
+			Identity identity = identityEnvironment.getIdentity();
+			if (identity == null) {
+				throw new AssertException("identity is null in identityEnvironment!");
+			}
+			SessionInfo sessionInfo = usess.getSessionInfo();
+			if (sessionInfo == null) {
+				throw new AssertException("sessionInfo was null for identity " + identity);
+			}
+			usess.setAuthenticated(true);
+	
+			if (sessionInfo.isWebDAV()) {
+				// load user prefs
+				usess.reloadPreferences();
 				// we're only adding this webdav session to the authUserSessions - not to the userNameToIdentity.
 				// userNameToIdentity is only needed for IM which can't do anything with a webdav session
 				authUserSessions.add(usess);
-			}
-			log.audit("Logged on [via webdav]: " + sessionInfo.toString());
-		} else {
-		
-			if(isDebug) {
-				log.debug("signOn() authUsersNamesOtherNodes.contains "+identity.getName() + ": " + authUsersNamesOtherNodes.contains(identity.getKey()));
-			}
-		
-			UserSession invalidatedSession = null;
-			synchronized (authUserSessions) {  //o_clusterOK by:fj
-		    // check if already a session exist for this user
-		    if ( (userNameToIdentity.contains(identity.getKey()) || userSessionCache.containsKey(identity.getKey()) ) 
-		         && !sessionInfo.isWebDAV() && !sessionInfo.isREST() && !usess.getRoles().isGuestOnly()) {
-		        log.info("Loggin-process II: User has already a session => signOffAndClear existing session");
-		        
-		        invalidatedSession = getUserSessionForGui(identity.getKey());
-		        //remove session to be invalidated
-		        //SIDEEFFECT!! to signOffAndClear
-		        //if invalidatedSession is removed from authUserSessions
-		        //signOffAndClear does not remove the identity.getName().toLowerCase() from the userNameToIdentity
-		        //
-		        authUserSessions.remove(invalidatedSession);
-		    }
-		    authUserSessions.add(usess);
+				log.audit("Logged on [via webdav]: " + sessionInfo.toString());
+			} else {	
+				UserSession invalidatedSession = null;
+
+				if(isDebug) {
+					log.debug("signOn() authUsersNamesOtherNodes.contains " + identity.getName() + ": " + authUsersNamesOtherNodes.contains(identity.getKey()));
+				}
+					
+			    // check if already a session exist for this user
+			    if ( (userNameToIdentity.contains(identity.getKey()) || userSessionCache.containsKey(identity.getKey()) ) 
+			         && !sessionInfo.isWebDAV() && !sessionInfo.isREST() && !usess.getRoles().isGuestOnly()) {
+			        log.info("Loggin-process II: User has already a session => signOffAndClear existing session");
+			        
+			        invalidatedSession = getUserSessionForGui(identity.getKey());
+			        //remove session to be invalidated
+			        //SIDEEFFECT!! to signOffAndClear
+			        //if invalidatedSession is removed from authUserSessions
+			        //signOffAndClear does not remove the identity.getName().toLowerCase() from the userNameToIdentity
+			        //
+		        	authUserSessions.remove(invalidatedSession);
+		    	}
+		    	authUserSessions.add(usess);
 				// user can choose upercase letters in identity name, but this has no effect on the
 				// database queries, the login form or the IM account. IM works only with lowercase
 				// characters -> map stores values as such
 				if(isDebug) log.debug("signOn() adding to userNameToIdentity: "+identity.getName().toLowerCase());
 				userNameToIdentity.add(identity.getKey());
 				userSessionCache.put(identity.getKey(), new Integer(Settings.getNodeId()));
-			}
-		
-			//reload user prefs
-			usess.reloadPreferences();
-
-			log.audit("Logged on: " + sessionInfo.toString());
-			CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new SignOnOffEvent(identity, true), ORES_USERSESSION);
-
-			// THE FOLLOWING CHECK MUST BE PLACED HERE NOT TO PRODUCE A DEAD-LOCK WITH SIGNOFFANDCLEAR
-			// check if a session from any browser was invalidated (IE has a cookie set per Browserinstance!!)
-			if (invalidatedSession != null || authUsersNamesOtherNodes.contains(identity.getKey())) {
-				// put flag killed-existing-session into session-store to show info-message 'only one session for each user' on user-home screen
-				usess.putEntry(STORE_KEY_KILLED_EXISTING_SESSION, Boolean.TRUE);
-				if(isDebug) log.debug("signOn() removing from authUsersNamesOtherNodes: "+identity.getName());
-				authUsersNamesOtherNodes.remove(identity.getKey());
-				//OLAT-3381 & OLAT-3382
-				if(invalidatedSession != null) {
-					signOffAndClear(invalidatedSession);
+			
+			
+				//reload user prefs
+				usess.reloadPreferences();
+	
+				log.audit("Logged on: " + sessionInfo.toString());
+				CoordinatorManager.getInstance().getCoordinator().getEventBus().fireEventToListenersOf(new SignOnOffEvent(identity, true), ORES_USERSESSION);
+	
+				// THE FOLLOWING CHECK MUST BE PLACED HERE NOT TO PRODUCE A DEAD-LOCK WITH SIGNOFFANDCLEAR
+				// check if a session from any browser was invalidated (IE has a cookie set per Browserinstance!!)
+				if (invalidatedSession != null || authUsersNamesOtherNodes.contains(identity.getKey())) {
+					// put flag killed-existing-session into session-store to show info-message 'only one session for each user' on user-home screen
+					usess.putEntry(STORE_KEY_KILLED_EXISTING_SESSION, Boolean.TRUE);
+					if(isDebug) log.debug("signOn() removing from authUsersNamesOtherNodes: "+identity.getName());
+					authUsersNamesOtherNodes.remove(identity.getKey());
+					//OLAT-3381 & OLAT-3382
+					if(invalidatedSession != null) {
+						signOffAndClear(invalidatedSession);
+					}
 				}
+	
+				if(isDebug) log.debug("signOn() END");
+			}
+			
+			// update logged in users counters
+			if (sessionInfo.isREST()) {
+				sessionCountRest.incrementAndGet();
+			} else if (sessionInfo.isWebDAV()) {
+				sessionCountDav.incrementAndGet();
+			} else {
+				sessionCountWeb.incrementAndGet();
 			}
-
-			if(isDebug) log.debug("signOn() END");
-		}
-		
-		// update logged in users counters
-		if (sessionInfo.isREST()) {
-			sessionCountRest.incrementAndGet();
-		} else if (sessionInfo.isWebDAV()) {
-			sessionCountDav.incrementAndGet();
-		} else {
-			sessionCountWeb.incrementAndGet();
 		}
 	}
 	
@@ -385,7 +362,7 @@ public class UserSessionManager implements GenericEventListener {
 	 * node2 catches the sign on event and invalidates the user on node2 "silently", e.g.
 	 * without firing an event.
 	 */
-	public void signOffAndClearWithout(final UserSession usess) {
+	private void signOffAndClearWithout(final UserSession usess) {
 		boolean isDebug = log.isDebug();
 		if(isDebug) log.debug("signOffAndClearWithout() START");
 		
@@ -394,7 +371,6 @@ public class UserSessionManager implements GenericEventListener {
 		final Identity ident = identityEnvironment.getIdentity();
 		if (isDebug) log.debug("UserSession:::logging off: " + sessionInfo);
 
-		//fxdiff BAKS-7 Resume function
 		if(usess.isAuthenticated() && usess.getLastHistoryPoint() != null && !usess.getRoles().isGuestOnly()) {
 			historyManager.persistHistoryPoint(ident, usess.getLastHistoryPoint());
 		}
@@ -403,6 +379,7 @@ public class UserSessionManager implements GenericEventListener {
 		 * use not RunnableWithException, as exceptionHandlng is inside the run
 		 */
 		Runnable run = new Runnable() {
+			@Override
 			public void run() {
 				Object obj = null;
 				try {
@@ -449,20 +426,19 @@ public class UserSessionManager implements GenericEventListener {
 
 		ThreadLocalUserActivityLoggerInstaller.runWithUserActivityLogger(run, UserActivityLoggerImpl.newLoggerForValueUnbound(usess));
 
-		synchronized (authUserSessions) {  //o_clusterOK by:fj
-			if(authUserSessions.remove(usess)){
-				//remove only from identityEnvironment if found in sessions.
-				//see also SIDEEFFECT!! line in signOn(..)
-				Identity previousSignedOn = identityEnvironment.getIdentity();
-				if (previousSignedOn != null) {
-					if(isDebug) log.debug("signOffAndClearWithout() removing from userNameToIdentity: "+previousSignedOn.getName().toLowerCase());
-					userNameToIdentity.remove(previousSignedOn.getKey());
-					userSessionCache.remove(previousSignedOn.getKey());
-				}
-			} else if (isDebug) {
-				log.info("UserSession already removed! for ["+ident+"]");			
+		if(authUserSessions.remove(usess)) {
+			//remove only from identityEnvironment if found in sessions.
+			//see also SIDEEFFECT!! line in signOn(..)
+			Identity previousSignedOn = identityEnvironment.getIdentity();
+			if (previousSignedOn != null) {
+				if(isDebug) log.debug("signOffAndClearWithout() removing from userNameToIdentity: "+previousSignedOn.getName().toLowerCase());
+				userNameToIdentity.remove(previousSignedOn.getKey());
+				userSessionCache.remove(previousSignedOn.getKey());
 			}
+		} else if (isDebug) {
+			log.info("UserSession already removed! for ["+ident+"]");			
 		}
+			
 		// update logged in users counters
 		if (sessionInfo != null) {
 			if (sessionInfo.isREST()) {
@@ -535,9 +511,8 @@ public class UserSessionManager implements GenericEventListener {
 		int invalidateCounter = 0;
 		log.audit("All sessions were invalidated by an administrator");
 		//clusterNOK ?? invalidate only locale sessions ?
-		Set<UserSession> iterCopy = getAuthenticatedUserSessions();
-		for (Iterator<UserSession> iterator = iterCopy.iterator(); iterator.hasNext();) {
-			UserSession userSession = iterator.next();
+		Set<UserSession> userSessions = getAuthenticatedUserSessions();
+		for (UserSession userSession : userSessions) {
 			Roles userRoles = userSession != null ? userSession.getRoles() : null; 
 			if (userRoles != null && !userRoles.isOLATAdmin()) {
 				//do not logout administrators
@@ -566,6 +541,7 @@ public class UserSessionManager implements GenericEventListener {
 		// 1. Copy authUserSessions in sorted TreeMap
 		// This is the Comparator that will be used to sort the TreeSet:
 		Comparator<UserSession> sessionComparator = new Comparator<UserSession>() {
+			@Override
 			public int compare(UserSession o1, UserSession o2) {
 				Long long1 = new Long((o1).getSessionInfo().getLastClickTime());
 				Long long2 = new Long((o2).getSessionInfo().getLastClickTime());
@@ -595,8 +571,7 @@ public class UserSessionManager implements GenericEventListener {
 	 * @param sessionTimeoutInSec
 	 */
 	public void setGlobalSessionTimeout(int sessionTimeoutInSec) {
-		Collection<UserSession> sessionSnapShot = getAuthenticatedUserSessions();
-		for (UserSession session : sessionSnapShot) {
+		authUserSessions.forEach(session -> {
 			try{
 				SessionInfo sessionInfo = session.getSessionInfo();
 				if(sessionInfo != null && sessionInfo.getSession() != null) {
@@ -605,28 +580,29 @@ public class UserSessionManager implements GenericEventListener {
 			} catch(Throwable th){
 				log.error("error setting sesssionTimeout", th);
 			}
-		}
+		});
 	}
 	
 	/**
-	 * Lookup non-webdav, non-REST UserSession for username.
+	 * Lookup non-webdav, non-REST UserSession for identity key.
 	 * @param identityKey
 	 * @return user-session or null when no session was founded. 
 	 */
 	private UserSession getUserSessionForGui(Long identityKey) {
+		UserSession identitySession = null;
 		if(identityKey != null) {
 			//do not call from somewhere else then signOffAndClear!!
-			Collection<UserSession> authUserSessionsCopy = getAuthenticatedUserSessions();
-			for (UserSession userSession : authUserSessionsCopy) {		
+			identitySession = authUserSessions.stream().filter(userSession -> {
 				Identity identity = userSession.getIdentity();
 				if (identity != null && identityKey.equals(identity.getKey())
 						&& userSession.getSessionInfo() != null
 						&& !userSession.getSessionInfo().isWebDAV()
 						&& !userSession.getSessionInfo().isREST()) {
-					return userSession;
+					return true;
 				}
-			}
+				return false;
+			}).findFirst().get();
 		}
-		return null;
+		return identitySession;
 	}
 }
diff --git a/src/main/java/org/olat/course/assessment/AssessmentHelper.java b/src/main/java/org/olat/course/assessment/AssessmentHelper.java
index ddf4c264e5b4d9c9df8a60c05b3398af6364b63e..61cba544f3ad7fd3a1e1b414e39ff315f64cdf4c 100644
--- a/src/main/java/org/olat/course/assessment/AssessmentHelper.java
+++ b/src/main/java/org/olat/course/assessment/AssessmentHelper.java
@@ -437,8 +437,11 @@ public class AssessmentHelper {
 		// - it is of an assessable course node type
 		boolean hasDisplayableValuesConfigured = false;
 		boolean hasDisplayableUserValues = false;
-		if ((numOfChildren > 0 || courseNode instanceof AssessableCourseNode) && !(courseNode instanceof ProjectBrokerCourseNode) ) {
-			if (courseNode instanceof AssessableCourseNode) {
+		if (numOfChildren > 0 || courseNode instanceof AssessableCourseNode) {
+			if(courseNode instanceof ProjectBrokerCourseNode) {
+				//ProjectBroker : no assessment-tool in V1.0 , remove project broker completely form assessment-tool gui
+				assessmentNodeData.setSelectable(false);
+			} else  if (courseNode instanceof AssessableCourseNode) {
 				AssessableCourseNode assessableCourseNode = (AssessableCourseNode) courseNode;
 				AssessmentEvaluation scoreEvaluation = scoreAccounting.evalCourseNode(assessableCourseNode);
 				if(scoreEvaluation != null) {
diff --git a/src/main/java/org/olat/course/assessment/AssessmentMainController.java b/src/main/java/org/olat/course/assessment/AssessmentMainController.java
index a2467f376943521a784131bd745a39db7a1d68e9..4232fe35af10c6fe79d40c98cf241964c0b5c615 100644
--- a/src/main/java/org/olat/course/assessment/AssessmentMainController.java
+++ b/src/main/java/org/olat/course/assessment/AssessmentMainController.java
@@ -409,7 +409,6 @@ public class AssessmentMainController extends MainLayoutBasicController implemen
 				} else if (cmd.equals(CMD_USERFOCUS)) {
 					mode = MODE_USERFOCUS;
 					identitiesList = getAllAssessableIdentities();
-					//fxdiff FXOLAT-108: improve results table of tests
 					doUserChooseWithData(ureq, identitiesList, null, null);
 				} else if (cmd.equals(CMD_GROUPFOCUS)) {
 					mode = MODE_GROUPFOCUS;
@@ -1117,8 +1116,7 @@ public class AssessmentMainController extends MainLayoutBasicController implemen
 		}
 		
 		boolean hasDisplayableValuesConfigured = false;
-		if ( (childrenData.size() > 0 || courseNode instanceof AssessableCourseNode) && !(courseNode instanceof ProjectBrokerCourseNode) ) {
-			// TODO:cg 04.11.2010 ProjectBroker : no assessment-tool in V1.0 , remove projectbroker completely form assessment-tool gui			// Store node data in hash map. This hash map serves as data model for 
+		if (childrenData.size() > 0 || courseNode instanceof AssessableCourseNode) {
 			// the user assessment overview table. Leave user data empty since not used in
 			// this table. (use only node data)
 			AssessmentNodeData nodeData = new AssessmentNodeData(recursionLevel, courseNode);
@@ -1133,9 +1131,11 @@ public class AssessmentMainController extends MainLayoutBasicController implemen
 					nodeData.setOnyx(false);
 				}
 			}
-
 			
-			if (courseNode instanceof AssessableCourseNode) {
+			if(courseNode instanceof ProjectBrokerCourseNode) {
+				//ProjectBroker : no assessment-tool in V1.0 , remove project broker completely form assessment-tool gui
+				nodeData.setSelectable(false);
+			} else if (courseNode instanceof AssessableCourseNode) {
 				AssessableCourseNode assessableCourseNode = (AssessableCourseNode) courseNode;
 				if ( assessableCourseNode.hasDetails()
 					|| assessableCourseNode.hasAttemptsConfigured()
diff --git a/src/main/java/org/olat/course/nodes/CourseNodeFactory.java b/src/main/java/org/olat/course/nodes/CourseNodeFactory.java
index 4cd2375a1c012245331999139cb0e571f7636dcc..675156d733b7d8970d2941764a2315bbbfa7ebbb 100644
--- a/src/main/java/org/olat/course/nodes/CourseNodeFactory.java
+++ b/src/main/java/org/olat/course/nodes/CourseNodeFactory.java
@@ -35,6 +35,7 @@ import java.util.Map;
 
 import org.olat.NewControllerFactory;
 import org.olat.core.CoreSpringFactory;
+import org.olat.core.configuration.PreWarm;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.logging.OLog;
@@ -51,7 +52,7 @@ import org.olat.repository.handlers.RepositoryHandlerFactory;
  * @author Mike Stock
  * @author guido
  */
-public class CourseNodeFactory {
+public class CourseNodeFactory implements PreWarm {
 	
 	private static final OLog log = Tracing.createLoggerFor(CourseNodeFactory.class);
 
@@ -73,6 +74,12 @@ public class CourseNodeFactory {
 		return INSTANCE;
 	}
 
+	@Override
+	public void run() {
+		getAllCourseNodeConfigurations();
+	}
+
+
 	/**
 	 * @return the list of enabled aliases
 	 */
@@ -88,13 +95,18 @@ public class CourseNodeFactory {
 		return alias;
 	}
 
-	private synchronized Map<String,CourseNodeConfiguration> getAllCourseNodeConfigurations() {
+	private Map<String,CourseNodeConfiguration> getAllCourseNodeConfigurations() {
 		if(allCourseNodeConfigurations == null) {
-			allCourseNodeConfigurations = new HashMap<String, CourseNodeConfiguration>();
-			Map<String, CourseNodeConfiguration> courseNodeConfigurationMap = CoreSpringFactory.getBeansOfType(CourseNodeConfiguration.class);
-			Collection<CourseNodeConfiguration> courseNodeConfigurationValues = courseNodeConfigurationMap.values();
-			for (CourseNodeConfiguration courseNodeConfiguration : courseNodeConfigurationValues) {
-				allCourseNodeConfigurations.put(courseNodeConfiguration.getAlias(), courseNodeConfiguration);
+			synchronized(INSTANCE) {
+				if(allCourseNodeConfigurations == null) {
+					Map<String, CourseNodeConfiguration> configurationMap = new HashMap<>();
+					Map<String, CourseNodeConfiguration> courseNodeConfigurationMap = CoreSpringFactory.getBeansOfType(CourseNodeConfiguration.class);
+					Collection<CourseNodeConfiguration> courseNodeConfigurationValues = courseNodeConfigurationMap.values();
+					for (CourseNodeConfiguration courseNodeConfiguration : courseNodeConfigurationValues) {
+						configurationMap.put(courseNodeConfiguration.getAlias(), courseNodeConfiguration);
+					}
+					allCourseNodeConfigurations = Collections.unmodifiableMap(configurationMap);
+				}
 			}
 		}
 		return allCourseNodeConfigurations;
diff --git a/src/main/java/org/olat/course/nodes/feed/FeedNodeSecurityCallback.java b/src/main/java/org/olat/course/nodes/feed/FeedNodeSecurityCallback.java
index 7f8fbc9cbee4df1fe2f0120e6778c82ac4482092..f064daf1ec71d0d46271553e44e8fe216b92f236 100644
--- a/src/main/java/org/olat/course/nodes/feed/FeedNodeSecurityCallback.java
+++ b/src/main/java/org/olat/course/nodes/feed/FeedNodeSecurityCallback.java
@@ -48,6 +48,7 @@ public class FeedNodeSecurityCallback implements FeedSecurityCallback {
 	/**
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayEditMetadata()
 	 */
+	@Override
 	public boolean mayEditMetadata() {
 		if (isGuestOnly) return false;
 		return ne.isCapabilityAccessible("moderator") || isOlatAdmin;
@@ -56,6 +57,7 @@ public class FeedNodeSecurityCallback implements FeedSecurityCallback {
 	/**
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayCreateItems()
 	 */
+	@Override
 	public boolean mayCreateItems() {
 		if (isGuestOnly) return false;
 		return ne.isCapabilityAccessible("poster") || ne.isCapabilityAccessible("moderator") || isOlatAdmin;
@@ -64,6 +66,7 @@ public class FeedNodeSecurityCallback implements FeedSecurityCallback {
 	/**
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayDeleteItems()
 	 */
+	@Override
 	public boolean mayDeleteItems() {
 		if (isGuestOnly) return false;
 		return ne.isCapabilityAccessible("moderator") || isOlatAdmin;
@@ -72,6 +75,7 @@ public class FeedNodeSecurityCallback implements FeedSecurityCallback {
 	/**
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayEditItems()
 	 */
+	@Override
 	public boolean mayEditItems() {
 		if (isGuestOnly) return false;
 		return ne.isCapabilityAccessible("moderator") || isOlatAdmin;
@@ -81,7 +85,6 @@ public class FeedNodeSecurityCallback implements FeedSecurityCallback {
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayViewAllDrafts()
 	 */
 	@Override
-	//fxdiff BAKS-18
 	public boolean mayViewAllDrafts() {
 		return isOwner || isOlatAdmin;
 	}
diff --git a/src/main/java/org/olat/course/nodes/projectbroker/ProjectEditDetailsFormController.java b/src/main/java/org/olat/course/nodes/projectbroker/ProjectEditDetailsFormController.java
index 80afc9276d1dcea021418ffd6ca1b6792aca98fb..7aa0b6976b6dc05aed387aa2ed0fc55bc1e4fb78 100644
--- a/src/main/java/org/olat/course/nodes/projectbroker/ProjectEditDetailsFormController.java
+++ b/src/main/java/org/olat/course/nodes/projectbroker/ProjectEditDetailsFormController.java
@@ -34,7 +34,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.StringTokenizer;
 
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
@@ -56,6 +55,7 @@ import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.id.Identity;
 import org.olat.core.id.UserConstants;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.vfs.LocalFileImpl;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.course.nodes.CourseNode;
@@ -68,6 +68,7 @@ import org.olat.course.nodes.projectbroker.service.ProjectBrokerModuleConfigurat
 import org.olat.course.nodes.projectbroker.service.ProjectGroupManager;
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.resource.OLATResource;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -86,7 +87,7 @@ public class ProjectEditDetailsFormController extends FormBasicController {
 	private RichTextElement projectDescription;
 	private IntegerElement maxMembers;
 	private StaticTextElement projectState;
-	FormLayoutContainer stateLayout;
+	private FormLayoutContainer stateLayout;
 	private FileElement attachmentFileName;
 
 	private TextElement projectLeaders;
@@ -111,9 +112,12 @@ public class ProjectEditDetailsFormController extends FormBasicController {
 	private final static String[] values = new String[] { "" };
 	private static final int MAX_MEMBERS_DEFAULT = 1;
 
-	private final ProjectBrokerMailer projectBrokerMailer;
-	private final ProjectGroupManager projectGroupManager;
-	private final ProjectBrokerManager projectBrokerManager;
+	@Autowired
+	private ProjectBrokerMailer projectBrokerMailer;
+	@Autowired
+	private ProjectGroupManager projectGroupManager;
+	@Autowired
+	private ProjectBrokerManager projectBrokerManager;
 
 	/**
 	 * Modules selection form.
@@ -127,12 +131,9 @@ public class ProjectEditDetailsFormController extends FormBasicController {
 		this.courseNode = courseNode;
 		this.projectBrokerModuleConfiguration = projectBrokerModuleConfiguration;
 		this.enableCancel = enableCancel;
-		projectBrokerMailer = CoreSpringFactory.getImpl(ProjectBrokerMailer.class);
-		projectGroupManager = CoreSpringFactory.getImpl(ProjectGroupManager.class);
-		projectBrokerManager = CoreSpringFactory.getImpl(ProjectBrokerManager.class);
-		customfieldElementList = new ArrayList<FormItem>();
-		eventStartElementList = new HashMap<Project.EventType, DateChooser>();
-		eventEndElementList = new HashMap<Project.EventType, DateChooser>();
+		customfieldElementList = new ArrayList<>();
+		eventStartElementList = new HashMap<>();
+		eventEndElementList = new HashMap<>();
 		initForm(ureq);
 	}
 
@@ -343,12 +344,13 @@ public class ProjectEditDetailsFormController extends FormBasicController {
 			projectGroupManager.setProjectGroupMaxMembers(getIdentity(), project.getProjectGroup(), maxMembers.getIntValue());
 			projectChanged = true;
 		}			
-		if (attachmentFileName.getUploadFileName() != null && !attachmentFileName.getUploadFileName().equals("")) {
+		if (StringHelper.containsNonWhitespace(attachmentFileName.getUploadFileName())) {
 			// First call uploadFiles than setAttachedFileName because uploadFiles needs old attachment name 
 			uploadFiles(attachmentFileName);
 			project.setAttachedFileName(attachmentFileName.getUploadFileName());
 			projectChanged = true;
-		} else if (project.getAttachmentFileName() != null && !project.getAttachmentFileName().equals("")) {
+		} else if (StringHelper.containsNonWhitespace(project.getAttachmentFileName())
+				&& attachmentFileName.getInitialFile() == null) {
 			// Attachment file has been removed
 			project.setAttachedFileName("");
 			projectChanged = true;
@@ -396,7 +398,7 @@ public class ProjectEditDetailsFormController extends FormBasicController {
 				projectBrokerManager.updateProject(project);
 				projectBrokerMailer.sendProjectChangedEmailToParticipants(ureq.getIdentity(), project, this.getTranslator());
 			} else {
-				this.showInfo("info.project.nolonger.exist", project.getTitle());
+				showInfo("info.project.nolonger.exist", project.getTitle());
 			}
 		}
 		fireEvent(ureq, Event.DONE_EVENT);
diff --git a/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectDAO.java b/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectDAO.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc8e9377d47226afb2b37a70ec14d2fb6ad10c0b
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectDAO.java
@@ -0,0 +1,66 @@
+/**
+ * <a href="http://www.openolat.org">
+ * OpenOLAT - Online Learning and Training</a><br>
+ * <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 the
+ * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
+ * <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>
+ * Initial code contributed and copyrighted by<br>
+ * frentix GmbH, http://www.frentix.com
+ * <p>
+ */
+package org.olat.course.nodes.projectbroker.service;
+
+import java.util.List;
+
+import org.olat.core.commons.persistence.DB;
+import org.olat.course.nodes.projectbroker.datamodel.Project;
+import org.olat.course.nodes.projectbroker.datamodel.ProjectImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Project queries must migrate here.
+ * 
+ * 
+ * Initial date: 01.02.2016<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class ProjectDAO {
+	@Autowired
+	private DB dbInstance;
+	
+	/**
+	 * The method load the project or return null if not found. The query fetch
+	 * all dependencies but the custom fields.
+	 * 
+	 * @param projectKey
+	 * @return The project
+	 */
+	public Project loadProject(Long projectKey) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select project from ").append(ProjectImpl.class.getName()).append(" as project ")
+		  .append(" left join fetch project.projectGroup pGroup")
+		  .append(" left join fetch pGroup.baseGroup bGroup")
+		  .append(" left join fetch project.candidateGroup cGroup")
+		  .append(" left join fetch project.projectBroker pBroker")
+		  .append(" where project.key=:projectKey");
+		
+		List<Project> projects = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Project.class)
+				.setParameter("projectKey", projectKey)
+				.getResultList();
+		return projects == null || projects.isEmpty() ? null : projects.get(0);
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectGroupManagerImpl.java b/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectGroupManagerImpl.java
index d0710faafc39a6405ac29de56a5e352ab1700aca..7982fe3c8f4675b24f4aeed8757e429b99e04b63 100644
--- a/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectGroupManagerImpl.java
+++ b/src/main/java/org/olat/course/nodes/projectbroker/service/ProjectGroupManagerImpl.java
@@ -68,6 +68,8 @@ public class ProjectGroupManagerImpl extends BasicManager implements ProjectGrou
 	@Autowired
 	private DB dbInstance;
 	@Autowired
+	private ProjectDAO projectDao;
+	@Autowired
 	private BaseSecurity securityManager;
 	@Autowired
 	private ProjectBrokerManager projectBrokerManager;
@@ -260,7 +262,7 @@ public class ProjectGroupManagerImpl extends BasicManager implements ProjectGrou
 
 	@Override
 	public BusinessGroupAddResponse acceptCandidates(final List<Identity> identities, final Project project, final Identity actionIdentity, final boolean autoSignOut, final boolean isAcceptSelectionManually) {
-		final Project reloadedProject = (Project) dbInstance.loadObject(project, true);
+		final Project reloadedProject = projectDao.loadProject(project.getKey());
 		final BusinessGroupAddResponse response = new BusinessGroupAddResponse();
 		BusinessGroupAddResponse state = businessGroupService.addParticipants(actionIdentity, null, identities, reloadedProject.getProjectGroup(), null);
 		response.getAddedIdentities().addAll(state.getAddedIdentities());
diff --git a/src/main/java/org/olat/ims/qti/questionimport/CSVToQuestionConverter.java b/src/main/java/org/olat/ims/qti/questionimport/CSVToQuestionConverter.java
index 5fc846efd173e23c85af8f13718872487244a1fb..c5cc4fbb04c8d7bbad94ce63b0e0cf3097b71fc1 100644
--- a/src/main/java/org/olat/ims/qti/questionimport/CSVToQuestionConverter.java
+++ b/src/main/java/org/olat/ims/qti/questionimport/CSVToQuestionConverter.java
@@ -372,8 +372,7 @@ public class CSVToQuestionConverter {
 	private void processPoints(String[] parts) {
 		if(currentItem == null) return;
 		
-		String pointsStr = parts[1];
-		float points = Float.parseFloat(pointsStr);
+		float points = parseFloat(parts[1], 1.0f);
 
 		Question question = currentItem.getItem().getQuestion();
 		int type = question.getType();
@@ -402,7 +401,7 @@ public class CSVToQuestionConverter {
 			Question question = currentItem.getItem().getQuestion();
 			int type = question.getType();
 			if (type == Question.TYPE_MC || type == Question.TYPE_SC) {
-				float point = Float.parseFloat(parts[0]);
+				float point = parseFloat(parts[0], 1.0f);
 				String content = parts[1];
 
 				ChoiceQuestion choice = (ChoiceQuestion)question;
@@ -424,7 +423,7 @@ public class CSVToQuestionConverter {
 					response.setContent(mat);
 					fib.getResponses().add(response);
 				} else {
-					float point = Float.parseFloat(parts[0]);
+					float point = parseFloat(parts[0], 1.0f);
 					String correctBlank = parts[1];
 
 					FIBResponse response = new FIBResponse();
@@ -451,6 +450,18 @@ public class CSVToQuestionConverter {
 		}
 	}
 	
+	private float parseFloat(String value, float defaultValue) {
+		float floatValue = defaultValue;
+		
+		if(value != null) {
+			if(value.indexOf(",") >= 0) {
+				value = value.replace(",", ".");
+			}
+			floatValue = Float.parseFloat(value);
+		}
+		return floatValue;
+	}
+	
 	private Material createMaterialWithText(String text) {
 		Material material = new Material();
 		material.add(createMattext(text));
diff --git a/src/main/java/org/olat/modules/dialog/DialogElementsController.java b/src/main/java/org/olat/modules/dialog/DialogElementsController.java
index 98e9d039fd32448ccf50e30de739aa0a163cd27d..098a06eceb4588312195f5d4e0e7fb4e311f6a4c 100644
--- a/src/main/java/org/olat/modules/dialog/DialogElementsController.java
+++ b/src/main/java/org/olat/modules/dialog/DialogElementsController.java
@@ -222,7 +222,7 @@ public class DialogElementsController extends BasicController {
 			TableEvent te = (TableEvent) event;
 			String command = te.getActionId();
 			int row = te.getRowId();
-			entry = tableModel.getEntryAt(row);
+			entry = tableModel.getEntryAt(tableCtr.getSortedRow(row));
 			if (command.equals(ACTION_START_FORUM)) {
 				selectedElement = dialogElmsMgr.findDialogElement(coursePropMgr, courseNode, entry.getForumKey());
 				if(selectedElement == null){
diff --git a/src/main/java/org/olat/modules/webFeed/FeedPreviewSecurityCallback.java b/src/main/java/org/olat/modules/webFeed/FeedPreviewSecurityCallback.java
index d70092b0eab42eb6acf428fc14b28f116e13fd14..088c2d14e7b7a381893331ccf7e069b8199c1c2c 100644
--- a/src/main/java/org/olat/modules/webFeed/FeedPreviewSecurityCallback.java
+++ b/src/main/java/org/olat/modules/webFeed/FeedPreviewSecurityCallback.java
@@ -60,7 +60,6 @@ public class FeedPreviewSecurityCallback implements FeedSecurityCallback {
 	/**
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayViewAllDrafts()
 	 */
-	//fxdiff BAKS-18
 	@Override
 	public boolean mayViewAllDrafts() {
 		return false;
diff --git a/src/main/java/org/olat/modules/webFeed/FeedResourceSecurityCallback.java b/src/main/java/org/olat/modules/webFeed/FeedResourceSecurityCallback.java
index 4e19ba8999322c2dd3bed6f5070018c0b34e2444..22e935f953bae97546cce76bb28d06b8663b7a02 100644
--- a/src/main/java/org/olat/modules/webFeed/FeedResourceSecurityCallback.java
+++ b/src/main/java/org/olat/modules/webFeed/FeedResourceSecurityCallback.java
@@ -67,7 +67,6 @@ public class FeedResourceSecurityCallback implements FeedSecurityCallback {
 	/**
 	 * @see org.olat.modules.webFeed.FeedSecurityCallback#mayViewAllDrafts()
 	 */
-	//fxdiff BAKS-18
 	@Override
 	public boolean mayViewAllDrafts() {
 		return isAdmin || isOwner;
diff --git a/src/main/java/org/olat/modules/webFeed/RSSFeed.java b/src/main/java/org/olat/modules/webFeed/RSSFeed.java
index 9b62d55e0e2ed22a221836fbeda4bb45bb7506f0..51f1a38ccd6e8c241f35ff6fff91f58cc1b161a0 100644
--- a/src/main/java/org/olat/modules/webFeed/RSSFeed.java
+++ b/src/main/java/org/olat/modules/webFeed/RSSFeed.java
@@ -49,6 +49,8 @@ import com.sun.syndication.feed.synd.SyndImageImpl;
  */
 public class RSSFeed extends SyndFeedImpl {
 
+	private static final long serialVersionUID = 4010701266801565756L;
+
 	/**
 	 * Constructor. The identityKey is needed to generate personal URLs for the
 	 * corresponding user.
diff --git a/src/main/java/org/olat/modules/webFeed/ui/ItemController.java b/src/main/java/org/olat/modules/webFeed/ui/ItemController.java
index 38b2c1baa56cc98d42d96e032fa9b7d599ecde44..3578b30f235ccdf12be800adc0a1f8cda70271ab 100644
--- a/src/main/java/org/olat/modules/webFeed/ui/ItemController.java
+++ b/src/main/java/org/olat/modules/webFeed/ui/ItemController.java
@@ -73,9 +73,15 @@ public class ItemController extends BasicController implements Activateable2 {
 		vcItem.contextPut("helper", helper);
 		vcItem.contextPut("callback", callback);
 		if (feed.isInternal()) {
-			if (editButton != null) vcItem.put("editButton", editButton);
-			if (deleteButton != null) vcItem.put("deleteButton", deleteButton);
-			if (artefactLink != null) vcItem.put("artefactLink", artefactLink.getInitialComponent());
+			if (editButton != null) {
+				vcItem.put("editButton", editButton);
+			}
+			if (deleteButton != null) {
+				vcItem.put("deleteButton", deleteButton);
+			}
+			if (artefactLink != null) {
+				vcItem.put("artefactLink", artefactLink.getInitialComponent());
+			}
 		}
 		backLink = LinkFactory.createLinkBack(vcItem, this);
 		// Add date component
@@ -91,7 +97,7 @@ public class ItemController extends BasicController implements Activateable2 {
 			vcItem.put("commentsAndRating", commentsCtr.getInitialComponent());				
 		}
 		//
-		this.putInitialPanel(vcItem);
+		putInitialPanel(vcItem);
 		// do logging
 		ThreadLocalUserActivityLogger.log(FeedLoggingAction.FEED_ITEM_READ, getClass(), LoggingResourceable.wrap(item));
 	}
@@ -99,6 +105,7 @@ public class ItemController extends BasicController implements Activateable2 {
 	/**
 	 * @see org.olat.core.gui.control.DefaultController#doDispose()
 	 */
+	@Override
 	protected void doDispose() {
 	// nothing to do
 	}
@@ -127,5 +134,4 @@ public class ItemController extends BasicController implements Activateable2 {
 			}
 		}		
 	}
-
-}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java b/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java
index c25701fb2571455ed9b2133c805bd8ad7b07bf82..7ce99ded690ebf0e0cddcb3f691185a6a9a2e417 100644
--- a/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java
+++ b/src/main/java/org/olat/modules/webFeed/ui/ItemsController.java
@@ -169,9 +169,9 @@ public class ItemsController extends BasicController implements Activateable2 {
 		startpageLink = LinkFactory.createLink("feed.startpage", vcItems, this);
 		startpageLink.setCustomEnabledLinkCSS("o_first_page");
 
-		if (callback.mayEditItems() || callback.mayCreateItems()) {
-			createEditButtons(ureq, feed);
-		}
+		
+		createEditButtons(ureq, feed);
+	
 		// Add item details page link
 		createItemLinks(feed);
 		// Add item user comments link and rating
@@ -218,9 +218,9 @@ public class ItemsController extends BasicController implements Activateable2 {
 	private void createEditButtons(UserRequest ureq, Feed feed) {
 		List<Item> items = feed.getCopiedListOfItems();
 
-		editButtons = new ArrayList<Link>();
-		deleteButtons = new ArrayList<Link>();
-		artefactLinks = new HashMap<Item,Controller>();
+		editButtons = new ArrayList<>();
+		deleteButtons = new ArrayList<>();
+		artefactLinks = new HashMap<>();
 		if (feed.isInternal()) {
 			addItemButton = LinkFactory.createButtonSmall("feed.add.item", vcItems, this);
 			addItemButton.setElementCssClass("o_sel_feed_item_new");
@@ -332,20 +332,32 @@ public class ItemsController extends BasicController implements Activateable2 {
 	 * the items velocity container's context.
 	 */
 	public void makeInternalAndExternalButtons() {
-		makeInternalButton = LinkFactory.createButton("feed.make.internal", vcItems, this);
-		makeExternalButton = LinkFactory.createButton("feed.make.external", vcItems, this);
+		if (callback.mayEditItems() || callback.mayCreateItems()) {
+			makeInternalButton = LinkFactory.createButton("feed.make.internal", vcItems, this);
+			makeExternalButton = LinkFactory.createButton("feed.make.external", vcItems, this);
+		}
 	}
 
 	/**
 	 * @param item
 	 */
 	private void createButtonsForItem(UserRequest ureq, Item item) {
+		boolean author = getIdentity().getKey().equals(item.getAuthorKey());
+		boolean edit = callback.mayEditItems() || author;
+		boolean delete = callback.mayDeleteItems() || author;
+
 		String guid = item.getGuid();
-		Link editButton = LinkFactory.createCustomLink("feed.edit.item." + guid, "feed.edit.item." + guid, "feed.edit.item",
-				Link.BUTTON_SMALL, vcItems, this);
+		String editId = "feed.edit.item.".concat(guid);
+		Link editButton = LinkFactory.createCustomLink(editId, editId, "feed.edit.item", Link.BUTTON_SMALL, vcItems, this);
 		editButton.setElementCssClass("o_sel_feed_item_edit");
-		Link deleteButton = LinkFactory.createCustomLink("delete." + guid, "delete." + guid, "delete", Link.BUTTON_SMALL, vcItems, this);
+		editButton.setEnabled(edit);
+		editButton.setVisible(edit);
+		
+		String deleteId = "delete.".concat(guid);
+		Link deleteButton = LinkFactory.createCustomLink(deleteId, deleteId, "delete", Link.BUTTON_SMALL, vcItems, this);
 		deleteButton.setElementCssClass("o_sel_feed_item_delete");
+		deleteButton.setEnabled(delete);
+		deleteButton.setVisible(delete);
 
 		if(feedResource.isInternal() && getIdentity().getKey() != null && getIdentity().getKey().equals(item.getAuthorKey())) {
 			String businessPath = BusinessControlFactory.getInstance().getAsString(getWindowControl().getBusinessControl());
@@ -353,7 +365,7 @@ public class ItemsController extends BasicController implements Activateable2 {
 			Controller artefactCtrl = EPUIFactory.createArtefactCollectWizzardController(ureq, getWindowControl(), feedResource, businessPath);
 			if(artefactCtrl != null) {
 				artefactLinks.put(item, artefactCtrl);
-				vcItems.put("feed.artefact.item." + guid, artefactCtrl.getInitialComponent());
+				vcItems.put("feed.artefact.item.".concat(guid), artefactCtrl.getInitialComponent());
 			}
 		}
 		
@@ -477,25 +489,19 @@ public class ItemsController extends BasicController implements Activateable2 {
 
 		} else if (source == olderItemsLink) {
 			helper.olderItems();
-			if (callback.mayEditItems() || callback.mayCreateItems()) {
-				createEditButtons(ureq, feed);
-			}
+			createEditButtons(ureq, feed);
 			createCommentsAndRatingsLinks(ureq, feed);
 			vcItems.setDirty(true);
 
 		} else if (source == newerItemsLink) {
 			helper.newerItems();
-			if (callback.mayEditItems() || callback.mayCreateItems()) {
-				createEditButtons(ureq, feed);
-			}
+			createEditButtons(ureq, feed);
 			createCommentsAndRatingsLinks(ureq, feed);
 			vcItems.setDirty(true);
 
 		} else if (source == startpageLink) {
 			helper.startpage();
-			if (callback.mayEditItems() || callback.mayCreateItems()) {
-				createEditButtons(ureq, feed);
-			}
+			createEditButtons(ureq, feed);
 			createCommentsAndRatingsLinks(ureq, feed);
 			vcItems.setDirty(true);
 
diff --git a/src/main/java/org/olat/modules/webFeed/ui/blog/_content/post.html b/src/main/java/org/olat/modules/webFeed/ui/blog/_content/post.html
index 95e565a16bd9fabfbd493e6fbd9077ba5e880a8e..8fcaa01173e5804d28111577d0fd4d6b20b492d6 100644
--- a/src/main/java/org/olat/modules/webFeed/ui/blog/_content/post.html
+++ b/src/main/java/org/olat/modules/webFeed/ui/blog/_content/post.html
@@ -35,18 +35,16 @@
 			#end
 		</div>
 	
-		#if (( $callback.mayEditItems() || ($callback.mayCreateItems() && $item.isDraft())) && $feed.isInternal())
-		#if ($r.available("editButton"))
+		#if(($r.available("editButton") && $r.visible("editButton")) || ($r.available("deleteButton") && $r.visible("deleteButton")))
 		<div class="o_button_group">
-			## special case: this item has been added by another user and thus we 
-			## don't yet have links for this item. But we can still display the content
-			$r.render("editButton")
-			#if ($callback.mayDeleteItems() || ($callback.mayCreateItems() && $item.isDraft()))
+			#if ($r.available("editButton") && $r.visible("editButton"))
+				$r.render("editButton")
+			#end
+			#if ($r.available("deleteButton") && $r.visible("deleteButton"))
 				$r.render("deleteButton")
 			#end
 		</div>
-		#end
-		#end			
+		#end		
 	</div>
 	
 	<div class="o_block_footer">
diff --git a/src/main/java/org/olat/modules/webFeed/ui/blog/_content/posts.html b/src/main/java/org/olat/modules/webFeed/ui/blog/_content/posts.html
index c3972bae7977313eaa5993646e5c8c35fc2b52cb..d52aa4e5bbf5106d90b11e71d5027cdd31a9bb7d 100644
--- a/src/main/java/org/olat/modules/webFeed/ui/blog/_content/posts.html
+++ b/src/main/java/org/olat/modules/webFeed/ui/blog/_content/posts.html
@@ -79,15 +79,13 @@
 				</div>
 			</div>
 				
-			#if (( $callback.mayEditItems() || ($callback.mayCreateItems() && $post.isDraft())) && $feed.isInternal())
+			#if($feed.isInternal())
 			<div class="o_button_group">
-				#if ($r.available("feed.edit.item.$post.getGuid()"))
-					## special case: this item has been added by another user and thus we 
-					## don't yet have links for this item. But we can still display the content
+				#if ($r.available("feed.edit.item.$post.getGuid()") && $r.visible("feed.edit.item.$post.getGuid()"))
 					$r.render("feed.edit.item.$post.getGuid()")
-					#if ($callback.mayDeleteItems() || ($callback.mayCreateItems() && $post.isDraft()))
-						$r.render("delete.$post.getGuid()")
-					#end
+				#end
+				#if ($r.available("delete.$post.getGuid()") && $r.visible("delete.$post.getGuid()"))
+					$r.render("delete.$post.getGuid()")
 				#end
 			</div>
 			#end
diff --git a/src/main/java/org/olat/modules/wiki/WikiMainController.java b/src/main/java/org/olat/modules/wiki/WikiMainController.java
index f7ff86a931290f198d4e15ccc0cdc0e5cf282839..4ac6f0846142640e225054b50dae30d5731bf8e8 100644
--- a/src/main/java/org/olat/modules/wiki/WikiMainController.java
+++ b/src/main/java/org/olat/modules/wiki/WikiMainController.java
@@ -1172,7 +1172,7 @@ public class WikiMainController extends BasicController implements CloneableCont
 	}
 	
 	private void clearPortfolioLink(){
-		content.put("portfolio-link", new Panel("empty"));
+		navigationContent.put("portfolio-link", new Panel("empty"));
 	}
 	
 	private Wiki getWiki(){
diff --git a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java
index 85d1d0cee066ed9774691f03584e75ed59912d6e..2db789b8f2d47a58bc35ea8661a31a1a7099407e 100644
--- a/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java
+++ b/src/main/java/org/olat/modules/wiki/gui/components/wikiToHtml/WikiMarkupRenderer.java
@@ -93,7 +93,7 @@ public class WikiMarkupRenderer extends DefaultComponentRenderer {
 			uri = URLDecoder.decode(uri, "utf-8");
 			input.setVirtualWiki(uri.substring(1, uri.length()-1));
 			if (iframePostEnabled) {
-				String targetUrl = " onclick='o_XHREvent(jQuery(this).attr(\"href\"),false,true); return false;'";
+				String targetUrl = " onclick=\"o_XHREvent(jQuery(this).attr('href'),false,true); return false;\"";
 				input.setURLTarget(targetUrl);
 			}
 			sb.append("<div style=\"min-height:"+ wikiComp.getMinHeight() +"px\" id=\"");
diff --git a/src/main/java/org/olat/portfolio/ui/structel/edit/EPCollectRestrictionResultController.java b/src/main/java/org/olat/portfolio/ui/structel/edit/EPCollectRestrictionResultController.java
index 927989691261c0a53f39a0aac44a8adaa9593321..9c0321fb59baf27ef2a14af1ff196dec653a4686 100644
--- a/src/main/java/org/olat/portfolio/ui/structel/edit/EPCollectRestrictionResultController.java
+++ b/src/main/java/org/olat/portfolio/ui/structel/edit/EPCollectRestrictionResultController.java
@@ -22,6 +22,7 @@ package org.olat.portfolio.ui.structel.edit;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
@@ -49,11 +50,13 @@ import org.olat.portfolio.ui.filter.PortfolioFilterController;
 public class EPCollectRestrictionResultController extends BasicController {
 	
 	private final VelocityContainer mainVc;
+	private static final AtomicLong restrictionsCounter = new AtomicLong(1l);
 	
 	public EPCollectRestrictionResultController(UserRequest ureq, WindowControl wControl) {
 		super(ureq, wControl);
 
 		mainVc = createVelocityContainer("restrictions_msg");
+		mainVc.contextPut("restrictionId", Long.toString(restrictionsCounter.getAndIncrement()));
 		putInitialPanel(mainVc);
 	}
 
diff --git a/src/main/java/org/olat/portfolio/ui/structel/edit/_content/restrictions_msg.html b/src/main/java/org/olat/portfolio/ui/structel/edit/_content/restrictions_msg.html
index 27870125841d08dfb7ebd5533c6b86909931ad96..af2db8790a2b5bc6aa4f7e2ff89125358f42e44f 100644
--- a/src/main/java/org/olat/portfolio/ui/structel/edit/_content/restrictions_msg.html
+++ b/src/main/java/org/olat/portfolio/ui/structel/edit/_content/restrictions_msg.html
@@ -1,12 +1,12 @@
 #if($messages)
-<div class="panel-group" id="o_ep_restrictions">
+<div class="panel-group" id="o_ep_restrictions_$restrictionId">
 	<div class="panel #if($restrictionsPassed) panel-success #else panel-warning #end">
     	<div class="panel-heading">
       		<h4 class="panel-title">
-       			 <a data-toggle="collapse" data-parent="#o_ep_restrictions" href="#collapseMessages">$r.translate("collect.restriction")</a>
+       			 <a data-toggle="collapse" data-parent="#o_ep_restrictions_$restrictionId" href="#collapseMessages_$restrictionId">$r.translate("collect.restriction")</a>
       		</h4>
     	</div>
-		<div id="collapseMessages" class="panel-collapse collapse">
+		<div id="collapseMessages_$restrictionId" class="panel-collapse collapse">
 			<div class="panel-body">
 			#foreach($message in $messages)
 				<p>$message</p>
diff --git a/src/main/java/org/olat/search/EmptySearchResults.java b/src/main/java/org/olat/search/EmptySearchResults.java
index c67bf7ad5647b2a677b004c1171c61e94c1572a6..b3ddce3f06ad8345a2562ec4ab809cde16ee9896 100644
--- a/src/main/java/org/olat/search/EmptySearchResults.java
+++ b/src/main/java/org/olat/search/EmptySearchResults.java
@@ -47,8 +47,8 @@ public class EmptySearchResults implements SearchResults {
 	}
 	
 	@Override
-	public String getLength() {
-		return "0";
+	public int size() {
+		return 0;
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/search/SearchResults.java b/src/main/java/org/olat/search/SearchResults.java
index 5d4d1a18a9c33108397a7fd91d478eafeb03284d..9b6e37ebad4a69e9d56e59069f5a02e4d2fbb59f 100644
--- a/src/main/java/org/olat/search/SearchResults.java
+++ b/src/main/java/org/olat/search/SearchResults.java
@@ -36,7 +36,7 @@ import org.olat.search.model.ResultDocument;
 public interface SearchResults extends Serializable {
 	public static final EmptySearchResults EMPTY_SEARCH_RESULTS = new EmptySearchResults();
 	
-	public String getLength();
+	public int size();
 	
 	public List<ResultDocument> getList();
 	
diff --git a/src/main/java/org/olat/search/service/searcher/JmsSearchProvider.java b/src/main/java/org/olat/search/service/searcher/JmsSearchProvider.java
index b22c4d7d27fc579bfc5419a7a96f90915a863457..926b9de6c6d3e8ee5fedb2f79547f2832eb59bb2 100644
--- a/src/main/java/org/olat/search/service/searcher/JmsSearchProvider.java
+++ b/src/main/java/org/olat/search/service/searcher/JmsSearchProvider.java
@@ -236,7 +236,7 @@ public class JmsSearchProvider implements MessageListener {
 			SearchResults searchResults = this.doSearch(searchRequest.getQueryString(), searchRequest.getCondQueries(), identity, searchRequest.getRoles(),
 					searchRequest.getFirstResult(), searchRequest.getMaxResults(), searchRequest.isDoHighlighting());
 			if (log_.isDebug()) {
-				log_.debug("searchResults: " + searchResults.getLength());
+				log_.debug("searchResults: " + searchResults.size());
 			}
 			if (searchResults != null) {
 				session = acquireSession();
diff --git a/src/main/java/org/olat/search/service/searcher/SearchResultsImpl.java b/src/main/java/org/olat/search/service/searcher/SearchResultsImpl.java
index e29e51fae32e4c0b62f55722915640735bef4d32..f2e5c23fa2dff914446d957f1ff09806f56faa1f 100644
--- a/src/main/java/org/olat/search/service/searcher/SearchResultsImpl.java
+++ b/src/main/java/org/olat/search/service/searcher/SearchResultsImpl.java
@@ -106,13 +106,15 @@ public class SearchResultsImpl implements SearchResults {
 	 * 
 	 * @return  Length of result-list.
 	 */
-	public String getLength() {
-		return Integer.toString(resultList.size());
+	@Override
+	public int size() {
+		return resultList == null ? 0 : resultList.size();
 	}
 	
   /**
    * @return List of ResultDocument.
    */
+	@Override
 	public List<ResultDocument> getList() {
 		return resultList;
 	}
diff --git a/src/main/java/org/olat/search/ui/SearchInputController.java b/src/main/java/org/olat/search/ui/SearchInputController.java
index f068623d1fa19b66ecb4bcdaabb2383d03c2ebcf..7d6c247e6a47b2dd42c6070ab5a45bc9db3c0c24 100644
--- a/src/main/java/org/olat/search/ui/SearchInputController.java
+++ b/src/main/java/org/olat/search/ui/SearchInputController.java
@@ -478,19 +478,18 @@ public class SearchInputController extends FormBasicController implements Generi
 				searchResults = searchClient.doSearch(query, condQueries, ureq.getIdentity(), ureq.getUserSession().getRoles(), firstResult, maxReturns, true);
 				searchCache.put(getQueryCacheKey(firstResult, query, condQueries), searchResults);
 			}	
-			if ((firstResult == 0 && searchResults.getList().isEmpty())
-					&& !query.endsWith(FUZZY_SEARCH)) {
+			if (firstResult == 0 && searchResults.size() == 0 && !query.endsWith(FUZZY_SEARCH)) {
 				// result-list was empty => first try to find word via spell-checker
-	    	if (doSpellCheck) {
-	    		Set<String> didYouMeansWords = searchClient.spellCheck(searchString);
-		    	if (didYouMeansWords != null && !didYouMeansWords.isEmpty()) {
-		    		setDidYouMeanWords(didYouMeansWords);
+		    	if (doSpellCheck) {
+		    		Set<String> didYouMeansWords = searchClient.spellCheck(searchString);
+			    	if (didYouMeansWords != null && !didYouMeansWords.isEmpty()) {
+			    		setDidYouMeanWords(didYouMeansWords);
+			    	} else {
+			    		searchResults = doFuzzySearch(ureq, searchString, null, parentCtxt, docType, rsrcUrl, firstResult, maxReturns);
+			    	}
 		    	} else {
 		    		searchResults = doFuzzySearch(ureq, searchString, null, parentCtxt, docType, rsrcUrl, firstResult, maxReturns);
 		    	}
-	    	} else {
-	    		searchResults = doFuzzySearch(ureq, searchString, null, parentCtxt, docType, rsrcUrl, firstResult, maxReturns);
-	    	}
 			}
 			
 			if(firstResult == 0 && searchResults.getList().isEmpty()) {
diff --git a/src/main/webapp/static/js/openolat/wiki.js b/src/main/webapp/static/js/openolat/wiki.js
index 8abde178882ff061c278090540fafc67c69f5e87..43383f118c8a57e5d25ea903e38937a5888720f0 100644
--- a/src/main/webapp/static/js/openolat/wiki.js
+++ b/src/main/webapp/static/js/openolat/wiki.js
@@ -35,6 +35,7 @@ function changeAnchorTargets(id) {
 					var pre = href.substr(0, href.indexOf(":1/"));
 					var post = href.substr(href.indexOf(":1/")+3, href.length);
 					anchor.attr("href", pre+":0/"+post);
+					anchor.prop('onclick', null).off('click');
 				}
 			} else if (anchor.attr("class") == "edit" && anchor.attr("title").indexOf("Media:") != -1) { //media file not found
 				href = href.substr(0, href.indexOf("Edit:topic"));