WebCenter: af:commandLink or af:goLink for Navigation

Introduction

In a previous post, which describes how to suppress the (ADF based )session time out popup from appearing, there was also a recommendation on how to enable navigation after the current user session had expired (timed out). In addition, the post included a side note, which describes the benefit of using an af:golInk as the navigation link.  This post will further emphasize this recommendation of using af:goLinks instead of af:commandLinks for ALL WebCenter based navigation, where the navigation is based on the WebCenter navigation model.

Main Article

To demonstrate why it is better to use an af:goLink, the following use case from a sample application will be used.  The sample application consists of the (default) home page, plus 3 other pages.  The default navigation model will be used with all four (page) links added.

comLinksOrgoLinks_a

 

The menu UI that will expose the links have been implemented in two different ways: as af:commandLinks, and as af:goLinks:

ATEAM recommends using af:iterator instead of af:forEach to stamp out UI components. While the <af:forEach> might be sufficient for most user’s needs, it does not work with a JSF DataModel, or CollectionModel. It also cannot be bound to EL expressions that use component-managed EL variables (such as the “var” variable on an <af:table>).  In addition, an af:forEach is less performant as it will generate a UI component for every iteration and must search the component tree in order to generate the unique id.  The <af:iterator> tag was created to address these issues.

<af:iterator var="node" varStatus="vs"
   value="#{navigationContext.defaultNavigationModel.listModel['startNode=/, includeStartNode=false']}"
id="iterator1">
   <af:spacer width="10" height="10" id="spacer2"/>
   <af:goLink id="pt_gl1" text="#{node.title}"
      destination="#{node.goLinkPrettyUrl}"
      targetFrame="#{node.attributes['Target']}"
      inlineStyle="font-size:small;#{node.selected ? 'font-weight:bold;' : ''}"/>
</af:iterator>
<af:iterator var="node" varStatus="vs"
   value="#{navigationContext.defaultNavigationModel.listModel['startNode=/, includeStartNode=false']}"
id="iterator2">
   <af:spacer width="10" height="10" id="spacer4"/>
   <af:commandLink id="commandLink1" text="#{node.title}"
      inlineStyle="background-color:white;font-size:small;#{node.selected ? 'font-weight:bold;' : ''}"
      action="pprnav" disabled="#{not node.navigable}"
      actionListener="#{navigationContext.processAction}"
      clientComponent="#{node.attributes['Target'] == '_popup' ? true : false}">
      <!-- pass node to processAction for setting current selection and navigation  -->
      <f:attribute name="node" value="#{node}"/>
   </af:commandLink>
</af:iterator>

The following is the simple test use case:

  • Launch the portal.  The custom portal will navigate to the default HOME page
  • Remain idle for the <session-timeout>, which as been set to 5 minutes
  • Once session has timed out, click on Page 1 navigation link

The expected outcome is that Page 1 will be displayed.

The custom (servlet filter) code that enables the navigation after time out can be found here.

To assist in describing what is happening behind the scenes, additional logging has been added to the servlet filter code.

The first test will involve using the af:commandLink(s).  The application is launched.  Note that the URL in the browser shoes wcnav_defaultSelection, which basically will redirect to the HOME page.  In addition, note the adf.ctrl-state URL parameter = 4pqh1ybck_4:

comLinksOrgoLinks_1

The log file reports the following:

Target URL — http://127.0.0.1:7101/SessionTimeOut-Portal-context-root/index.html
requestedSession : YrHgSwJXmssFpLNwdh4PFkLJpMcnZQxkYbX1tqTnzJsyk5y8zyTW!1245085276
currentWebSession : 1YxhSwLQXCgCRmJRnvLw8LmFTbRsp29CFx0FwlrK893QJsTLJkGS!1543679928!1378929424684
requestURI : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
currentWebSession == requestedSession? : false
redirecting to : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
Expiry time :Wed Sep 11 13:02:04 PDT 2013
***********************
requestedSession : 1YxhSwLQXCgCRmJRnvLw8LmFTbRsp29CFx0FwlrK893QJsTLJkGS!1543679928!1378929424684
currentWebSession : 1YxhSwLQXCgCRmJRnvLw8LmFTbRsp29CFx0FwlrK893QJsTLJkGS!1543679928!1378929424684
requestURI : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:02:04 PDT 2013
***********************
requestedSession : 1YxhSwLQXCgCRmJRnvLw8LmFTbRsp29CFx0FwlrK893QJsTLJkGS!1543679928!1378929424684
currentWebSession : 1YxhSwLQXCgCRmJRnvLw8LmFTbRsp29CFx0FwlrK893QJsTLJkGS!1543679928!1378929424684
requestURI : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:02:04 PDT 2013

After waiting the allotted time for time out (Expiry time = 5 minutes), the commandLink for PAGE1 is selected.  Once the browser refreshes, notice that the adf.ctrl-state has been updated from 4pqh1ybck_4 to h4lur7wj_4, so a essentially the framework has established a new session.  But also notice the URL, as it still displays the previous URL:

comLinksOrgoLinks_2

And from the log.  Notice that it detected the session change, but the requested URI is still home:

