Thursday, July 21, 2011

Custom BPM Applications(InitiableTasks) ADF TaskFlow

In a previous post, we show how to access the initiable tasks in a main method of a simple Java class. In line with, this post demonstrates how to get the task's URL and launch the corresponding generated BPM task details form in an ADF application.


The following are the key methods and artifacts:
  • getTaskDisplayURL() - this method retrieves from a task object, the URL defined in the runtime Human Task configuration of a specific deployed composite, which can be found in Enterprise Manager. The URL is automatically set when you deploy a web app that contains BPM task forms with the configuration - "hwtaskflow.xml" that contains our task definition.
  • getTaskFlowDefinitionId() - this method returns a TaskFlowId object from the lengthy URL returned by the getTaskDisplayURL() method above.
  • initiateTask() - this method that returns a string is used as action attribute in the page fragment. It invokes both methods above then returns a "callTaskDetail" which launches a declarative popup.
  • The declarative pop-up, "modal-dialog-task-flow", is a simple task flow that we reused from the BPM Worklist components library. It doesn't do much but invoke a remote task flow. We could create our own if necessary.
  • wf_client_config.xml - We add this config file to remove from our code the connection details. To get a BPMServiceClientFactory instance, we just passed null parameters as follows:
    factory = BPMServiceClientFactory.getInstance(null, null, null);
  • Configure ADF Security - so we don't need to pass username and password when getting a BPMContext.

Below is the the backing bean that support our page fragment.
package soadev.bpm.web.backing;

import java.net.URLDecoder;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import oracle.adf.controller.TaskFlowId;

import oracle.bpel.services.bpm.common.IBPMContext;
import oracle.bpel.services.workflow.task.model.Task;
import oracle.bpel.services.workflow.worklist.api.util.WorklistUtil;
import oracle.bpel.services.workflow.worklist.servlet.Constants;

import oracle.bpm.client.BPMServiceClientFactory;
import oracle.bpm.services.client.IBPMServiceClient;
import oracle.bpm.services.processmetadata.IProcessMetadataService;
import oracle.bpm.services.processmetadata.ProcessMetadataSummary;

import org.apache.myfaces.trinidad.context.RequestContext;

import soadev.view.utils.JSFUtils;


public class InitiableTaskListForm {
    private IBPMContext bpmContext;
    private ProcessMetadataSummary process;
    private BPMServiceClientFactory factory;

