1 Reply Latest reply: Jun 18, 2012 10:35 AM by Ravi Jegga RSS

    issue with InvokeActionBean on migration from 11.1.1.5 to 11.1.1.6

    user8438481
      Hi All,

      We were overrding method setOperation in our bean method which extends

      oracle.bpel.services.workflow.worklist.adf.InvokeActionBean

      in 11.1.1.5 signature was public void setOperation(ActionEvent actionEvent)
      on migrating to 11.1.1.6 its changed to public String setOperation(ActionEvent actionEvent) ,

      so our code was failing on approving from BPM worklist, it was giving error saying method
      setOperation not found

      we changed overridden method to in our bean code to return String,
      currently I am returning a dummy value i.e return "test", it seems to be working fine and approval is working ok

      Can someone point me to what could be harm of returning incorrect value and whats the correct value which we should be returning at end of method?


      public String setOperation(ActionEvent actionEvent) {
      FacesContext facesContext = FacesContext.getCurrentInstance();
      if ("ctb1".equalsIgnoreCase(actionEvent.getComponent().getClientId(facesContext))) {
      ExpressionFactory exprFactory =
      facesContext.getApplication().getExpressionFactory();
      ValueExpression valueExpr =
      exprFactory.createValueExpression(facesContext.getELContext(),
      "#{pageFlowScope.CommentsOk}",
      Object.class);
      String value = (String)valueExpr.getValue(facesContext.getELContext());

      if (!("Y".equalsIgnoreCase(value))) {
      FacesMessage msg =
      new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Please enter reason for Rejection by clicking + in below Comments region");
      facesContext.addMessage(null, msg);
      return null;
      }
      }
      super.setOperation(actionEvent);
      return "test";

      }

      Edited by: user8438481 on Jun 17, 2012 11:59 PM
        • 1. Re: issue with InvokeActionBean on migration from 11.1.1.5 to 11.1.1.6
          Ravi Jegga
          Hi
          1. To begin with, I am not sure if InvokeActionBean is exposed as Public class where, the APIs are gauranteed and will not change with releases (mostly). I could not see this class in any public APIs. Anyhow, looks like you used internal private class APIs which are subject to change. This is not the recommended/supported way. But the quick and immediate solution is see actual implementation of this class using java decompiler. Open "bpm-workflow-datacontrol.jar" from yourWLS_Home\Oracle_SOA1\soa\modules\oracle.soa.workflow_11.1.1 folder. For InvokeActionBean.class, generate .java file using any free java decompiler. See the code in the method setOperation() and do the similar thing.

          2. Looks like your requirement is, when user rejects a Task, you want to make sure that he enters the Comments. If not, do not allow Reject operation.

          3. The more elegant and standard way for these kind of requirements is to use the official way that has public APIs for the interface named ITaskValidationCallback. In the method, get name of action ("REJECT") and if it matches, use the official APIs to get list of Comments/Attachments and do your validation there.

          http://docs.oracle.com/cd/E14571_01/apirefs.1111/e10660/oracle/bpel/services/workflow/task/ITaskValidationCallback.html

          This post gives some idea on this usage: Re: Assign role, group to Human Task when initiated

          4. Another approach is, to have your own custom ManagedBean and implement a method like customRejectAction(...). Link this to the action attribute of your Reject button. In this method, use APIs to get list of comments. If its there, then use Bindings to get the action of Reject, and invoke the reject action manually using bindings. The sample code snippet will be like this:
          ****** JSP Code
          <af:commandToolbarButton actionListener="#{invokeActionBean.setOperation}"
                           text="#{wf:getResourceValue('REJECT', 'bindings.customActions')}"
                           disabled="#{!bindings.REJECT.enabled}"
                           action="#{yourManagedBean.customRejectAction}" partialSubmit="false"
                           visible="#{wf:isCustomActionAvailable('REJECT', 'bindings.customActions')}"
                           id="ctbRej">
          <f:attribute name="DC_OPERATION_BINDING" value="bindings.REJECT"/>
          </af:commandToolbarButton>
          
          ***** Custom ManagedBean Code
              // You can make this method generic also, by passing actual binding name and link to Approve, Reject or any action
              public String customRejectAction() {
              String bindingName = "REJECT";
                  String returnMessage = null;
                  try {
                      System.out.println("customRejectAction -> Begin");
                      
                      // Do all your Validation Here that includes like for out of box comments or attachement or even your own custom validations
                      //if validation fails
                      //return null;
          
                   // if Validation Passes
          
                      BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
                      OperationBinding operationBinding = bindings.getOperationBinding(bindingName);
                      Map paramsMap = operationBinding.getParamsMap(); // "#{bindings." + bindingName + ".inputValue}"
                      paramsMap.put("DC_OPERATION_BINDING", expHelper.evalExpression("#{bindings." + bindingName + ".inputValue}"));
                      operationBinding.execute();
                      System.out.println("customRejectAction -> operationBinding.getErrors(): " + operationBinding.getErrors());
                      
                      List errorsOnSubmit = operationBinding.getErrors();
                      if (errorsOnSubmit == null || errorsOnSubmit.isEmpty()) {
                          returnMessage = "closeTaskFlow";
                          // Below code will close the screen. There is a scenario, where the task details screen sometimes do not close
                          FacesContext facesContext = FacesContext.getCurrentInstance();
                          ExtendedRenderKitService service = Service.getRenderKitService(facesContext, ExtendedRenderKitService.class);
                          service.addScript(facesContext, "window.opener = self;window.close();");
                      }
                  } catch (Exception anException) {
                      anException.printStackTrace();
                  }
                  return returnMessage;            
              }
          Thanks
          Ravi Jegga