requestedSession : 1YxhSwLQXCgCRmJRnvLw8LmFTbRsp29CFx0FwlrK893QJsTLJkGS!1543679928
currentWebSession : Dcb4SwNSLKLRJWc89RJ76dvYLrVQdCc2kh8ffSnQG10pMGh7PWz6!1543679928!1378930130164
requestURI : /SessionTimeOut-Portal-context-root/faces/home
currentWebSession == requestedSession? : false
redirecting to : /SessionTimeOut-Portal-context-root/faces/home
Expiry time :Wed Sep 11 13:13:50 PDT 2013
***********************
requestedSession : Dcb4SwNSLKLRJWc89RJ76dvYLrVQdCc2kh8ffSnQG10pMGh7PWz6!1543679928!1378930130164
currentWebSession : Dcb4SwNSLKLRJWc89RJ76dvYLrVQdCc2kh8ffSnQG10pMGh7PWz6!1543679928!1378930130164
requestURI : /SessionTimeOut-Portal-context-root/faces/home
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:13:50 PDT 2013
***********************

Now the same test will be done using goLinks.  Upon launching the application, the URL reports the same and the adf.ctrl-state = 8imz43w44_4:

comLinksOrgoLinks_3

From the log:

requestedSession : Dcb4SwNSLKLRJWc89RJ76dvYLrVQdCc2kh8ffSnQG10pMGh7PWz6!1543679928
currentWebSession : gdXZSwPVhzdnvWJhppxmQQgyLTbWdWrZ3WNnCT152wNzth2s2ZhJ!1543679928!1378930485365
requestURI : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
currentWebSession == requestedSession? : false
redirecting to : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
Expiry time :Wed Sep 11 13:19:45 PDT 2013
***********************
requestedSession : gdXZSwPVhzdnvWJhppxmQQgyLTbWdWrZ3WNnCT152wNzth2s2ZhJ!1543679928!1378930485365
currentWebSession : gdXZSwPVhzdnvWJhppxmQQgyLTbWdWrZ3WNnCT152wNzth2s2ZhJ!1543679928!1378930485365
requestURI : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:19:45 PDT 2013
***********************
requestedSession : gdXZSwPVhzdnvWJhppxmQQgyLTbWdWrZ3WNnCT152wNzth2s2ZhJ!1543679928!1378930485365
currentWebSession : gdXZSwPVhzdnvWJhppxmQQgyLTbWdWrZ3WNnCT152wNzth2s2ZhJ!1543679928!1378930485365
requestURI : /SessionTimeOut-Portal-context-root/faces/wcnav_defaultSelection
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:19:45 PDT 2013
***********************

After waiting the allotted time for time out (Expiry time = 5 minutes), the af:goLink for PAGE1 is selected.  Notice that unlike commandLink, the browser URL is (correctly) pointing to desired PAGE1 destination and also adf.ctrl-state has been updated from 8imz43w44_4 to ef9fnhwal_4:

comLinksOrgoLinks_4

The log further proves this fact:

requestedSession : gdXZSwPVhzdnvWJhppxmQQgyLTbWdWrZ3WNnCT152wNzth2s2ZhJ!1543679928
currentWebSession : zp1BSwQDcKDv1Bd7nZTChvwTgjCQnW31sJSrJnWvHpyNS9Gpg4v0!1543679928!1378930819789
requestURI : /SessionTimeOut-Portal-context-root/faces/Page1
currentWebSession == requestedSession? : false
redirecting to : /SessionTimeOut-Portal-context-root/faces/Page1
Expiry time :Wed Sep 11 13:25:19 PDT 2013
***********************
requestedSession : zp1BSwQDcKDv1Bd7nZTChvwTgjCQnW31sJSrJnWvHpyNS9Gpg4v0!1543679928!1378930819789
currentWebSession : zp1BSwQDcKDv1Bd7nZTChvwTgjCQnW31sJSrJnWvHpyNS9Gpg4v0!1543679928!1378930819789
requestURI : /SessionTimeOut-Portal-context-root/faces/Page1
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:25:19 PDT 2013
***********************
requestedSession : zp1BSwQDcKDv1Bd7nZTChvwTgjCQnW31sJSrJnWvHpyNS9Gpg4v0!1543679928!1378930819789
currentWebSession : zp1BSwQDcKDv1Bd7nZTChvwTgjCQnW31sJSrJnWvHpyNS9Gpg4v0!1543679928!1378930819789
requestURI : /SessionTimeOut-Portal-context-root/faces/Page1
currentWebSession == requestedSession? : true
session is OK
Expiry time :Wed Sep 11 13:25:19 PDT 2013
***********************

As you can see using an af:commandLink in this use case scenario will have issues with navigation after a session time out.  Moreover, the general usage for af:commandLinks is for pure ADF applications where the navigation is basically defined in the adfc-config.xml.  WebCenter apps are different in that regard, so this is why ATEAM always recommend af:goLinks for WebCenter based custom applications.

Comments

  1. Vinodh Kumar Ramadoss says:

    ” WebCenter apps are different in that regard, so this is why ATEAM always recommend af:goLinks for WebCenter based custom applications.”

    But if we have to do Action Processing and set parameters for this action, how will we handle that with goLinks?

    If I read this right, is it saying that we should NEVER use for Webcenter Navigation. What if I want the PPR smooth navigation that commandLink gives. And again what if I want to do action processing before navigation?

Add Your Comment