    public InitiableTaskListForm() {
        factory = BPMServiceClientFactory.getInstance(null, null, null);
    }
    public List<ProcessMetadataSummary> getInitiatiableTasks() {
        try {
            // get the process metadata service
            IProcessMetadataService pms =
                factory.getBPMServiceClient().getProcessMetadataService();
            // get the list of initiatable proceses
            return pms.getInitiatableProcesses(getIBPMContext());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    
    public String initiateTask() throws Exception {
        Task task = initiateTask(process.getCompositeDN()+ "/" + process.getProcessName());
        String detailsUrl = getTaskDisplayURL(task);
        getPageFlowScope().put("remoteUserTaskUrl", detailsUrl);
        getPageFlowScope().put("remoteTaskDefId", getTaskFlowDefinitionId(detailsUrl));
        return "callTaskDetail";
    }


    private Map<String, Object> getPageFlowScope() {
        return RequestContext.getCurrentInstance().getPageFlowScope();
    }

    private Task initiateTask(String compositeDN) throws Exception {
        IBPMServiceClient client = factory.getBPMServiceClient();
        return client.getInstanceManagementService().createProcessInstanceTask(getIBPMContext(),
                                                                               compositeDN);
    }

    private String getTaskDisplayURL(Task task) throws Exception {
        Map parameters = new HashMap();
        parameters.put(Constants.BPM_WORKLIST_TASK_ID,
                       task.getSystemAttributes().getTaskId());
        parameters.put(Constants.BPM_WORKLIST_CONTEXT,
                       getIBPMContext().getToken());
        String url =
            WorklistUtil.getTaskDisplayURL(factory.getWorkflowServiceClient(),
                                           getIBPMContext(), task, null,
                                           "worklist", parameters);
        return url;
    }


    //courtesy of http://amulyamishras-tech-blog.blogspot.com/2011/01/opening-remote-http-url-inan-adf-dialog.html

    private TaskFlowId getTaskFlowDefinitionId(String detailsURL) {
        //Checks if the url is null.
        if (detailsURL == null)
            return null;
        //gets the parameter list from the url.
        String parameterList =
            detailsURL.substring(detailsURL.indexOf("?") + 1,
                                 detailsURL.length());
        //tokenizes the url.
        StringTokenizer stok = new StringTokenizer(parameterList, "&");
        String taskFlowId = null;
        String documentName = null;
        //gets the taskflowId from the url.
        while (stok.hasMoreTokens()) {
            String parameter = stok.nextToken();
            String[] parts = parameter.split("=", 2);
            if (parts[0].equals("_id"))
                taskFlowId = parts[1];
            if (parts[0].equals("_document"))
                documentName = parts[1];
        }
        //decodes the encoded url.
        try {
            documentName = URLDecoder.decode(documentName, "UTF-8");
            taskFlowId = URLDecoder.decode(taskFlowId, "UTF-8");

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return new TaskFlowId(documentName, taskFlowId);
    }

    public void setProcess(ProcessMetadataSummary process) {
        this.process = process;
    }

    public ProcessMetadataSummary getProcess() {
        return process;
    }

    private IBPMContext getIBPMContext() throws Exception {
        if (bpmContext == null) {
            bpmContext = (IBPMContext)JSFUtils.getFromSession("BPM_CONTEXT");
        }
        if (bpmContext == null) {
            bpmContext = factory.getBPMUserAuthenticationService().getBPMContextForAuthenticatedUser();
        }
        JSFUtils.storeOnSession("BPM_CONTEXT", bpmContext);
        return bpmContext;
    }
}
The "initiable_task_list.jsff" page fragment:
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:f="http://java.sun.com/jsf/core">
  <af:panelBox text="Applications" id="pb1">
    <f:facet name="toolbar"/>
    <af:panelList id="pl1">     
      <af:forEach items="#{viewScope.initiableTaskListForm.initiatiableTasks}"
                  var="process">
            <af:commandLink text="#{process.projectName}: #{process.processName}"
                      action="#{viewScope.initiableTaskListForm.initiateTask}" id="cl1"
                            useWindow="true"
                            windowModalityType="applicationModal">
          <af:setPropertyListener type="action" from="#{process}"
                                  to="#{viewScope.initiableTaskListForm.process}"/>
        </af:commandLink>
      </af:forEach>
    </af:panelList>
  </af:panelBox>
</jsp:root>

Sample Application

You can get the sample application from this link. The sample application needs to be deployed on a SOA server. On a subsequent post I will demonstrate how to run this sample on the integrated weblogic server.
In the sample, the InitiableTasksProject is deployed as an ADF library so it can easily be reused in other projects/ applications.

Cheers!

47 comments:

  1. Its really good, i have created similar kind of application in my previous web development and design services provider company, but there are few things which we need to improve in that application. But its looks complete one.

    ReplyDelete
  2. Hi Pino,

    Great post!!
    I have just copied BPMApp.zip file and chnaged the wf_client_config.xml with our SOA server details and deployed to SOA server as EAR file.

    I have also created some sample users in jazn-data.xml. How ever, when i try to access http://:/worklist/faces/main.jspx, i got blank page and ins erver logs, i could see below exception...

    ADF_FACES-60098:Faces lifecycle receives unhandled exceptions in phase RENDER_RESPONSE 6 javax.faces.FacesException: javax.servlet.ServletException: OracleJSP error: javax.faces.FacesException: oracle.adf.controller.ControllerException: ADFC-10001: cannot instantiate class 'soadev.bpm.web.backing.InitiableTaskListForm' at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:415) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:44) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:44) at oracle.adfinternal.view.faces.config.rich.RecordRequestAttributesDuringDispatch.dispatch(RecordRequestAttributesDuringDispatch.java:44) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:45) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:45) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:45) at org.apache.myfaces.trinidadinternal.context.FacesContextFactoryImpl$OverrideDispatch.dispatch(FacesContextFactoryImpl.java:268) at com.sun.faces.application.ViewHandlerImpl.executePageToBuildView(ViewHandlerImpl.java:471) at com.sun.faces.application.ViewHandlerImpl.renderView

    Looks like it is not able to initialize the bean class.. Could you help me how to resolve this issue?

    Am i missing something?

    Thanks!!

    ReplyDelete
  3. Hi Pino,

    Sorry abt prev post.. Looks like its a deployment issue. I re generated ADF lib jar for InitiableTasksProject and deployed teh EAR.

    Now i got the Main page but I did not get any task links under "Applications" navigation.

    I have created two users, for whoom, i have tasks assigned in BPM worklist. When i login to standard worklist app with the same user, I could see task list.

    Am I missing something? Pls advise.

    Thanks!!

    ReplyDelete
  4. Hi Pino,

    Our requirement is, we want to display the BPM tasks assigned to a logged - in user in our custom ADF region..

    I tried running the stand alone program(from your prev post) with a sample user, I am getting 0 initible tasks. I have a basic question here.. what is "Initiable Tasks?".. How they differ from normal Human task notifications?

    All we need to do is, fetch the assigned human task notifications and display in a ADF region. Can you help me in achieving that?

    Thanks for your help!!!

    ReplyDelete
  5. Hi Subba,
    Initiable tasks are different from standard task list. Initiable tasks are those deployed BPM processes (applications) that can be initiated by the authenticated user. With regards to your requirement, it is relatively easier, I and will post a blog about it later but until then please check http://download.oracle.com/docs/cd/E21764_01/integration.1111/e10224/bp_worklist.htm#BABDCHEG

    Regards,
    Pino

    ReplyDelete
  6. Pino,

    Thanks for your reply!!
    I tried writing code for getting standard tasklist and the notification detail UI as well.

    However, user wants the same standard BPM worklist UI look and feel with tabular layout etc... The link you have given is to just create a custom region by embedding the standard BPM task list region. Question here is, how can we customize it? to add more columns or hide some of the existing columns?

    Is there a way that we can customize the look and feel of the standard BPM task list region in ADF?

    Please help!!

    Thanks!!
    Subba.

    ReplyDelete
  7. Hi Subba,

    You can pass "displayColumnsList" parameter to the taskList-task-flow-definition. This parameter should be a comma separated string of the columns to be displayed in the task list table.

    Is there a way that we can customize the look and feel of the standard BPM task list region in ADF? If you are asking about skinning, then the answer is yes. BPM task list will inherit the look and feel of the containing page.

    Please try to check also my recent post about using BPM Workspace taskflows inside a custom ADF application on this link: http://soadev.blogspot.com/2011/07/adf-uishell-application-with-oracle-bpm.html

    Regards,
    Pino

    ReplyDelete
  8. Thanks alot pino for reply!!

    I tried with "displayColumnsList" attribute to pass comma separated string. But looks like it accepts only the following values..

    Possible values:

    *

    title
    *

    number
    *

    priority
    *

    assignees
    *

    state
    *

    createdDate
    *

    expirationDate

    It is mentioned in http://download.oracle.com/docs/cd/E21764_01/integration.1111/e10224/bp_portlets.htm#BABCJJAD.

    Basically, we are looking to have "instanceId" and "Application Name" in the display columns and want to enable the filter also. For easy access of the notification to the user.

    In our case we have so many Human Task notifications and a user would have 100's of notifications in his Inbox. So, if we can have "Application Name" as a filter he can easily pull up a particular notification and act on it.

    Customizing I mean, adding more columns to task table. Rest of teh functionality is fine for us.

    Pls help me, if there is a way to customize to display other columns.

    Thanks!!
    Subba.

    ReplyDelete
  9. Hi Pino,

    I have one more question, the standard tasklist task flow region works fine, if we have ADF authentication enabled. Lets say, If we have application not enabled with ADF security then how to pass the workflow context in that case?

    I see a parameter "wfCtxID" .. but i tried passing the workflow context Id for a authenticated user. But it is not working. It is giving below exceptions..

    Caused by: java.lang.NullPointerException
    at oracle.bpel.worklistapp.util.WorklistUtil.getCurrentUser(WorklistUtil.java:507)
    at oracle.bpel.worklistapp.tasklist.beans.view.TaskListTaskFlowParams.setTaskFlowParams(TaskListTaskFlowParams.java:329)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.sun.el.parser.AstValue.invoke(Unknown Source)
    at com.sun.el.MethodExpressionImpl.invoke(Unknown Source)
    at oracle.adf.controller.internal.util.ELInterfaceImpl.invokeMethod(ELInterfaceImpl.java:168)
    at oracle.adfinternal.controller.activity.MethodCallActivityLogic.execute(MethodCallActivityLogic.java:160)

    Could you help me in getting the task-flow work in non-ADF secure applications?

    Thanks for your help!!
    Subba.

    ReplyDelete
  10. Hi Subba,
    "Customizing I mean, adding more columns to task table. Rest of teh functionality is fine for us."
    -You can take advantage of custom views plus the flex-field mapping capability of the standard BPM worklist application. You can create separate views per application and add additional columns coming from the payload into the table using public flex-field.
    Rommel

    ReplyDelete
  11. With regards to the non-ADF secured application, I will try to cover it in a separate blogpost.

    ReplyDelete
  12. Hi Rommel,

    Thanks alot for information!!

    Is there any sample app or link which uses global flex-filed?

    how add custom views to a perticulary application to add flex-field column? any links which explains the same?

    Is there a way that we can programatically add those custom views to taskList task-flow and render them by default ?

    And as asked in other post, can you help me in configuring the wf_client_confg.xml for non-ADF secured applications?

    Once again Thanks alot for your help!!
    Subba.

    ReplyDelete
  13. Hello,

    I would like to know if you can help me on this because I need to reuse some bpm functionallity, like you do here...

    I have a relatively simple process: one task and then some routes that will be executed depending of the outcome of the task. At the final of each route I will call a subprocess.

    When a user is on a task, there is an action menu where the user selects an action. If he clicks on the reassign action, he will choose for whom the task should be reassignes. As far as I know, when the user reassign a task, my process will not continue (because the task is not accomplish yet), right?

    The problem is that I need the funcionality of searching users like the reassign action give out of the box, but I just want it to get the users/groups selected. With that I will later call a subprocess that will be route to the former users/groups. So I need the page but I dont want to reassign the task.

    To achieve this I put a button on the form, and Im calling the same popup the reassign is calling. The popup works, but it seems something is not initailized because the search doesnt give results. Strangly, if I open the popup using the reasign button, close it, and then open the same poup using my button, the search will work... So basically something is missing here..

    After that, I need to get the selected users/groups (in my managed bean for the popup/dialog and then set a process variable (by code) and finally submit the form.

    Do I need to create a custom action for this? How?

    I appreciate any help on this.

    thank you

    fwu

    ReplyDelete
  14. Hi webuser,

    This can be done. I was able to succesfully use such identity browser popup in my custom BPM task form.

    Regards,
    Pino

    ReplyDelete
  15. Can you post here the code snippets of your button and the popup?

    ReplyDelete
  16. Hello Pino,

    I think im talking with you in the oracle forum also :)

    My use case is like this:

    I add this adf button in design time to the task form with a showPopupBehavior:





    Im just pointing to the automatically created reassign popup. I didn´t changed nothing in the reassign popup!

    When I click on the button in run time, the popup will work: I see the popup with the indentity browser on it. However, the search inside the identity browser doesnt return results (maybe is throwing an error, dont know).

    If I go to the automatically built action menu and choose reassign, the popup will open and the search works...

    If I then go to my button again, the search will work... So there is something that the action button is initalizing or something like that that dont happen when I open the popup using my button.

    I dont even talk about the fact that I really dont want to execute the reassign beahvior (just want the searh functionality). So my goal, after be able to search with the identityBrowser, is to delete the action listener (so the reassign will not be executed), and execute my own bean.

    any idea? if you want i can send you my code

    thank you

    fwu

    ReplyDelete
  17. Hi fwu,

    Can you first try to launch the popup programmatically in a managed bean instead of the showPopupBehaviour.
    http://soadev.blogspot.com/2010/02/adf-faces-rc-simple-but-robust.html

    To prevent the user from reassignning the task, I believe you need to create another popup component which could be pointing to the same identityBrowser, but different action listener on the dialog buttons.

    Regards,
    Pino

    ReplyDelete
  18. yes,

    my intenttion is to use another popup with another listner, indeed. So you are saying that my problem is maybe due to the showpopupbehaviour? I will try that other way than.

    But just to let you know, if that works, I will have another big problem: to get the selected users from the identityBrowser control. Any ideas to accomplish this? Is it possible to get a reference to the shuttle in the identityBrowser?

    thank you

    fwu

    ReplyDelete
  19. Hi webuser,

    To get the selectedUsers access the IdentityBrowser model which is in pageFlowScope. Below is how you can access it programmatically:
    IdentityBrowserView identityBrowserView =
    (IdentityBrowserView)getPageFlowScope().get("identityBrowserView");
    List selectedIdentities =
    identityBrowserView.getSelectedIdentities();

    Of course you can use EL like #{pageFlowScope.identityBrowserView.selectedIdentities}

    Regards,
    Pino

    ReplyDelete
  20. Hello,

    Im trying to use your code (to show the popup) exactly as you posted, but im getting this error:

    Target unreachable acctgEntryEditForm returned null

    Im creating a java file inside the Application Sources of my UI project. This java file is not using any package declaration.

    The unique thing I changed was the name of the class, changing "A" to "a" (but I tried with "a" and "A" with the same results).

    Any ideas about this?

    thank you

    ReplyDelete
  21. Hi webuser,
    The acctgEntryEditForm in my case is a backing bean that is specific to my page. You should create another one which is applicable you like for example TaskDetailsBean.java and declare it as managed bean in the task-flow where your taskDetails.jspx view is located.

    Regards,
    Pino

    ReplyDelete
  22. hello,

    I was able to invoke the popup with your code. Unfortunattly, the identitybrowser still doesnt return values on the search... I just put the identity component in the new popup, but it still doesnt return values....

    Do you have any other idea?

    thank you very much

    ReplyDelete
  23. Hello,

    finally I was able to make the popup work. the problem when I copied your code was that for some reason the proprieties of each object didnt get refreshed. So I explicitly set the properties in each box and now the popup works.

    I will try to use you second code to get the users, now.

    thank you again!

    ReplyDelete
  24. Hello again,


    - How do you know the identityBrowser control has this method: getSelectedIdentities(). Where can I see the other methods?

    - I need to set the assignees of other task (in a subprocess) with the selected users in the identityBrowser. For that I was thinking in putting the users I get with your code to a variable and then set this variable to the assignees in the subprocess. However, I dont know how this variable sgould be composed. For instances: with each user/group followed by a semmicolon?

    - Also, after set the value to this variable, I need to submit the task (so my process will continue). for that im usign this code (after the previous code to ger the users form identityBrowser:

    BindingContainer bc = BindingContext.getCurrent().getCurrentBindingsEntry();
    OperationBinding operationBinding = bc.getOperationBinding("submit");
    Object result = operationBinding.execute();

    But then Im getting an error saying that identityBrowserView returns null..

    Can you help me or pointing me on the right direction?

    thank you for your support.

    fwu

    ReplyDelete
  25. Hi webuser
    - How do you know the identityBrowser control has this method: getSelectedIdentities(). Where can I see the other methods?

    >You can find it in you task flow definition. The managed beans including this identityBrowserView are defined there. If you view the source of the task flow, you can control+click on the class name so that JDev will create a stub class that shows the exposed methods of the class.

    - I need to set the assignees of other task (in a subprocess) ...
    >Then you need to put the value you retrieved in the identityBrowserView.getSelectedIdentities() to a variable in your task payload.

    --- Also, after set the value to this variable, I need to submit the task..
    > it seems that you are too far from what you are trying to achieve. The sample code you present doesn't help either. I suggest that you read the developer guides, which are all present JDeveloper help.

    Regards,
    Pino

    ReplyDelete
  26. Hello,

    Im sorry for atill asking you questions, and thank you for your help so far.

    you said:
    "Then you need to put the value you retrieved in the identityBrowserView.getSelectedIdentities() to a variable in your task payload."

    If I drag and drop the variable from the payload to the form I get this binding:
    #{bindings.user.inputValue}

    "user" is my string

    Can you give me an example of how I can set this value in adf/java code?


    Relating to the code I post here, I got it dragging and dropping the submit and update action to the form. Then in the backendbean I get the code.

    So I think that I just would need to put this code in my button. Actually, if my button doesnt have any popup/dialog, it seems to work. The problem is that when I open the dialog (using the same button) I then get the error:

    "target unreachable, "identityBrowserView" returned null.

    I dont have any clue why this is happening because, after clicking OK in the dialog, I dont need the identitybrowser anymore (I already copy the data to my variable), so why there is something trying to find it? Is it the scope where it is declared?

    Do you have any idea?

    I really need help on this :(

    thank you!

    fwu

    ReplyDelete
  27. Hi webuser,
    "Can you give me an example of how I can set this value in adf/java code?"
    -Please see the following from the developers guide: http://download.oracle.com/docs/cd/E14571_01/web.1111/b31974/web_adv.htm#CACIDGAD

    So in your case, you may have:
    JUCtrlAttrsBinding user= (JUCtrlAttrsBinding)bindings.findNamedObject("user");
    user.setAttribute("user", "your_user_values_here_from_identity_browser");

    But there are already ulitity methods to simplify the code above. Try searching for ADFUtils in the forum. As a sample usage of this ADFUtils, see the following code from Andrejus blog: http://4.bp.blogspot.com/_OSq71i5oy0c/TMk1rMVFg9I/AAAAAAAAEbM/9-ibTD9ycHA/s1600/21.png
    located in: http://andrejusb.blogspot.com/2010/10/initializing-oracle-bpm-11g-process.html

    "? Is it the scope where it is declared?"
    --As I said, it is declared in the task flow where your taskDetails page is contained.

    ReplyDelete
  28. hello Pino,

    I tried this code to set the variable value:

    import oracle.adf.model.BindingContext;

    BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();


    JUCtrlAttrsBinding user= (JUCtrlAttrsBinding) bindings.get("user");
    user.setAttribute("user", "testuser");

    Please note that Im not usign the method "findNamedObject", because I get the message it doesnt exists. So im using the "get" method, and maybe this is my problem.

    Can you tell me why I dont have that method. Is it the import Im using?

    I then tried to use the ADFUtil, but I cant find an example to set the bindings of a variable.

    If I drag the payload field to the user form, the binding I get is this: #{bindings.user.inputValue}

    So, if I need to use the ADFUtils, can you tell me how to use this el expression?

    Again, thank you for your patience and support.

    fwu

    ReplyDelete
  29. Hello,

    Just to let you know that I follow your ling, but the problem is that Im using a different ADFUtils. Now I used the one in the link you gave me and in the ok button of the dialog Im making this:

    ADFUtils.setBoundAttributeValue("user", "testuser");

    But no luck with that :(

    What can I be doing wrong? The scoope of my bean to control de ok button of the dialog is now "request". Can be this the problem?

    thank you.

    fwu

    ReplyDelete
  30. hello Pino,

    Im doing this code (similar to yours):

    DCBindingContainer bc = (DCBindingContainer)FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{bindings}", BindingContainer.class);
    JUCtrlAttrsBinding dc = (JUCtrlAttrsBinding) bc.findNamedObject("user");
    dc.setInputValue(selectedIdentities.toArray());
    fc.addMessage(null, new FacesMessage

    (FacesMessage.SEVERITY_ERROR, "::: type ::" + dc.getAttributeValue().toString(), null));

    The last message displays the value I set to the variable. So, this code should be working.

    However, when I go to Enterprise manager and look at the instance of the task that left the activity, my values are not being passed on the xml :(

    Do you have any idea of what can be wrong?

    I dont understand why if I drag the field to my form and write something on it (it will have this bind: #{bindings.user.inputValue}) the value is being passed, but if I make that code, even seeing that the value was actually changed), the value is lost somewhere.... like if it is not committed.

    Do you have any idea about why this happens?

    thank you

    fwu

    ReplyDelete
  31. Hello Pino,

    Im really sorry to post so much messages, but, I realize that if I put that code in a bean in a button that is in the task form, the variable is set. However, in a bean related to a dialog, the variable get set but for any reason it is lost after. So this must be a scope situation, right?

    But in that way I still dont know how to be able to acomplish this in the event of a dialog/popup method.

    any idea?

    thank you

    ReplyDelete
  32. Hi webuser,
    This is not a scope issue because the binding container has its own internal scope. The problem is the operation being made after the value was set that should trigger an update to the task.
    Are you sure that it woks on a regular button and not on a dialog button? Please confirm by having another test. If indeed it works, post here the whole action listener code (you call bean code).
    Pino

    ReplyDelete
  33. Hi Pino,

    The following code is the code from my button. But the code from the dialog is exactly the same.

    Im pretty sure it works, because Im looking to the xml of the activity in EM. I even deployed the process again.

    Im not getting much luck with dialogs :(

    import javax.faces.application.FacesMessage;
    import javax.faces.context.FacesContext;

    import oracle.adf.model.binding.DCBindingContainer;

    import oracle.binding.BindingContainer;

    import oracle.jbo.uicli.binding.JUCtrlAttrsBinding;

    public class buttonteste {
    public buttonteste() {
    }

    public String setvalues() {
    // Add event code here...

    DCBindingContainer bc = (DCBindingContainer)FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{bindings}", BindingContainer.class);
    JUCtrlAttrsBinding dc = (JUCtrlAttrsBinding) bc.findNamedObject("user");
    dc.setInputValue("TestUser".toString());
    // fc.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "::: type ::" + dc.getAttributeValue().toString(), null));

    return null;
    }
    }

    ReplyDelete
  34. Hi webuser,
    Since your sure that it works using normal button, then I suggest you try putting code inside a dialogListener like as follows:
    public void handleIdentityBrowserDialogReturn(DialogEvent ev) {

    if(ev.getOutcome().equals(DialogEvent.Outcome.ok)) {
    //put relavent code here...
    }
    }
    Remove the buttons in your dialog and set the dialogListener property of the af:dialog to point to the method above like as follows:
    <af:dialog id="d3" type="okCancel"
    dialogListener="#{your_bean.handleIdentityBrowserDialogReturn}">
    <wlc:identityBrowser .../>
    </af:dialog>

    Pino

    ReplyDelete
  35. hello Pino,

    My first approach (the one Im trying to accomplish) is build exactly with a dialoglistner. In the dialogListner property Im pointing to a bean where Im executing that same code. And then doesnt work...

    I just dont understand what you mean about "remove the buttons in your dialog", because without buttons how the code will be executed?

    Did I understood wrong your words?

    thank you
    fwu

    ReplyDelete
  36. Pino,

    just let me explain one more thing. The button where the code works is not in the dialog. That button is in the task form itself. That is the difference Im talking about. Everything else is exactly the same.

    So, for any reason, if I run that code in a bean associated with an object in the form, that works, but running that code in dialogs, doesnt work.

    thank you

    fwu

    ReplyDelete
  37. Hi webuser,
    "because without buttons how the code will be executed?" - The code will be executed in the DialogListener (not ActionListener). The "YesNo" dialog type will have two buttons even if you remove your custom buttons.

    "if I run that code in a bean associated with an object in the form, that works, but running that code in dialogs, doesnt work." -- Sorry, but I cant really comment on this one.

    Regards,
    Pino

    ReplyDelete
  38. Hi Pino,

    Unfortunatly, that is what Im already doing :( I always used a dialog listner.

    fwu

    ReplyDelete
  39. Hi Pino,

    thank you for sharing this article: i found it very useful. Please, let me ask you a couple of questions about it. Thanks to your suggestions and other material i found on the web, I successed in realizing a traditional Fusion Web App able to remotely open BPM human task forms in an inline-frame (or pop-up or whatever...). Basically i successed in doing something very similar to what the picture in your article shows (open a dialog with inside a BPM human task form). Anyway, i'm encountering the following problem: wherever i close any of the task forms approving or rejecting the task, the task is pushed forward in the BPM process, but the task form remains opened in the browser and i get the following error:

    Caused By: java.lang.NullPointerException
    at oracle.bpel.services.workflow.worklist.adf.ADFWorklistBeanUtil.getURLTORedirect(ADFWorklistBeanUtil.java:416)
    at oracle.bpel.services.workflow.worklist.adf.InvokeActionBean.getParentURL(InvokeActionBean.java:1048)
    at oracle.bpel.services.workflow.worklist.adf.InvokeActionBean.invokeScript(InvokeActionBean.java:1063)

    By investigating the matter, i discovered the problem was i didn't provide the "parentURL" parameter to the task flow in the hash map passed to the getTaskDisplayURL method, but even if i provide that parameter the human task form doesn't close itself which is quite annoying. I even tried to pass the "bpmBrowserWindowStatus" parameter with value "close" or "keep", and in that case i get no error but the browser shows an error pop-up with no message and the task form keeps to stay open: arrrrrghhh!!!
    Do you have any clue on this behavior?

    Thanks,
    Fabio.

    ReplyDelete
  40. Hello Digit,
    Have you resolved your problem?
    I have same problem
    Please contact me at javistcg@gmail.com
    Thanks

    ReplyDelete
    Replies
    1. Hi is this issue resolved, i am facing the same issue, i have passed the ParentURL but on click of any action, its getting updated in the task but page redirecting to 404 error.

      Please help.

      Delete
  41. i took checkout of code and without doing any changes deployed it.

    Getting below error.

    [02:34:38 PM] ---- Deployment started. ----
    [02:34:38 PM] Target platform is (Weblogic 10.3).
    [02:34:39 PM] Retrieving existing application information
    [02:34:39 PM] Running dependency analysis...
    [02:34:39 PM] Building...
    [02:34:49 PM] Deploying profile...
    [02:34:49 PM] #### Deployment incomplete. ####

    ReplyDelete
  42. Hi Rommel

    i am trying to run above code in my jDeveloper & i'm getting following java exception stack trace:
    Exception in thread "main" java.lang.NoClassDefFoundError: oracle/bpm/casemgmt/client/ICaseManagementServiceClient
    at com.wft.uep.Fixture.getBPMServiceClientFactory(Fixture.java:29)
    at com.wft.uep.Fixture.getBPMServiceClient(Fixture.java:45)
    at com.wft.uep.GetProcessInstances.testGetProcessInstances(GetProcessInstances.java:26)
    at com.wft.uep.GetProcessInstances.main(GetProcessInstances.java:21)
    Caused by: java.lang.ClassNotFoundException: oracle.bpm.casemgmt.client.ICaseManagementServiceClient
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 4 more

    i don't know where to find oracle.bpm.casemgmt.client.ICaseManagementServiceClient class can you please help me on this.

    ReplyDelete
  43. Hi,
    Thank a lot for sharing this post :)

    I have already implemented a customized worklist and I used a sample code -like what you did present here- in my worklist. it shows the list of applications for the user and initiates applications well.

    But I have still an unsolved task which is opening assigned task's form.
    I am just able to get detailed information of the task, but I am not able to generate appropriate link to open humantask's form.

    I used your "getTaskDisplayURL(task)" method to generate a link to open assigned task, but it did not generate a valid url to open the humanTask's form.
    this is a sample one: "http://rfh-ptc-uat-ws:7003/workflow/Project1/faces/adf.task-flow?_document=WEB-INF%2FHumantask1_TaskFlow.xml&parentURL=http%3A%2F%2FRFH-PTC-UAT-WS%3A7003%2Fworklist&bpmWorklistContext=f44adbb2-b0f6-475f-bcf2-4a2b448d62df%3B%3BVZROoLhY4hm1mZZ%2FJwCHmxMkivxpBYlB7V98jmo4UVDSnGoV%2FXYp8x5%2FVGrVVL0mud2jA4APbIKgA6br37NB%2FhjAhFQhpJUTTJu%2BwPjfspLNVq1QPgRnY6gfVJFlY%2BS5QohskySbooH9U8DOAsfWKQqDnShq10D6OnHaNCMAoNhGXswRa8GxlynokOVS9ZiuS4znIsV3730wUOq55x1SemFAUK8VMFjUXDYcnGkyWcmqVQ%2Fl1lB4Ofga47a99qCb&bpmWorklistTaskId=TestEnglish&_id=Humantask1_TaskFlow&_afrLoop=1303713189363704&_afrWindowMode=0&_afrWindowId=bp_workflow"

    How can I generate the link ?
    Would you help me out please ? :)

    Regards,

    ReplyDelete
  44. You will need these two jars
    \Oracle_SOA1\soa\modules\oracle.bpm.runtime_11.1.1
    - oracle.bpm.casemgmt.interface.jar
    - oracle.bpm.metadata-interface.jar

    ReplyDelete
  45. HI, Pino
    There is a problem bothering me, how to get the task operation page/url in workspace
    I'm not sure whether this method can, WorklistUtil getTaskDisplayURL (factory. GetWorkflowServiceClient (), getIBPMContext (), task, null, "worklist", the parameters).
    You only instruction how to init a task of process,I want to more,Thanks!

    ReplyDelete
  46. "I'm not sure whether this method can, WorklistUtil getTaskDisplayURL (factory. GetWorkflowServiceClient (), getIBPMContext (), task, null, "worklist", the parameters)."

    Why not try?

    Cheers

    ReplyDelete