Java CAPS Tip: Simple Visual Web Pack Implementation of the Work List Manager GUI

Following on for my previous Java CAPS Tip on Integrating Work List Manager with Sun DSEE 6.x , found here, I will further extend the concept and illustrate how we can now build a simple Visual Web Pack (VWP) based application that allows the user to View, Accept, Reject or Escalate tasks created by a simple Workflow application. As with all example it is intentionally kept simple although I hope it provides enough information for the reader to expand upon. This posting assumes you have read the previous and if following them through implement / configure your system to work with DSEE and if not please read the previous posting.

Resources

A simple Java CAPS eInsight based Workflow

As stated previously this process has intentionally been kept simple. We will trigger the workflow business process using a simple file, it does not matter what the content is we will simply display it, and we will provide a simple summary in the Worklist Manager (WLM) flexString1. The example Java CAPS project can be download from here.
  1. Create a new Project
  2. Create a new Business Process bpWLM as below.

    bpWLM

    The key component of this Business Process is the WLM API User Activity which will cause the BP to be suspended until the WLM activity is completed.
  3. In the first Business Rule Map the content of the File to the WLMTask Input and a simple static String to the Flex String1

    Business Rule 1

  4. The User Activity can be configured by Right-Clicking on it and editing the properties and selecting Assignments Tab. You will need to connect to your DSEE instance and then select a number of users or group to assign the task to.

    DSEE CoonnectionAssignment

  5. The second Business rule should be modified to copy the content of the WLM Task output to the file write.

    Business Rule 2

  6. You should not create an environment configuring the WLM external to match that define in the previous article build a connectivity map and then deploy to your integration server.

    Connectivity Map

Simple Visual Web Pack Application

