diff --git a/src/main/java/org/olat/basesecurity/AuthHelper.java b/src/main/java/org/olat/basesecurity/AuthHelper.java
index 7da43afab34f0a334cd2000f5b1d39954bc67932..f6708fee6aa58e5a06d05587e0a251ae957ee9b0 100644
--- a/src/main/java/org/olat/basesecurity/AuthHelper.java
+++ b/src/main/java/org/olat/basesecurity/AuthHelper.java
@@ -253,7 +253,7 @@ public class AuthHelper {
 			} else {
 				//fxdiff FXOLAT-151: add eventually the identity to the security group
 				if(!groupDao.hasRole(invitation.getBaseGroup(), identity, GroupRoles.invitee.name())) {
-					groupDao.addMembership(invitation.getBaseGroup(), identity, GroupRoles.invitee.name());
+					groupDao.addMembershipTwoWay(invitation.getBaseGroup(), identity, GroupRoles.invitee.name());
 					DBFactory.getInstance().commit();
 				}
 
diff --git a/src/main/java/org/olat/basesecurity/manager/GroupDAO.java b/src/main/java/org/olat/basesecurity/manager/GroupDAO.java
index 1b9c05e1026c4707c2c02248ba2cb115b4696bd6..a0c8a5624fdcee58cb6169a00b5b8e53252889bf 100644
--- a/src/main/java/org/olat/basesecurity/manager/GroupDAO.java
+++ b/src/main/java/org/olat/basesecurity/manager/GroupDAO.java
@@ -80,7 +80,11 @@ public class GroupDAO {
 		return group;
 	}
 	
-	public GroupMembership addMembership(Group group, Identity identity, String role) {
+	/**
+	 * Add a membership to the group, in the set of the group too which can be
+	 * reloaded.
+	 */
+	public GroupMembership addMembershipTwoWay(Group group, Identity identity, String role) {
 		GroupMembershipImpl membership = new GroupMembershipImpl();
 		membership.setCreationDate(new Date());
 		membership.setLastModified(new Date());
@@ -98,6 +102,19 @@ public class GroupDAO {
 		return membership;
 	}
 	
+	/**
+	 * Create a membership without updating the set in the group.
+	 */
+	public void addMembershipOneWay(Group group, Identity identity, String role) {
+		GroupMembershipImpl membership = new GroupMembershipImpl();
+		membership.setCreationDate(new Date());
+		membership.setLastModified(new Date());
+		membership.setGroup(group);
+		membership.setIdentity(identity);
+		membership.setRole(role);
+		dbInstance.getCurrentEntityManager().persist(membership);
+	}
+	
 	public int removeMemberships(Group group) {
 		EntityManager em = dbInstance.getCurrentEntityManager();
 		List<GroupMembership> memberships = em.createNamedQuery("membershipsByGroup", GroupMembership.class)
diff --git a/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java b/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java
index 885616b5ab6bd0e990afbe5e618fe24b7a77c175..c9a0de90f03127399f296584cd542a9e0bce68f3 100644
--- a/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java
+++ b/src/main/java/org/olat/basesecurity/model/GroupMembershipImpl.java
@@ -59,6 +59,7 @@ import org.olat.core.id.Persistable;
 	@NamedQuery(name="membershipsByGroupAndIdentity", query="select membership from bgroupmember as membership where membership.group.key=:groupKey and membership.identity.key=:identityKey"),
 	@NamedQuery(name="membershipsByGroupIdentityAndRole", query="select membership from bgroupmember as membership where membership.group.key=:groupKey and membership.identity.key=:identityKey and membership.role=:role"),
 	@NamedQuery(name="countMembersByGroup", query="select count(membership.key) from bgroupmember as membership where membership.group.key=:groupKey"),
+	@NamedQuery(name="countMembersByGroupAndRole", query="select count(membership.key) from bgroupmember as membership where membership.group.key=:groupKey and membership.role=:role"),
 	@NamedQuery(name="membersByGroupAndRole", query="select distinct membership.identity from bgroupmember as membership where membership.group.key=:groupKey and membership.role=:role"),
 	@NamedQuery(name="hasRoleByGroupIdentityAndRole", query="select count(membership.key) from bgroupmember as membership where membership.group.key=:groupKey and membership.identity.key=:identityKey and membership.role=:role")
 })
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
index ad1ba63e55014a6554b6b821fdde907ef7e77c8c..47134e92332a49dfb844197e0968e1c5eff1b4a5 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupDAO.java
@@ -141,7 +141,7 @@ public class BusinessGroupDAO {
 		Group group = groupDao.createGroup();
 		businessgroup.setBaseGroup(group);
 		if (creator != null) {
-			groupDao.addMembership(group, creator, GroupRoles.coach.name());
+			groupDao.addMembershipTwoWay(group, creator, GroupRoles.coach.name());
 		}
 
 		EntityManager em = dbInstance.getCurrentEntityManager();
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
index 5ca80d6859dedc04d5767ad2962da7150ce2eaf6..0693b16d4a5a0707b9933a448e6be64eb144d0d0 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupRelationDAO.java
@@ -39,6 +39,8 @@ import org.olat.basesecurity.model.IdentityRefImpl;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.PersistenceHelper;
 import org.olat.core.id.Identity;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.course.assessment.manager.AssessmentModeDAO;
 import org.olat.group.BusinessGroup;
@@ -61,6 +63,8 @@ import org.springframework.stereotype.Service;
  */
 @Service("businessGroupRelationDao")
 public class BusinessGroupRelationDAO {
+	
+	private static final OLog log = Tracing.createLoggerFor(BusinessGroupRelationDAO.class);
 
 	@Autowired
 	private DB dbInstance;
@@ -75,9 +79,18 @@ public class BusinessGroupRelationDAO {
 		repositoryEntryRelationDao.createRelation(((BusinessGroupImpl)group).getBaseGroup(), re);
 	}
 	
-	public void addRole(Identity identity, BusinessGroupRef businessGroup, String role) {
-		Group group = getGroup(businessGroup);
-		groupDao.addMembership(group, identity, role);
+	public void addRole(Identity identity, BusinessGroup businessGroup, String role) {
+		Group group = null;
+		try {
+			group = businessGroup.getBaseGroup();
+			if(group == null) {
+				group = getGroup(businessGroup);
+			}
+		} catch(Exception e) {
+			log.warn("", e);
+			group = getGroup(businessGroup);
+		}
+		groupDao.addMembershipOneWay(group, identity, role);
 	}
 	
 	public boolean removeRole(Identity identity, BusinessGroupRef businessGroup, String role) {
@@ -195,6 +208,21 @@ public class BusinessGroupRelationDAO {
 		return count == null ? 0 : count.intValue();
 	}
 	
+	/**
+	 * Count the number of participants.
+	 * 
+	 * @param group
+	 * @return
+	 */
+	public int countEnrollment(BusinessGroup group) {
+		Number count = dbInstance.getCurrentEntityManager()
+				.createNamedQuery("countMembersByGroupAndRole", Number.class)
+				.setParameter("groupKey", group.getBaseGroup().getKey())
+				.setParameter("role", GroupRoles.participant.name())
+				.getSingleResult();
+		return count == null ? 0 : count.intValue();
+	}
+	
 	/**
 	 * Return the number of coaches with author rights.
 	 * @param group
diff --git a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
index 5cef78b7fa898f45193f066841ff8a2a3ced3281..fd798171b2e4243aaabb09df9c681751ddba67c0 100644
--- a/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
+++ b/src/main/java/org/olat/group/manager/BusinessGroupServiceImpl.java
@@ -1385,11 +1385,11 @@ public class BusinessGroupServiceImpl implements BusinessGroupService, UserDataD
 				reservationDao.deleteReservation(reservation);
 			}
 		} else if (reloadedGroup.getMaxParticipants() != null) {
-			int participantsCounter = businessGroupRelationDAO.countRoles(reloadedGroup, GroupRoles.participant.name());
+			int participantsCounter = businessGroupRelationDAO.countEnrollment(reloadedGroup);
 			int reservations = reservationDao.countReservations(reloadedGroup.getResource());
 			
 			log.info("doEnroll - participantsCounter: " + participantsCounter + ", reservations: " + reservations + " maxParticipants: " + reloadedGroup.getMaxParticipants().intValue(), identity.getName());
-			if (reservation == null && (participantsCounter + reservations) >= reloadedGroup.getMaxParticipants().intValue()) {
+			if ((participantsCounter + reservations) >= reloadedGroup.getMaxParticipants().intValue()) {
 				// already full, show error and updated choose page again
 				if (reloadedGroup.getWaitingListEnabled().booleanValue()) {
 					addToWaitingList(ureqIdentity, identity, reloadedGroup, mailing, events);
diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
index e39ce15e4e95ac1a45bb109f54f86d1e243052ff..4324f1ba8f8f957acc28d56dc5cd1804a5cbfb73 100644
--- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
+++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
@@ -173,7 +173,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 	public Binder createNewBinder(String title, String summary, String imagePath, Identity owner) {
 		BinderImpl portfolio = binderDao.createAndPersist(title, summary, imagePath, null);
 		if(owner != null) {
-			groupDao.addMembership(portfolio.getBaseGroup(), owner, PortfolioRoles.owner.name());
+			groupDao.addMembershipTwoWay(portfolio.getBaseGroup(), owner, PortfolioRoles.owner.name());
 		}
 		return portfolio;
 	}
@@ -188,7 +188,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 	public void createAndPersistBinderTemplate(Identity owner, RepositoryEntry entry, Locale locale) {
 		BinderImpl binder = binderDao.createAndPersist(entry.getDisplayname(), entry.getDescription(), null, entry);
 		if(owner != null) {
-			groupDao.addMembership(binder.getBaseGroup(), owner, PortfolioRoles.owner.name());
+			groupDao.addMembershipTwoWay(binder.getBaseGroup(), owner, PortfolioRoles.owner.name());
 		}
 		//add section
 		Translator pt = Util.createPackageTranslator(PortfolioHomeController.class, locale);
@@ -564,7 +564,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 	public Binder assignBinder(Identity owner, BinderRef templateBinder, RepositoryEntry entry, String subIdent, Date deadline) {
 		BinderImpl reloadedTemplate = (BinderImpl)binderDao.loadByKey(templateBinder.getKey());
 		BinderImpl binder = binderDao.createCopy(reloadedTemplate, entry, subIdent);
-		groupDao.addMembership(binder.getBaseGroup(), owner, PortfolioRoles.owner.name());
+		groupDao.addMembershipTwoWay(binder.getBaseGroup(), owner, PortfolioRoles.owner.name());
 		return binder;
 	}
 
@@ -635,7 +635,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 	public void addAccessRights(PortfolioElement element, Identity identity, PortfolioRoles role) {
 		Group baseGroup = element.getBaseGroup();
 		if(!groupDao.hasRole(baseGroup, identity, role.name())) {
-			groupDao.addMembership(baseGroup, identity, role.name());
+			groupDao.addMembershipTwoWay(baseGroup, identity, role.name());
 		}
 	}
 	
@@ -647,7 +647,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 				if(change.isAdd()) {
 					if(!groupDao.hasRole(baseGroup, identity, change.getRole().name())) {
 						Group group = getGroup(change.getElement());
-						groupDao.addMembership(group, identity, change.getRole().name());
+						groupDao.addMembershipOneWay(group, identity, change.getRole().name());
 					}
 				} else {
 					if(groupDao.hasRole(baseGroup, identity, change.getRole().name())) {
@@ -839,7 +839,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 			((SectionImpl)reloadedSection).setSectionStatus(SectionStatus.inProgress);
 		}
 		Page page = pageDao.createAndPersist(title, summary, imagePath, align, editable, reloadedSection, null);
-		groupDao.addMembership(page.getBaseGroup(), owner, PortfolioRoles.owner.name());
+		groupDao.addMembershipTwoWay(page.getBaseGroup(), owner, PortfolioRoles.owner.name());
 		return page;
 	}
 
diff --git a/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java b/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java
index 61d160033d3df55ae53d835dc7805a7ec45fa09a..dd332c2435104114039a434737a0d328ecb5e583 100644
--- a/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java
+++ b/src/main/java/org/olat/portfolio/manager/EPPolicyManager.java
@@ -225,7 +225,7 @@ public class EPPolicyManager {
 			Group secGroup = groupDao.createGroup();
 			relation = createBaseRelation(map, secGroup, EPMapPolicy.Type.user.name(), policy.getFrom(), policy.getTo());
 			for(Identity identity:policy.getIdentities()) {
-				groupDao.addMembership(secGroup, identity, GroupRoles.participant.name());
+				groupDao.addMembershipTwoWay(secGroup, identity, GroupRoles.participant.name());
 			}
 		} else {
 			EPStructureElementToGroupRelation currentPolicy = reusePolicyInSession(relation, map);
@@ -248,7 +248,7 @@ public class EPPolicyManager {
 				groupDao.removeMembership(secGroup, currentMember);
 			}
 			for(Identity newMember:newMembers) {
-				groupDao.addMembership(secGroup, newMember, GroupRoles.participant.name());
+				groupDao.addMembershipTwoWay(secGroup, newMember, GroupRoles.participant.name());
 			}
 		}
 		return relation;
diff --git a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
index c3102bf0e1b4e4c590ed70da457ce7520e087438..6c8067aed974e808bcc7c834e8655e6eca0f1987 100755
--- a/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
+++ b/src/main/java/org/olat/portfolio/manager/EPStructureManager.java
@@ -1829,7 +1829,7 @@ public class EPStructureManager {
 		Group group = repositoryEntyRelationDao.getDefaultGroup(entry);
 		if(group == null) {
 			group = groupDao.createGroup();
-			groupDao.addMembership(group, identity, GroupRoles.owner.name());
+			groupDao.addMembershipTwoWay(group, identity, GroupRoles.owner.name());
 		}
 		
 		EPStructureElementToGroupRelation relation = createBaseRelation(el, group);
@@ -1885,7 +1885,7 @@ public class EPStructureManager {
 		relation.setCreationDate(new Date());
 		relation.setGroup(ownerGroup);
 		relation.setStructureElement(element);
-		groupDao.addMembership(ownerGroup, author, GroupRoles.owner.name());
+		groupDao.addMembershipTwoWay(ownerGroup, author, GroupRoles.owner.name());
 		return relation;
 	}
 	
diff --git a/src/main/java/org/olat/portfolio/manager/InvitationDAO.java b/src/main/java/org/olat/portfolio/manager/InvitationDAO.java
index c104acd26e25d091547806bdbc7e7ad23b90f794..b279768530d411721342b9f19e5fe71e6a9b0640 100644
--- a/src/main/java/org/olat/portfolio/manager/InvitationDAO.java
+++ b/src/main/java/org/olat/portfolio/manager/InvitationDAO.java
@@ -110,7 +110,7 @@ public class InvitationDAO {
 		User user = userManager.createUser(invitation.getFirstName(), invitation.getLastName(), invitation.getMail());
 		user.getPreferences().setLanguage(locale.toString());
 		Identity invitee = securityManager.createAndPersistIdentityAndUser(tempUsername, null, user, null, null);
-		groupDao.addMembership(invitation.getBaseGroup(), invitee, GroupRoles.invitee.name());
+		groupDao.addMembershipTwoWay(invitation.getBaseGroup(), invitee, GroupRoles.invitee.name());
 		return invitee;
 	}
 	
@@ -129,7 +129,7 @@ public class InvitationDAO {
 			invitee = securityManager.createAndPersistIdentityAndUser(tempUsername, null, user, null, null, null);
 		}
 		// add invitee to the security group of that portfolio element
-		groupDao.addMembership(group, invitee, GroupRoles.invitee.name());			
+		groupDao.addMembershipTwoWay(group, invitee, GroupRoles.invitee.name());			
 		return invitee;
 	}
 	
diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
index 85e1eccab580d6e7697f1759cf4f600aa845d441..459a6519ba81662e0c57fa59f0c0b6d57ab7c793 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
@@ -168,7 +168,7 @@ public class RepositoryEntryRelationDAO {
 	
 	public void addRole(Identity identity, RepositoryEntryRef re, String role) {
 		Group group = getDefaultGroup(re);
-		groupDao.addMembership(group, identity, role);
+		groupDao.addMembershipOneWay(group, identity, role);
 	}
 	
 	public int removeRole(IdentityRef identity, RepositoryEntryRef re, String role) {
diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
index 90f6e7600bf0a4483ae44ed859258d586e7a2a82..bfc6933b253efa78f889a1ea850f05fcb8c6276f 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
@@ -215,7 +215,7 @@ public class RepositoryServiceImpl implements RepositoryService {
 		re.setGroups(rels);
 		
 		if(initialAuthor != null) {
-			groupDao.addMembership(group, initialAuthor, GroupRoles.owner.name());
+			groupDao.addMembershipTwoWay(group, initialAuthor, GroupRoles.owner.name());
 		}
 		
 		dbInstance.getCurrentEntityManager().persist(re);
diff --git a/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java b/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java
index 7da1b5fa3b1506d5251577bce0534f35d528f050..5febf6910c3cff3ccf1f5c66fa1100ed458d3bc8 100644
--- a/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java
+++ b/src/test/java/org/olat/basesecurity/manager/GroupDAOTest.java
@@ -61,18 +61,26 @@ public class GroupDAOTest extends OlatTestCase {
 	public void createGroupMembership() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership = groupDao.addMembership(group, id, "author");
+		GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author");
 
 		dbInstance.commit();
 		
 		Assert.assertNotNull(membership);
 	}
 	
+	@Test
+	public void createGroupMembership_oneWay() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-");
+		Group group = groupDao.createGroup();
+		groupDao.addMembershipOneWay(group, id, "author");
+		dbInstance.commit();
+	}
+	
 	@Test
 	public void createGroupMembership_v2() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership = groupDao.addMembership(group, id, "author");
+		GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author");
 		dbInstance.commit();
 		
 		Assert.assertNotNull(membership);
@@ -86,11 +94,25 @@ public class GroupDAOTest extends OlatTestCase {
 		Assert.assertEquals(1, members.size());
 	}
 	
+	@Test
+	public void createGroupMembership_oneWay_v2() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-");
+		Group group = groupDao.createGroup();
+		groupDao.addMembershipOneWay(group, id, "author");
+		dbInstance.commitAndCloseSession();
+		
+		GroupImpl loadedGroup = (GroupImpl)groupDao.loadGroup(group.getKey());
+		Assert.assertNotNull(loadedGroup);
+		Set<GroupMembership> members = loadedGroup.getMembers();
+		Assert.assertNotNull(members);
+		Assert.assertEquals(1, members.size());
+	}
+	
 	@Test
 	public void getMemberships() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership = groupDao.addMembership(group, id, "author");
+		GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author");
 		dbInstance.commit();
 		
 		Assert.assertNotNull(membership);
@@ -101,13 +123,25 @@ public class GroupDAOTest extends OlatTestCase {
 		Assert.assertNotNull(members);
 		Assert.assertEquals(1, members.size());
 	}
+	
+	@Test
+	public void getMemberships_oneWay() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-1-");
+		Group group = groupDao.createGroup();
+		groupDao.addMembershipOneWay(group, id, "author");
+		dbInstance.commitAndCloseSession();
+		
+		List<GroupMembership> members = groupDao.getMemberships(group, "author");
+		Assert.assertNotNull(members);
+		Assert.assertEquals(1, members.size());
+	}
 
 	@Test
 	public void hasRole() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-2-");
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-2b-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership = groupDao.addMembership(group, id, "author");
+		GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author");
 		dbInstance.commit();
 		
 		Assert.assertNotNull(membership);
@@ -126,7 +160,7 @@ public class GroupDAOTest extends OlatTestCase {
 	public void getMembers() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-3-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership = groupDao.addMembership(group, id, "author");
+		GroupMembership membership = groupDao.addMembershipTwoWay(group, id, "author");
 		dbInstance.commit();
 		
 		Assert.assertNotNull(membership);
@@ -143,9 +177,9 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-5-");
 		Identity id3 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-6-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot");
-		GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot");
-		GroupMembership membership3 = groupDao.addMembership(group, id3, "copilot");
+		GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot");
+		GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot");
+		GroupMembership membership3 = groupDao.addMembershipTwoWay(group, id3, "copilot");
 		dbInstance.commit();
 		
 		Assert.assertNotNull(membership1);
@@ -162,8 +196,8 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-7-");
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-8-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot");
-		GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot");
+		GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot");
+		GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot");
 		Assert.assertNotNull(membership1);
 		Assert.assertNotNull(membership2);
 		dbInstance.commitAndCloseSession();
@@ -189,9 +223,9 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-7-");
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-8-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot");
-		GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot");
-		GroupMembership membership2alt = groupDao.addMembership(group, id2, "commander");
+		GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot");
+		GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot");
+		GroupMembership membership2alt = groupDao.addMembershipTwoWay(group, id2, "commander");
 		Assert.assertNotNull(membership1);
 		Assert.assertNotNull(membership2);
 		Assert.assertNotNull(membership2alt);
@@ -226,8 +260,8 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-7-");
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-8-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot");
-		GroupMembership membership2 = groupDao.addMembership(group, id2, "pilot");
+		GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot");
+		GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "pilot");
 		Assert.assertNotNull(membership1);
 		Assert.assertNotNull(membership2);
 		dbInstance.commitAndCloseSession();
@@ -250,8 +284,8 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-12-");
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-13-");
 		Group group = groupDao.createGroup();
-		GroupMembership membership1 = groupDao.addMembership(group, id1, "pilot");
-		GroupMembership membership2 = groupDao.addMembership(group, id2, "copilot");
+		GroupMembership membership1 = groupDao.addMembershipTwoWay(group, id1, "pilot");
+		GroupMembership membership2 = groupDao.addMembershipTwoWay(group, id2, "copilot");
 		Assert.assertNotNull(membership1);
 		Assert.assertNotNull(membership2);
 		dbInstance.commitAndCloseSession();
@@ -278,14 +312,14 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id1 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-9-");
 		Identity id2 = JunitTestHelper.createAndPersistIdentityAsRndUser("bgrp-10-");
 		Group group1 = groupDao.createGroup();
-		GroupMembership membership1 = groupDao.addMembership(group1, id1, "pilot");
-		GroupMembership membership2 = groupDao.addMembership(group1, id2, "pilot");
+		GroupMembership membership1 = groupDao.addMembershipTwoWay(group1, id1, "pilot");
+		GroupMembership membership2 = groupDao.addMembershipTwoWay(group1, id2, "pilot");
 		Assert.assertNotNull(membership1);
 		Assert.assertNotNull(membership2);
 		dbInstance.commitAndCloseSession();
 		Group group2 = groupDao.createGroup();
-		GroupMembership membership3 = groupDao.addMembership(group2, id1, "passanger");
-		GroupMembership membership4 = groupDao.addMembership(group2, id2, "passanger");
+		GroupMembership membership3 = groupDao.addMembershipTwoWay(group2, id1, "passanger");
+		GroupMembership membership4 = groupDao.addMembershipTwoWay(group2, id2, "passanger");
 		Assert.assertNotNull(membership3);
 		Assert.assertNotNull(membership4);
 		dbInstance.commitAndCloseSession();
@@ -359,7 +393,7 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("grant-1-");
 		Group group = groupDao.createGroup();
 		String role = "hasGrant-role";
-		groupDao.addMembership(group, id, role);
+		groupDao.addMembershipTwoWay(group, id, role);
 		OLATResource resource = JunitTestHelper.createRandomResource();
 		groupDao.addGrant(group, role, "hasGrant-perm", resource);
 		dbInstance.commitAndCloseSession();
@@ -373,7 +407,7 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("grant-1-");
 		Group group = groupDao.createGroup();
 		String role = "getPermissions-role";
-		groupDao.addMembership(group, id, role);
+		groupDao.addMembershipTwoWay(group, id, role);
 		OLATResource resource = JunitTestHelper.createRandomResource();
 		groupDao.addGrant(group, role, "getPermissions-perm", resource);
 		dbInstance.commitAndCloseSession();
@@ -389,9 +423,9 @@ public class GroupDAOTest extends OlatTestCase {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("grant-1-");
 		Group group = groupDao.createGroup();
 		String role1 = "getPermissions-role-1";
-		groupDao.addMembership(group, id, role1);
+		groupDao.addMembershipTwoWay(group, id, role1);
 		String role2 = "getPermissions-role-2";
-		groupDao.addMembership(group, id, role2);
+		groupDao.addMembershipTwoWay(group, id, role2);
 		OLATResource resource = JunitTestHelper.createRandomResource();
 		groupDao.addGrant(group, role1, "getPermissions-perm-1", resource);
 		groupDao.addGrant(group, role2, "getPermissions-perm-2", resource);
@@ -408,8 +442,8 @@ public class GroupDAOTest extends OlatTestCase {
 	public void addRemoveGrant() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("addremove-1-");
 		Group group = groupDao.createGroup();
-		groupDao.addMembership(group, id, "addremove-1");
-		groupDao.addMembership(group, id, "addremove-2");
+		groupDao.addMembershipTwoWay(group, id, "addremove-1");
+		groupDao.addMembershipTwoWay(group, id, "addremove-2");
 		OLATResource resource = JunitTestHelper.createRandomResource();
 		groupDao.addGrant(group, "addremove-1", "addremove-1-perm", resource);
 		groupDao.addGrant(group, "addremove-2", "addremove-2-perm", resource);
@@ -436,8 +470,8 @@ public class GroupDAOTest extends OlatTestCase {
 	public void addRemoveGrants() {
 		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("addremove-1-");
 		Group group = groupDao.createGroup();
-		groupDao.addMembership(group, id, "addremove-1");
-		groupDao.addMembership(group, id, "addremove-2");
+		groupDao.addMembershipTwoWay(group, id, "addremove-1");
+		groupDao.addMembershipTwoWay(group, id, "addremove-2");
 		OLATResource resource = JunitTestHelper.createRandomResource();
 		groupDao.addGrant(group, "addremove-1", "addremove-1-perm", resource);
 		groupDao.addGrant(group, "addremove-1", "addremove-11-perm", resource);
diff --git a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java
index 0bc285744fa416f59ae1febdad118144687059ae..9e46d1b9a0a3eb4178c9a427a867ae757c91500d 100644
--- a/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java
+++ b/src/test/java/org/olat/course/nodes/en/EnrollmentManagerConcurrentTest.java
@@ -33,12 +33,14 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
+import java.util.Random;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.GroupRoles;
@@ -58,6 +60,11 @@ import org.olat.core.id.context.BusinessControl;
 import org.olat.core.id.context.ContextEntry;
 import org.olat.core.logging.OLog;
 import org.olat.core.logging.Tracing;
+import org.olat.core.logging.activity.OlatResourceableType;
+import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
+import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller;
+import org.olat.core.util.SessionInfo;
+import org.olat.core.util.UserSession;
 import org.olat.core.util.Util;
 import org.olat.course.CourseFactory;
 import org.olat.course.CourseModule;
@@ -75,6 +82,7 @@ import org.olat.resource.OLATResource;
 import org.olat.resource.OLATResourceManager;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
+import org.olat.util.logging.activity.LoggingResourceable;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -249,23 +257,30 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win
 	
 	@Test
 	public void testConcurrentEnrollmentWithWaitingList() {
-		List<Identity> ids = new ArrayList<Identity>(30);	
-		for(int i=0; i<30; i++) {
+		int NUM_OF_USERS = 30;
+		List<Identity> ids = new ArrayList<Identity>(NUM_OF_USERS);	
+		for(int i=0; i<NUM_OF_USERS; i++) {
 			Identity id = JunitTestHelper.createAndPersistIdentityAsUser("enroll-a-" + i + "-" + UUID.randomUUID().toString());
 			ids.add(id);
 		}
 		
 		ENCourseNode enNode = new ENCourseNode();
-		OLATResource resource = resourceManager.createOLATResourceInstance(CourseModule.class);
-		RepositoryEntry addedEntry = repositoryService.create("Ayanami", "-", "Enrollment test course 2", "A JUnit course", resource);
+		
+		Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("enroller");
+		RepositoryEntry addedEntry = JunitTestHelper.deployBasicCourse(author);
 		CourseEnvironment cenv = CourseFactory.createCourse(addedEntry, "Test-Enroll", "Test", "Test enrollment with concurrent users").getCourseEnvironment();
 		BusinessGroup group = businessGroupService.createBusinessGroup(id1, "Enrollment", "Enroll", new Integer(1), new Integer(10), true, false, null);
 		Assert.assertNotNull(group);
 		dbInstance.commitAndCloseSession();
 
 		final CountDownLatch doneSignal = new CountDownLatch(ids.size());
+		EnrollThread[] threads = new EnrollThread[NUM_OF_USERS];
+		int t = 0;
 		for(Identity id:ids) {
-			EnrollThread thread = new EnrollThread(id, group, enNode, cenv, doneSignal);
+			threads[t++] = new EnrollThread(id, addedEntry, group, enNode, cenv, doneSignal);
+		}
+		
+		for(EnrollThread thread:threads) {
 			thread.start();
 		}
 		
@@ -275,6 +290,8 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win
 		} catch (InterruptedException e) {
 			fail("" + e.getMessage());
 		}
+		
+		dbInstance.commitAndCloseSession();
 
 		List<Identity> enrolledIds = businessGroupService.getMembers(group, GroupRoles.participant.name());
 		Assert.assertNotNull(enrolledIds);
@@ -284,17 +301,91 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win
 		Assert.assertNotNull(waitingIds);
 		Assert.assertEquals(ids.size() - 10, waitingIds.size());
 	}
+	
+	
+	@Test @Ignore
+	public void testConcurrentEnrollmentWithWaitingList_big() {
+		List<Identity> ids = new ArrayList<Identity>(100);	
+		for(int i=0; i<100; i++) {
+			Identity id = JunitTestHelper.createAndPersistIdentityAsUser("enroll-a-" + i + "-" + UUID.randomUUID().toString());
+			ids.add(id);
+		}
+		
+		Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("enroller");
+		RepositoryEntry addedEntry = JunitTestHelper.deployBasicCourse(author);
+		
+		ENCourseNode enNode1 = new ENCourseNode();
+		ENCourseNode enNode2 = new ENCourseNode();
+		ENCourseNode enNode3 = new ENCourseNode();
+		ENCourseNode enNode4 = new ENCourseNode();
+		ENCourseNode enNode5 = new ENCourseNode();
+
+		CourseEnvironment cenv = CourseFactory.loadCourse(addedEntry).getCourseEnvironment();
+		BusinessGroup group1 = businessGroupService.createBusinessGroup(author, "Enrollment 1", "Enroll 1", new Integer(1), new Integer(8), true, true, addedEntry);
+		BusinessGroup group2 = businessGroupService.createBusinessGroup(author, "Enrollment 2", "Enroll 2", new Integer(1), new Integer(10), true, true, addedEntry);
+		BusinessGroup group3 = businessGroupService.createBusinessGroup(author, "Enrollment 3", "Enroll 3", new Integer(1), new Integer(4), true, true, addedEntry);
+		BusinessGroup group4 = businessGroupService.createBusinessGroup(author, "Enrollment 4", "Enroll 4", new Integer(1), new Integer(10), true, true, addedEntry);
+		BusinessGroup group5 = businessGroupService.createBusinessGroup(author, "Enrollment 5", "Enroll 5", new Integer(1), new Integer(9), true, true, addedEntry);
+		dbInstance.commitAndCloseSession();
+
+		EnrollThread[] threads = new EnrollThread[100];
+		
+		final CountDownLatch doneSignal = new CountDownLatch(ids.size());
+		int t = 0;
+		for(int i=0; i<30; i++) {
+			threads[t++] = new EnrollThread(ids.get(i), addedEntry, group1, enNode1, cenv, doneSignal);
+		}
+		for(int i=30; i<50; i++) {
+			threads[t++] = new EnrollThread(ids.get(i), addedEntry, group2, enNode2, cenv, doneSignal);
+		}
+		for(int i=50; i<70; i++) {
+			threads[t++] = new EnrollThread(ids.get(i), addedEntry, group3, enNode3, cenv, doneSignal);
+		}
+		for(int i=70; i<90; i++) {
+			threads[t++] = new EnrollThread(ids.get(i), addedEntry, group4, enNode4, cenv, doneSignal);
+		}
+		for(int i=90; i<100; i++) {
+			threads[t++] = new EnrollThread(ids.get(i), addedEntry, group5, enNode5, cenv, doneSignal);
+		}
+		
+		for(EnrollThread thread:threads) {
+			thread.start();
+		}
+
+		try {
+			boolean interrupt = doneSignal.await(360, TimeUnit.SECONDS);
+			assertTrue("Test takes too long (more than 10s)", interrupt);
+		} catch (InterruptedException e) {
+			fail("" + e.getMessage());
+		}
+		
+		dbInstance.commitAndCloseSession();
+
+		List<Identity> enrolled_1_Ids = businessGroupService.getMembers(group1, GroupRoles.participant.name());
+		Assert.assertEquals(8, enrolled_1_Ids.size());
+		List<Identity> enrolled_2_Ids = businessGroupService.getMembers(group2, GroupRoles.participant.name());
+		Assert.assertEquals(10, enrolled_2_Ids.size());
+		List<Identity> enrolled_3_Ids = businessGroupService.getMembers(group3, GroupRoles.participant.name());
+		Assert.assertEquals(4, enrolled_3_Ids.size());
+		List<Identity> enrolled_4_Ids = businessGroupService.getMembers(group4, GroupRoles.participant.name());
+		Assert.assertEquals(10, enrolled_4_Ids.size());
+		List<Identity> enrolled_5_Ids = businessGroupService.getMembers(group5, GroupRoles.participant.name());
+		Assert.assertEquals(9, enrolled_5_Ids.size());
+	}
 
 	private class EnrollThread extends Thread {
 		private final ENCourseNode enNode;
 		private final Identity identity;
 		private final CourseEnvironment cenv;
 		private final BusinessGroup group;
+		private final RepositoryEntry courseEntry;
 		private final CountDownLatch doneSignal;
 		
-		public EnrollThread(Identity identity, BusinessGroup group, ENCourseNode enNode, CourseEnvironment cenv, CountDownLatch doneSignal) {
+		public EnrollThread(Identity identity, RepositoryEntry courseEntry, BusinessGroup group,
+				ENCourseNode enNode, CourseEnvironment cenv, CountDownLatch doneSignal) {
 			this.enNode = enNode;
 			this.group = group;
+			this.courseEntry = courseEntry;
 			this.identity = identity;
 			this.cenv = cenv;
 			this.doneSignal = doneSignal;
@@ -303,19 +394,30 @@ public class EnrollmentManagerConcurrentTest extends OlatTestCase implements Win
 		@Override
 		public void run() {
 			try {
-				sleep(10);
+				UserSession session = new UserSession();
+				session.setIdentity(identity);
+				session.setSessionInfo(new SessionInfo(identity.getKey(), identity.getName()));
+				ThreadLocalUserActivityLoggerInstaller.initUserActivityLogger(session);
+				
 				IdentityEnvironment ienv = new IdentityEnvironment();
 				ienv.setIdentity(identity);
 				UserCourseEnvironment userCourseEnv = new UserCourseEnvironmentImpl(ienv, cenv);
 				CoursePropertyManager coursePropertyManager = userCourseEnv.getCourseEnvironment().getCoursePropertyManager();
 				CourseGroupManager courseGroupManager = userCourseEnv.getCourseEnvironment().getCourseGroupManager();
 				
+				ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(courseEntry.getOlatResource(), OlatResourceableType.course));
+				ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(enNode));
+				ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrap(group));
+
+				sleep(Math.round(new Random().nextDouble() * 100l));
 				enrollmentManager.doEnroll(identity, JunitTestHelper.getUserRoles(), group, enNode, coursePropertyManager, EnrollmentManagerConcurrentTest.this /*WindowControl mock*/, testTranslator,
 						new ArrayList<Long>()/*enrollableGroupNames*/, new ArrayList<Long>()/*enrollableAreaNames*/, courseGroupManager);
-				DBFactory.getInstance().commitAndCloseSession();
+				DBFactory.getInstance().commit();
 			} catch (Exception e) {
 				log.error("", e);
 			}	finally {
+				ThreadLocalUserActivityLoggerInstaller.resetUserActivityLogger();
+				DBFactory.getInstance().commitAndCloseSession();
 				doneSignal.countDown();
 			}
 		}
diff --git a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java
index 879d8c41cdf5ad7a174dd39f38d68d653b16d1e5..5a695ccd9bb4db274e2a51af87ec9cdc54ff4c37 100644
--- a/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java
+++ b/src/test/java/org/olat/group/test/BusinessGroupRelationDAOTest.java
@@ -93,7 +93,7 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		Group group = ((BusinessGroupImpl)businessGroup).getBaseGroup();
-		groupDao.addMembership(group, coach, "coach");
+		groupDao.addMembershipTwoWay(group, coach, "coach");
 		dbInstance.commitAndCloseSession();
 		
 		List<String> roles = businessGroupRelationDao.getRoles(coach, businessGroup);
@@ -582,6 +582,36 @@ public class BusinessGroupRelationDAOTest extends OlatTestCase {
 		Assert.assertEquals(1, numOfAuthors);
 	}
 	
+	@Test
+	public void countRoles() {
+		Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("auth-" + UUID.randomUUID().toString());
+		Identity test = JunitTestHelper.createAndPersistIdentityAsRndUser("not-auth");
+		BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false);
+		businessGroupRelationDao.addRole(author, group, GroupRoles.coach.name());
+		businessGroupRelationDao.addRole(test, group, GroupRoles.coach.name());
+		dbInstance.commitAndCloseSession();
+		
+		int numOfCoachs = businessGroupRelationDao.countRoles(group, GroupRoles.coach.name());
+		Assert.assertEquals(2, numOfCoachs);
+		int numOfParticipants = businessGroupRelationDao.countRoles(group, GroupRoles.participant.name());
+		Assert.assertEquals(0, numOfParticipants);
+	}
+	
+	@Test
+	public void countEnrollment() {
+		Identity author = JunitTestHelper.createAndPersistIdentityAsAuthor("auth-" + UUID.randomUUID().toString());
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("not-auth");
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("not-auth");
+		BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false);
+		businessGroupRelationDao.addRole(author, group, GroupRoles.coach.name());
+		businessGroupRelationDao.addRole(participant1, group, GroupRoles.participant.name());
+		businessGroupRelationDao.addRole(participant2, group, GroupRoles.participant.name());
+		dbInstance.commitAndCloseSession();
+		
+		int numOfParticipants = businessGroupRelationDao.countEnrollment(group);
+		Assert.assertEquals(2, numOfParticipants);
+	}
+	
 	@Test
 	public void loadForUpdate() {
 		BusinessGroup group = businessGroupDao.createAndPersist(null, "rel-repo", "rel-repo-desc", 0, 10, true, false, false, false, false);