Implementing Task Details

This post is part of a series on building a custom worklist for BPM/SOA 11g.

Most of our controllers are fairly similar and not too complicated, so let’s jump right in and take a look at the com.oracle.ateam.TaskDetailController.  Here is the code (more comments in Subversion):

package com.oracle.ateam;

import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.oracle.ateam.domain.*;
import com.oracle.ateam.util.MLog;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class TaskDetailController extends SimpleSuccessFailureController {

  @Override
  public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
      throws Exception {
    MLog.log("TaskDetailController", "Entering handleRequest()");
    String taskNumber = request.getParameter("x_tasknumber");
    MLog.log("TaskDetailController", "Task Number: " + taskNumber);
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("task", MTaskList.getTaskDetails(request.getUserPrincipal().getName(), taskNumber));
    return new ModelAndView("/WEB-INF/jsp/taskdetail.jsp", "model", model);
  }
}

Like we did for the TaskListController, we extend the SimpleSuccessFailureController and we perform some logging using our MLog utility class.

We retrieve the x_tasknumber parameter from the caller, it is passed in as an URL parameter.  Then we create the ModelAndView and call the MTaskList.getTaskDetails() method in our domain package to obtain the fully populated MTask wrapper object for the nominated task.  This is then added into the model under the key “task” and we send the user on to the view.

Here is the code for the view:

<%@ page import="com.oracle.ateam.util.MLog" %>
<%@ page import="com.oracle.ateam.domain.MTask" %>
<%@ page import="java.util.List" %>
<%@ include file="/WEB-INF/jsp/common/head.jspf" %>
<%
  MLog.log("taskdetail.jsp", "Entered taskdetail.jsp");
%>
  <h1>Task Detail for ${model.task.title}</h1>
  <table>
    <tr>
      <th class="td-head">Task Number</th><td class="td-row">${model.task.number}</td><td>&nbsp;&nbsp;</td>
      <th class="td-head">Created</th><td class="td-row">${model.task.createDate}</td><td>&nbsp;&nbsp;</td>
      <th class="td-head">Creator</th><td class="td-row">${model.task.creator}</td><td>&nbsp;&nbsp;</td>
    </tr>
    <tr>
      <th class="td-head">Priorty</th><td class="td-row">${model.task.priority}</td><td>&nbsp;&nbsp;</td>
      <th class="td-head">Updated</th><td class="td-row">${model.task.updateDate}</td><td>&nbsp;&nbsp;</td>
      <th class="td-head">Acquired by</th><td class="td-row">${model.task.acquirer}</th><td>&nbsp;&nbsp;</td>
    </tr>
    <tr>
      <th class="td-head">State</th><td class="td-row">${model.task.state}</td><td>&nbsp;&nbsp;</td>
      <th class="td-head">Expiry</th><td class="td-row">${model.task.expiryDate}</td><td>&nbsp;&nbsp;</td>
      <th class="td-head">Outcome</th><td class="td-row">${model.task.outcome}</td><td>&nbsp;&nbsp;</td>
    </tr>
  </table>
  <form action="processtask.do" method="POST"><p>Take action on this task:
  <select name="x_action">
    <c:forEach items="${model.task.customActions}" var="customAction">
      <option value="${customAction.action}">${customAction.displayName}</option>
    </c:forEach>
    <option value="SYS_ESCALATE">Escalate</option>
    <option value="SYS_WITHDRAW">Withdraw</option>
    <c:choose>
      <c:when test="${model.task.state == 'SUSPENDED'}">
        <option value="SYS_RESUME">Resume</option>
      </c:when>
      <c:otherwise>
        <option value="SYS_SUSPEND">Suspend</option>
      </c:otherwise>
    </c:choose><option value="SYS_PURGE">Purge</option>
    <option value="SYS_ERROR">Error</option>
    <option value="SYS_ACQUIRE">Acquire</option>
  </select>
  <input type="hidden" name="x_tasknumber" value="${model.task.number}"/>
  <input type="submit" value="Process Now"/>
  <p></form>
  <table>
    <tr>
      <td colspan="2">
        <h2 class="td-h2">Payload</h2>
        <c:forEach items="${model.task.payloadAsHtml}" var="parm">
          <pre>${parm}</pre><br/>
        </c:forEach>
      </td>
    </tr>
    <tr>
      <td>
        <h2 class="td-h2">Comments</h2>
        <table width="50%" class="tl-table">
          <tr>
            <th width="150">User</th>
            <th width="200">Date</th>
            <th>Comment</th>
          </tr>
        </table>
        <table width="50%">
          <c:forEach items="${model.task.comments}" var="comment">
            <tr>
              <td width="150">${comment.updatedBy.id}</td>
              <td width="200">${comment.updatedDate.time}</td>
              <td>${comment.comment}</td>
            </tr>
          </c:forEach>
          <tr><td>Add a new comment:</td></tr>
          <tr>
            <td colspan="3"><form action="addcomment.do" method="POST">
              <textarea name="x_comment" rows="6" cols="40"></textarea>
              <input type="hidden" name="x_tasknumber" value="${model.task.number}"/>
              <input type="submit" value="Add Comment"/>
            </form></td>
          </tr>
        </table>
      </td>
    </tr>
  </table>