Now that we have built and successfully deployed the Simple JavaCAPS application we will build a VWP based GUI that provides user Login, Task List and Task View screens. The example NB project export can be found here. Although the example project contains some additional functionality not described here, because it is not necessary for the example, the code gives possible layout examples. The step require to implement the three screen example as as follows. Where appropriate notes will be added to highlight certain features and key areas.
  1. Before we can attempt to build the application we must first import our WorkflowServiceClient.jar file create in the previous article. This is done, within NetBeans, by selecting Services Tab->Enterprise Beans(2.x)->Right-Click->Add Set of Session EJBs. This will allow you to import and configure the interface to the EJB.

    Add WorkflowServiceClient.jarConfigure WorkflowServiceClient.jar

    In the second Wizard page you will notice that a number of the methods are highlighted with a warning and we will need to configure the return types for these as follows:
    1. getAllSubordinates - java.lang.Object
    2. getAuditHistory - java.lang.Object
    3. getDistinctValues - java.lang.Object
    4. getGroups - java.lang.Object
    5. getManagers - java.lang.Object
    6. getTasks - com.stc.bpms.wlm.model.Task
    7. getTasksForUser - com.stc.bpms.wlm.model.Task (This method exists twice)
    8. getUserActivities - java.lang.Object
    9. getUserRoles - java.lang.Object
  2. Now we can create a new Web project (WorkListManager)
  3. We now create, rename the default Page1, a Login Page that contain simply a username TextField, a password PasswordField and a button.

    Login PageEJB Methods

    Behind the Login button we will need to call the authenticateUser method of the ejb. Before editing the code drag the authenticateUser method from the previously imported EJB on to the page and this will cause NetBeans to import the appropriate jars so that the project may be built. Within the SessionBean we should create a username property and bind the display usernameTF to this property. We will use the value within the SessionBean throughout the project. Once this has been do the following should be added to Login Button.

        public String loginBtn_action() {
            String logon = null;
            FacesContext context = getFacesContext();
            String username = usernameTF.getValueAsString(context);
            String password = passwordPF.getValue().toString();
            try {
                if (workflowServiceClient.authenticateUser(username, password.toCharArray())) {
                    logon = "logon";
                    log("\*\*\* APH-I1 Login Successfull";);
                    // Get User Display Preferences
                    SqlTimestampConverter converter = (SqlTimestampConverter)getSessionBean1().getTimestampConverter();
                    converter.setDateStyle("long";);
                    getSessionBean1().getTimestampConverter();
                } else {
                    warn("Invalid Username / Password";);
                    log("\*\*\* APH-I1 : Invalid Username / Password";);
                }
            } catch (Exception e) {
                Logger.getLogger(LogonPage.class.getName()).log(Level.SEVERE, "Logon Exception", e);
                error(e.getMessage());
            }

            return logon;
        }

    The authenticateUser will return true if the user exists and is able to logon. Once successfully logged in the page should navigate to the TaskListPage.

    Page Navigation

  4. The TaskList Page should be created and a Table dragged on to the canvas. Once this has been done we will need to drag the appropriate getTasksForUser method onto the Page. You can identify which is the appropriate version of the method by hovering over it with the mouse and look at the tool-tip. The method we require contains only two input parameters. Once this has bee done we will need to associate the Table with the defined Data Provider. THis can be done by selecting the Table Properties and then selecting the workflowServiceGetTasksForUser data provider. Select the Priority, Status, Start Date, Assigned To, flexString1 fields so they are displayed and then add three additional columns that should be defined as Buttons with the following text View, Escalate and Accept. Select Ok and the table will be displayed.

    Note:
    For some reason within the current release of NetBeans you are unable to go back into the Table Layout option because NetBeans fails to refresh the Data Providers. If you need to do any changes you will have to do it using the Page Navigator.

    In addition when importing the EJB you may notice that the classes created for the getTasksForuser method have different names to those in my example export. My export has WorkflowServiceGetTasksForUser2 for the name of the 2 parameter method. If this does occur then simply change the name of the imported class an all references. This seems to be a feature of the EJB import process.

    Because the getTaskForUser Method requires two input parameters we need to modify the preprocess and prerender methods to set these correctly so that when the page is display the tasks for the logon user will be displayed. To facility this we will need to modify the methods as follows:

        public void preprocess() {
            defineTaskFilter();
        }
        public void prerender() {
            defineTaskFilter();
        }
        private void defineTaskFilter() {
            if (stateFilterDD.getSelected() == null | "All".equals(stateFilterDD.getSelected())) {
                log("\*\*\* APH-I1 : Select All filter";);
                taskFilter = new TaskFilter();
            } else {
                try {
                    log("\*\*\* APH-I1 : Select " + stateFilterDD.getSelected() + " filter";);
                    taskFilter = new TaskFilter(TaskFilter.TaskFilterType_ByTaskStatus, (String) stateFilterDD.getSelected());
                } catch (TaskException ex) {
                    Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                    error(ex.getMessage());
                }
            }
            workflowServiceGetTasksForUser.setArg0(getSessionBean1().getUsername());
            workflowServiceGetTasksForUser.setArg1(taskFilter);
            workflowServiceGetTasksForUser.refresh();
        }

    The defineTaskFilter method check to see if we need to do Task State filtering in addition to Username filtering. To retrieve all tasks for a user simple assign an empty TaskFilter to Arg1.

    Task List

    The following code should added for each of the buttons.

        public String viewBtn_action() {
            getSessionBean1().setTaskId((String) getValue("#{currentRow.value['taskId']}";));
            return "viewtask";
        }

        public String escalateBtn_action() {
            try {
                String taskId = (String) getValue("#{currentRow.value['taskId']}";);
                List taskIdList = new ArrayList();
                taskIdList.add(taskId);
                TaskFilter taskFilter = new TaskFilter(TaskFilter.TaskFilterType_ByTaskIdList, taskIdList);
                getWorkflowServiceClient().escalateTasks(getSessionBean1().getUsername(), taskFilter);

            } catch (Exception ex) {
                Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                error(ex.getMessage());
            }
            getWorkflowServiceGetTasksForUser().refresh();
            return null;
        }

        public String acceptBtn_action() {
            try {
                String taskId = (String) getValue("#{currentRow.value['taskId']}";);
                List taskIdList = new ArrayList();
                taskIdList.add(taskId);
                TaskFilter taskFilter = new TaskFilter(TaskFilter.TaskFilterType_ByTaskIdList, taskIdList);
                getWorkflowServiceClient().checkoutTasks(getSessionBean1().getUsername(), taskFilter);
                getWorkflowServiceClient().setOutput(taskId, "Accept";);
                getWorkflowServiceClient().checkinTasks(getSessionBean1().getUsername(), taskFilter);
                getWorkflowServiceClient().completeTasks(getSessionBean1().getUsername(), taskFilter);
            } catch (Exception ex) {
                Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                error(ex.getMessage());
            }

            return null;
        }

    The View Button will simple copy the current taskId to the SessionBean and then call the Task Details page. When the Escalate Button is pressed it will take the current Task and execute the escalateTasks for this user. We could, if we provided multiple select option, escalate multiple tasks by simply building up the list of Task Ids. To accept / authorise a task we will need to first check out the task from the WLM, which indicates that we will be processing this task then update the appropriate fields. Once this has been done the task will be checked in and completed. If a number of screens need to be associated with the Task acceptance on a user needs to lock a task whilst they are processing it then the methods may be called separately.
  5. The Task Details Page simply displays the input information associated with the selected Task, identified by the value written to the taskId property with the Session Bean, its details will be selected again on entry to the Page.

    Task Details

    The fields displayed within this Page are bound to the Task Page property and its sub properties. The following code defines the Task Property and the appropriate button actions. I will say little else about this page and leave you to create your own.

        // Properties
        private Task task = null;

        public Task getTask() {
            if (task == null) {
                try {
                    task = getWorkflowServiceClient().getTaskById(getSessionBean1().getTaskId());
                } catch (Exception ex) {
                    Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                    error(ex.getMessage());
                }
            }

            return task;
        }

        public void setTask(Task task) {
            this.task = task;
        }
       
        private Option[] assignedArray = null;
       
        public Option[] getAssignedArray() {
            if (assignedArray == null) {
                assignedArray = new Option[getTask().getAssignedTo().size()];
                Iterator<String> assignedItr = getTask().getAssignedTo().iterator();
                String assignedTo = null;
                int optionIdx = 0;
                while(assignedItr.hasNext()) {
                    assignedTo = assignedItr.next();
                    assignedArray[optionIdx++] = new Option(assignedTo,assignedTo);
                }
            }
            return assignedArray;
        }

        // Methods
        // Button Actions
        public String taskListBtn_action() {
            // TODO: Process the action. Return value is a navigation
            // case name where null will return to the same page.
            return "taskList";
        }

        public String escalateBtn_action() {
            try {
                String taskId = getSessionBean1().getTaskId();
                List taskIdList = new ArrayList();
                taskIdList.add(taskId);
                TaskFilter taskFilter = new TaskFilter(TaskFilter.TaskFilterType_ByTaskIdList, taskIdList);
                getWorkflowServiceClient().escalateTasks(getSessionBean1().getUsername(), taskFilter);

            } catch (Exception ex) {
                Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                error(ex.getMessage());
            }
            return "taskList";
        }

        public String acceptBtn_action() {
            try {
                String taskId = getSessionBean1().getTaskId();
                List taskIdList = new ArrayList();
                taskIdList.add(taskId);
                TaskFilter taskFilter = new TaskFilter(TaskFilter.TaskFilterType_ByTaskIdList, taskIdList);
                getWorkflowServiceClient().checkoutTasks(getSessionBean1().getUsername(), taskFilter);
                getWorkflowServiceClient().setOutput(taskId, "Accept";);
                getWorkflowServiceClient().checkinTasks(getSessionBean1().getUsername(), taskFilter);
                getWorkflowServiceClient().completeTasks(getSessionBean1().getUsername(), taskFilter);
            } catch (Exception ex) {
                Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                error(ex.getMessage());
            }

            return "taskList";
        }

        public String rejectBtn_action() {
            try {
                String taskId = getSessionBean1().getTaskId();
                List taskIdList = new ArrayList();
                taskIdList.add(taskId);
                TaskFilter taskFilter = new TaskFilter(TaskFilter.TaskFilterType_ByTaskIdList, taskIdList);
                getWorkflowServiceClient().checkoutTasks(getSessionBean1().getUsername(), taskFilter);
                getWorkflowServiceClient().setOutput(taskId, "Reject";);
                getWorkflowServiceClient().checkinTasks(getSessionBean1().getUsername(), taskFilter);
                getWorkflowServiceClient().completeTasks(getSessionBean1().getUsername(), taskFilter);
            } catch (Exception ex) {
                Logger.getLogger(TaskListPage.class.getName()).log(Level.SEVERE, null, ex);
                error(ex.getMessage());
            }

            return "taskList";
        }


  6. The project can now be built and deployed to Application Server running the WorkflowServices.jar
Resources

Comments:

Hi. Could you help me. I'm trying to figure out how to develop a custom GUI for the WLM and wanted to get your example working, but in my case, my WLM business process is running in a 5.1.2 JCAPS domain. So I downloaded the WorkflowService.zip from the repository, edited the connection.properties, jar'd up the changes, created the client stubs from the JCAPS 5.1.2 domain, deployed the WorkflowService.jar ejb to 5.1.2 JCAPS domain and am trying to get your web app to connect from Netbeans Glassfish server running locally on my workstation. But I seem to be missing a piece. When I click the login button, it's unable to find the EJB context. I assume it's trying to find it locally in the Glassfish domain. I have imported the WorkflowServiceClient.jar into Netbeans. Do I have to modify the client manually to specify the JCAPS domain server and port to get it to find the EJB there?

Posted by sjhunyadi on May 08, 2009 at 01:41 PM GMT #

Post a Comment:
Comments are closed for this entry.
About

As a member of the Oracle A-Team we specialise in enabling and supporting the Oracle Fusion Middleware communities.

Search

Archives
« April 2014
MonTueWedThuFriSatSun
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today