Tuesday, July 26, 2016

Oracle Workflow Tips and Tricks - hide default action history and show custom action history, customizing notifications, hiding buttons, recall functionality

I am here by going to discuss on a few of the tricks and scenarios related to Oracle Workflow. If you think we cannot do much with the limitations of the workflow then you are going wrong. There are ways we can play with a workflow notification. 

(1) Hide default Action History and show your custom Action History region

 At times you feel like hiding default Action History region and show your own action history from your custom table in OAF region being displayed inside Workflow message. There are two ways you can do that:

(a) In OAF region controller : You can use the below lines to hide Oracle default Action History        region:

        OAWebBean rootWebBean = pageContext.getRootWebBean();
        //Don`t show standard action history region in notification
        OAStackLayoutBean ntfHistoryRN =                     (OAStackLayoutBean)rootWebBean.findIndexedChildRecursive("NtfHistoryRG");
        if(ntfHistoryRN != null)
(b) #HISTORY item attribute : You can add an attribute with internal name #HISTORY in your message and then you can specify the value to point to required OAF region which will be displayed in notification instead of Action History region. You can pass parameters as well in your URL. Example - JSP:/OA_HTML/OA.jsp?OAFunc=XXXX_ACTION_HIST_RN-&pRequestId=-&REQUESTID


(2) Hide custom buttons coming through lookup

If you are thinking about hiding default workflow buttons like Reassign or More Info, no I am not talking about them here. Hiding them has been documented in so many places – you just need to add an ATTRIBUTE with internal name #HIDE_REASSIGN or #HIDE_MOREINFO in your workflow message with value as “Y”. It is shown in the figure below:

I am here going to talk about other buttons which come up in your workflow notification through a lookup defined in workflow process as shown below:

Now obviously when the above notification goes to any user he will see 1  button – Submit.
This is a notification which goes to the user when the approver returns it for correction back to the employee. Now I don`t want employee to submit the notification from notification itself, rather I want employee to be redirected to my custom page and there he will do all necessary actions and finally submit back the request.

To do this we need to hide the Submit button and create a new button for redirection. This can be done in two ways:

       a.            (a) In OAF region controller: You can use the below lines to hide button coming from lookup and then create a new button to redirect to your custom page:

OATableLayoutBean pgBtnBarBean =  (OATableLayoutBean) rootWebBean.findChildRecursive("pgBtnBarTbl");
OARowLayoutBean stdRowLayout = (OARowLayoutBean) pgBtnBarBean.getIndexedNodeList().getUINode(pageContext.getRenderingContext(), 0);
// Render the row containing buttons to false

// Create a new button and add it in Page Button Bar
OARowLayoutBean rowLayoutBean = (OARowLayoutBean)createWebBean(pageContext,               OAWebBeanConstants.ROW_LAYOUT_BEAN);
OAButtonBean buttonBean = (OAButtonBean)createWebBean(pageContext, OAWebBeanConstants.BUTTON_BEAN);
buttonBean.setText("Update Request");
buttonBean.setShortDesc("Update Request");
// request_id parametet being passed from workflow
String request_id = pageContext.getParameter("request_id");
buttonBean.setDestination("OA.jsp?page=/oracle/apps/xx/abc/webui/TestPG&action=update& request_id ="+ request_id);
      b.            (b) Extending NtfDetailsControlsCO: Second way to achieve the same requirement is by extending NtfDetailsControlsCO and hide the buttons in the processRequest of your custom controller:
 public class xxhrTLMNtfControlsCO extends NtfDetailsControlsCO      
 // Oracle creates the buttons from lookup with IDs as RR0, RR1 and so on      
 OAButtonBean oabuttonbean1 = (OAButtonBean)oawebBean.findChildRecursive("RR0");
 if(oabuttonbean1 != null)

Now you can create a new button same as shown in 2(a)
You have to make sure to personalize the Notification Page( Page Button Bar) at function level and put your new controller as shown below:

In your custom page when employee is clicking on programmatically created button you need to give correct result as per your lookup type so that it follows the next activity in the workflow:

wf_notification.SetAttrText(lv_ntf_id, 'RESULT', 'SUBMIT');
wf_notification.Respond(lv_ntf_id, NULL, lv_responder,

(3) Recall functionality:

One of the biggest challenges related to workflows is user does some mistake while submitting the request and he wants it to be recalled so that he can resubmit it. To achieve this functionality we can have an extra link <Default> from our Approval Notification. We can have a recall button in our custom page which gets enabled once the user submits the request. Once the requester clicks on Recall button, in the code we need to get hold of the current notification which is pending on the approver and respond to it with Result Recall. As a result it will follow the <Default> path as shown in the workflow below and a Recall notification is sent to the requester. 

A sample workflow showing all different actions

    I hope the above functionalities will be helpful to the developers. Please drop a comment if you have any query on the above.

    Thanks to my colleague Manish Goel from whom I learnt Oracle Workflow recently and to Munish Narang whose code has been very helpful.



    1. Gr8 work Deepak, If possible can you share your code.
      Email id: pvrmsc@gmail.com

      1. Most of the code and directions are already there. Let me know if you have any query.

    2. could you please explain more regarding Return for correction functionality ? how we can achieve it in custom WF ?

      1. When an approver clicks on return for correction, it calls a function which in turn sets requester as current performer and then sends RFC notification to requester.
        Now there can be two ways - either you want requester to take action on the same notification or you want to hide workflow buttons and programatically put a button in your OAF region clicking on which the requester is directed to another page. The requester finally clicks on submit and in your code you will have to retrieve the notification and respond it with the requester`s action so that it again moves to the next approver.

    3. Hello Deepak,
      I have a requirement in which I need to default the Update Installment Rule and Update Revenue Rule to in Notification page,so that user will not fill anything and can proceed further. Could you please help me out in this.
      I am trying to extend NtfDetailsResponseCO.
      Will be grateful if you please respond to my query.


      1. HI Anwesha,

        Default the Update Installment Rule and Update Revenue Rule? Can you explain more on this?

        I am not sure which page you are customizing and if possible you can email me your exact requirement at deepak.jain@yahoo.co.in with screenshots.


      2. You can extend NtfDetailsResponseCO and do it. You can retrieve those message choice and set the values after super.processRequest().

        But make sure you do it at function level and the function should be the same one which is being used inside this notification to show oaf region.

      3. Hello Deepak,

        Thank you so much for your response.I am extending the CO but facing some difficulty in retrieving the message choice.
        Request to please suggest how can i get hold of the message choice.
        The message choice is getting created programmatically and so I am very confused.Please find the below code for message choice creation in seeded NtfDetailsResponseCO class:

        if ("LOOKUP".equalsIgnoreCase((String)object4)) {
        string8 = (OAViewObject)oAApplicationModule.findViewObject("LookupCodesVO" + j);
        if (string8 == null) {
        string8 = (OAViewObject)oAApplicationModule.createViewObject("LookupCodesVO" + j, "oracle.apps.fnd.wf.worklist.server.LookupCodesVO");
        Serializable[] arrserializable4 = new Serializable[]{object3};
        if (bl2) {
        string8.invokeMethod("initQueryDigSig", arrserializable4);
        } else {
        string8.invokeMethod("initQuery", arrserializable4);
        string9 = (OAMessageChoiceBean)this.createWebBean(oAPageContext, "MESSAGE_POPLIST");
        string9.setUINodeName("NRR" + j);
        string9.setListViewObject(oAPageContext, (ViewObject)string8);
        string10 = (String)oARow.getAttribute("TextValue");
        string9.setSelectionValue(oAPageContext, string10);