<%@ include file="/WEB-INF/jsp/common/tail.jspf" %>
<%
  MLog.log("taskdetail.jsp", "Done");
%>

The table at the top of the page displays details for the task.  As the task was added to the model with the name “task” (as we saw earlier), we can access properties of the MTask using Expression Language as follows:

${model.task.number}

Following this, we have an HTML SELECT that allows the user to choose an action to take on the task.  Recall that there are two kinds of actions – custom actions and system actions.  Custom actions those that are defined in the task definition.  These are displayed using the following piece of code:

    <c:forEach items="${model.task.customActions}" var="customAction">
      <option value="${customAction.action}">${customAction.displayName}</option>
    </c:forEach>

The system actions are the same for any task (more or less) so we can just go ahead and add the ones that we want to support as follows:

    <option value="SYS_ESCALATE">Escalate</option>
    <option value="SYS_WITHDRAW">Withdraw</option>
    <c:choose>
      <c:when test="${model.task.state == 'SUSPENDED'}">
        <option value="SYS_RESUME">Resume</option>
      </c:when>
      <c:otherwise>
        <option value="SYS_SUSPEND">Suspend</option>
      </c:otherwise>
    </c:choose><option value="SYS_PURGE">Purge</option>
    <option value="SYS_ERROR">Error</option>
    <option value="SYS_ACQUIRE">Acquire</option>

Notice that we check if the task is in the SUSPENDED state when deciding whether to show the Suspend or Resume action.  Only one of these will make sense at any given time, depending on the state of the task.

Next we display the payload(s) of the task.  A task can have zero or more payloads, and each can be simple or complex.  You may recall that the payload(s) are stored in org.w3c.dom.Element objects, so we wrote a getPayloadAsHtml() method in our MTask wrapper object to convert them to an HTML String representation that we could display on a page conveniently.  In the code below, you can see how we access the payload(s) using this method:

        <h2 class="td-h2">Payload</h2>
        <c:forEach items="${model.task.payloadAsHtml}" var="parm">
          <pre>${parm}</pre><br/>
        </c:forEach>

Following after the payload, we want to display any existing comments on the task.  This is done with the code below.  Again, you can notice that our MTask wrapper class makes our view code very simple and clean, we can just refer to the objects and iterate over them using simple Expression Language statements like model.task.comments.

          <c:forEach items="${model.task.comments}" var="comment">
            <tr>
              <td width="150">${comment.updatedBy.id}</td>
              <td width="200">${comment.updatedDate.time}</td>
              <td>${comment.comment}</td>
            </tr>
          </c:forEach>

We also want to allows users to add a new comment to the task.  This will be handled by our com.oracle.ateam.AddCommentController, which we will see in a later post.  For now, we need to create an HTML FORM that will pass in the necessary parameters for that Controller, the task number and the comment.  Here is the code that handles this:

            <form action="addcomment.do" method="POST">
              <textarea name="x_comment" rows="6" cols="40"></textarea>
              <input type="hidden" name="x_tasknumber" value="${model.task.number}"/>
              <input type="submit" value="Add Comment"/>
            </form>

Summary

So that completes our Task Details page.  By now you should be noticing some patterns in the Controllers and Views that we are developing:

  • The Controllers are fairly simple, and basically gather parameters from the caller, call a method in our ‘busines logic’ in the com.oracle.ateam.domain package, populate the model and forward to a View,
  • The Views use JSTL and Expression Language to access the objects in the model and iterate over them,
  • We use HTML FORMs in the View to pass parameters to the next Controller.

In the next post, we will create the controller to add a comment to a task.

About Mark Nelson

Mark Nelson is an Architect (an "IC6") in the Fusion Middleware Central Development Team at Oracle. Mark's job is to make Fusion Middleware easy to use in the cloud and at home, for developers and operations folks, with special focus on continuous delivery, configuration management and provisioning - making it simple to manage the configuration of complex environments and applications built with Oracle Database, Fusion Middleware and Fusion Applications, on-premise and in the cloud. Before joining this team, Mark was a senior member of the A-Team since 2010, and worked in Sales Consulting at Oracle since 2006 and various roles at IBM since 1994.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s