Tuesday, April 27, 2010

Generic prompting PeopleTools 8.50

As of PeopleTools 8.50, Oracle introduced Generic Prompting for process definitions. With this feature the creation of runcontrol pages has become obsolete.   PeopleBooks describes the ability of Generic Prompting, but does not give an example how to achieve this, nor does DMO provided an example.

This post describes the steps needed to get Generic Prompting working properly.

For our example I created an Application Enige which uses a runcontrol record with 3 additional parameters Fromdate, Todate and Rundate



Create a process definition for the Application Engine, as if you always would.



Now go to tab-folder Runtime Parameters.



Add a new row for each runcontrol parameter and fill in references to your runcontrol record and runcontrol fields. Select the parameter labels to be shown on runtime. Do not forget to check Enable Generic Prompting, otherwise this feature will not work.

As of now you have implemented Generic prompting for this application engine without the use of a runcontrol page. You can now add this process to you favorites in the reporting console.



Click on Run and you will be presented with a parameter screen.



Validation

What is the use of a runcontrol page without proper validation of parameters?

Let’s go back to our process definition and incorporate validation.



Check Validation? checkbox and you will be presented with two new columns, Validation Function and Test Function. Clicking on Validation Function will pop-up a new screen.


This screen tells us that we need an application class for the validation of our runtime parameters. This means that we have to build the validation code in an application class, whereas before we were used to building validation on SaveEdit en FieldEdit events on the runcontrol record.

After some investigation, I found that PeopleSoft calls method ValidateAppMethodValue in class PRCS_GENERIC:PRCS_GENERICHelper to execute Generic Prompting validation.

method ValidateAppMethodValue
/+ &appClassName as String, +
/+ &methodName as String, +/
/+ &fldValue as String, +/
/+ &fldType as String +/
/+ Returns Boolean +/

/*Local object &AppClsObject = CreateObject(&appClassName);*/

Local array of any &RunCntlArray;
Local boolean &retVal;

/*If (&AppClsObject = Null) Then
   &retVal = False;
End-If;*/

Evaluate &fldType
When "NUMBER"
When "SIGNEDNUMBER"

   Local number &VAL1 = ValueUser(&fldValue);
   &RunCntlArray = CreateArrayAny(&VAL1);
   &retVal = ObjectDoMethodArray(CreateObject(&appClassName), &methodName, &RunCntlArray); 
   Break;

When "CHAR"

   &RunCntlArray = CreateArrayAny(&fldValue);
   &retVal = ObjectDoMethodArray(CreateObject(&appClassName), &methodName, &RunCntlArray);
   Break;

When "LONGCHAR"

   &RunCntlArray = CreateArrayAny(&fldValue);
   &retVal = ObjectDoMethodArray(CreateObject(&appClassName), &methodName, &RunCntlArray);
   Break;

When "DATE"

   Local date &DATEVAL = DateValue(&fldValue);
   &RunCntlArray = CreateArrayAny(&DATEVAL);
   &retVal = ObjectDoMethodArray(CreateObject(&appClassName), &methodName, &RunCntlArray);
   Break;

When "DATETIME"

   Local datetime &DATETIMEVAL = DateTimeValue(&fldValue);
   &RunCntlArray = CreateArrayAny(&DATETIMEVAL);
   &retVal = ObjectDoMethodArray(CreateObject(&appClassName), &methodName, &RunCntlArray);
   Break;

When "TIME"

   Local time &DATEVAL1 = TimeValue(&fldValue);
   &RunCntlArray = CreateArrayAny(&DATEVAL1);
   &retVal = ObjectDoMethodArray(CreateObject(&appClassName), &methodName, &RunCntlArray);
   Break;

End-Evaluate;

Return &retVal;

end-method;

This method uses the build-in function ObjectDoMethodArray to create the object  and executes the method that is specified in the validation function screen. This method also assumes that our validation class method will have a return Boolean value.

I created an application class with basic date validation.

class SyncPersParams

method validateFromDate(&fldValue As date) Returns boolean;

method validateToDate(&fldValue As date) Returns boolean;

private

end-class;

method validateFromDate

/+ &fldValue as Date +/

/+ Returns Boolean +/

If None(&fldValue) Then

Error "From date is required";

End-If;

If &fldValue > %Date Then

Error "From date must be in the past";

End-If;

Return True;

end-method;

method validateToDate

/+ &fldValue as Date +/

/+ Returns Boolean +/

If None(&fldValue) Then

Error "To date is required";

End-If;

If &fldValue > %Date Then

Error "To date must be in the past";

End-If;

Return True;

end-method;

You can now fill in the Validation Function screen, referencing our application class.



With the button Test Function you can test your validation code



Let’s try testing FROM_DATE field validation



Results



Well, that concludes field validation

Cross Field validation

But what about Crossfield validation?

We definitely want to check if Todate if past Fromdate. This is a bit trickier. Remember method ValidateAppMethodValue? This method calls our validation code with ObjectDoMethodArray. This means for every field validation a new object will be created and we will lose references to other fields. Luckily the method ValidateAppMethodValue is called in a loop in method ValidateRuntimeParamValues. Therefore we can use component variables to store other values.

To incorporate cross field validation first create component variables in our validation class and assign values to the component variables as they are called. Then create a new method that will be called from our validation methods that does the cross validation when all fields have been validated and component variables have been assigned.

Code will look something like this:

class SyncPersParams
method validateFromDate(&fldValue As date) Returns boolean;
method validateToDate(&fldValue As date) Returns boolean;
method crossFieldValidation();
private
end-class;


Component date &cdFromdate;
Component date &cdTodate;


method validateFromDate
/+ &fldValue as Date +/
/+ Returns Boolean +/


If None(&fldValue) Then
Error "From date is required";
End-If;


If &fldValue > %Date Then
Error "From date must be in the past";
End-If;


&cdFromdate = &fldValue;

%This.crossFieldValidation();

Return True;
end-method;


method validateToDate
/+ &fldValue as Date +/
/+ Returns Boolean +/


If None(&fldValue) Then
Error "To date is required";
End-If;


If &fldValue > %Date Then
Error "To date must be in the past";
End-If;


&cdTodate = &fldValue;

%This.crossFieldValidation();

Return True;
end-method;


method crossFieldValidation

If All(&cdTodate, &cdFromdate) Then
If &cdFromdate >= &cdTodate Then
Error "From date past To date";
End-If;
End-If;


end-method;

2 comments:

  1. This is really a handy one.

    ReplyDelete
  2. You f**kng rock dude! Thanks for sharing this info!

    ReplyDelete