Hi all,
We built a huge intranet portal with hundreds of roles and groups. The intranet is structured into different MO's (Marktorganisations) which have an initial role and then MO specific roles which are merged.
We recognized that our intranet is getting slower and slower so we are trying cut down the groups and roles a user has assigned. A user should than be only in the groups of the current MO he is visiting, and of course only have the roles assigned to this groups. Every time a user switch to an MO this group switch happens.
The MO-Switcher works like this:
1. Check if a switch has been initialized. If so, get the ID of the new group passed as an URL parameter
2. Remove user from the old group
3. Insert user into the new group
4. Get the navigation target for the "Inside" role within the new MO
5. Redirect to this navigation target
Unfortunately we are facing a delay between the switching of the UME groups and the time the navigation knows about the new roles assignments.
The problem occurs at step 4, after the user has been assigned to the new visitor group. Although the user now has assigned the new roles, sometimes it is not possible to find the navigation node for "Inside".
The curious thing is, sometimes it works, sometimes it doesn't. It looks like the more sub sites a MO has, the less often it works. Especially for HAG we have this problem. For the smaller Mos the switch seems to work.
Details of Step 4:
1. find navigation node within the TLN
2. find the main MO navigation node
3. find the navigation node for "Inside" below the MO main role
I have created an abstract portal component which does the group switch and prints out the results of every single step in finding "Inside".
If it was not possible to find the navigation node, the method waits for 3 seconds and tries it again.
In the first run the methods for retrieving the merged nodes are returning a different result than in the second one.
Since exactly the same code is executed, time can be the only difference. Therefore it should be either a caching "problem" within the methods of the navigation
or the merging of the roles has not been completed by the time the code is execute the first time (maybe due to the group to group to role assignment)
Here the code, some might miss them 😊
1)USER->GROUP change:
IUserMaint ium = UMFactory.getUserFactory().getMutableUser(user.getUniqueID()); ium.addtoGroup(newGroup) ium.removeFromGroup(oldGroup) ium.commit();
2)invalidate http-Session
request.getComponentSession().getHttpSession().invalidate();
3)delete cookies, client-side redirect
response.write("document.cookies=null;"); response.write("location.replace("" + newUrl + "");n");
Group switch:
*************
private boolean doGroupSwitch(IGroup newGroup) throws UMException { IGroupFactory groupFact = UMFactory.getGroupFactory(); IUserMaint ium = UMFactory.getUserFactory().getMutableUser( this.request.getUser().getUniqueID()); String userId = ium.getUniqueID(); String newGroupId = newGroup.getUniqueID(); boolean changed = false; boolean done = false; Iterator it = ROLEMAP.keySet().iterator(); // iterate throu all visitor groups while (it.hasNext()) { IGroup group = groupFact.getMutableGroup(((IGroup) it.next()).getUniqueID()); // remove from old group if (!newGroupId.equals(group.getUniqueID()) && group.isMember(userId, false)) { ium.removeFromGroup(group.getUniqueID()); changed = true; // changed = group.removeMember(username); // insert into new group } else if ( newGroupId.equals(group.getUniqueID()) && !group.isMember(userId, false)) { ium.addToGroup(group.getUniqueID()); changed = true; // changed = group.addMember(username); } // if any changes are done, execute commit if (changed) { // group.commit(); ium.commit(); groupFact.invalidateCacheEntry(group.getUniqueID()); done = true; } } return done; }
MO switch:
**********
public boolean doMOSwitch() throws UMException, InterruptedException, NoSuchRoleException, NamingException { // check if MO switch is initialized String newGroupId = this.request.getParameter("newGroupId"); if (newGroupId != null) { IGroupFactory groupFact = UMFactory.getGroupFactory(); IGroup newGroup = groupFact.getGroup(newGroupId); // check if a different MO is selected than the current one // do switch only if a new MO is selected if (newGroup != null && !this.getCurrentMOName().equals(getMOName(newGroup))) { // switch the groups and if done, finde "Inside" and force redirect if (this.doGroupSwitch(newGroup)) { this.request.getUser().refresh(); this.getHelperService().invalidateNavSession(this.request); // get main MO role IRole newRole = (IRole) ROLEMAP.get(newGroup); INavigationNode entryNode = null; int i = 0; // try to find "Inside" if not found wait 3 seconds and try again up to 3 times while (entryNode == null && i < 3) { try { // find "Inside" node entryNode = this.getMOEntryNode(getMOName(newRole)); } catch (Exception e) { this.response.write("<hr>"); Thread.sleep(3000); } i++; } // if found, redirect to "Inside" if (entryNode != null && i == 1) { this.response.write("script>n"); this.response.write( "window.top.location.replace("/irj/portal?NavigationTarget=" + entryNode.getHashedName() + "&ORG=SWITCH");n"); this.response.write("</script>n"); return true; } else { throw new NoSuchRoleException( "No entry role found for: " + this.getMORoleName(getMOName(newRole))); } } } } return false; }
Find "Inside"
**************
public INavigationNode getMOEntryNode(String mo) throws NamingException, NoSuchRoleException { INavigationNode entryNode = null; if (mo != null && mo.length() > 0) { String moRole = this.getMORoleName(mo); NavigationNodes childs = null; // find navigation node from TLN INavigationNode hgi = this.getHGINode(); if (hgi != null) { this.response.write(hgi.getName() + "<br><br>"); see attachment line 1 childs = hgi.getChildren(this.getEnvironment()); if (childs != null) { INavigationNode child = null; Iterator it = childs.iterator(); // Iterate throu all childs and find main MO role (should always be the fist one) while (it.hasNext() && entryNode == null) { child = (INavigationNode) it.next(); this.response.write(child.getName() + "<br><br>"); see attachment line 2 // if main MO navigaion node found, get "Inside" if (child.contains(moRole)) { entryNode = this.findInsideChildNode(child); if (entryNode == null) { throw new NamingException("NavigationNode: Inside not found!"); } } } if (entryNode == null) { throw new NoSuchRoleException( "MO role not found: " + moRole); } } else { throw new NamingException( "No children found for: " + hgi.getName()); } } else { throw new NoSuchRoleException("role not found!"); } } else { throw new NoSuchRoleException("Parameter mo not defined!"); } this.response.write(entryNode.getName() + "<br><br>"); see attachment line 3 return entryNode; }
Get HGI Node:
*****************
private INavigationNode getHGINode() throws NamingException { INavigationNode hgi = null; NavigationNodes topLvel = this.getService().getInitialNodes(this.getEnvironment()); Iterator it = topLvel.iterator(); while (it.hasNext()) { hgi = (INavigationNode) it.next(); if (hgi .contains("ROLES://portal_content/com.comp/webContent/com.comp.intra.glo.c.main_role/global_intranet")) { return hgi; } } return null; }
Finde "Inside"
****************
private INavigationNode findInsideChildNode(INavigationNode node) throws NamingException { if (node != null) { NavigationNodes childs = node.getChildren(this.getEnvironment()); if (childs != null) { Iterator it = childs.iterator(); INavigationNode child = null; String name = null; while (it.hasNext()) { child = (INavigationNode) it.next(); name = this.getHighesPriorityRoleName(child); name = name.substring(name.lastIndexOf("/") + 1); if (name.toLowerCase().startsWith("inside")) { return child; } } } } return null; }
Any ideas why we have a delay and it sometimes work and sometimes not?
Add a comment