Showing posts with label Web Service. Show all posts
Showing posts with label Web Service. Show all posts

Monday, February 22, 2016

HCM SOA Registry - Demystified

If you have worked on either HCM or Campus Solutions applications in PeopleSoft then you would have come across the term 'HCM SOA Registry'. Associated with the HCM SOA Registry is a step/process to 'Refresh Cache' which can either be done online or batch.

I have seen many customers (using HCM or Campus Solutions) who run this 'Refresh Cache' on a regular basis and sometimes as a post step to standard migrations. By standard migrations, I mean the weekly/fortnightly migrations which are part of production support release cycles and not necessarily the bundle/patch/upgrade migrations.

What is wrong with running this process regularly as a post step to any migration?

Well, nothing. But of late, I am finding several cases where the 'Refresh Cache' process fails with "RowsetCache::Save: Save failed for xxx/xxx=: unknown error. (2,975)" error particularly since HRMS 9.0 Bundle 26 (last HR bundle for CS).

Since this online/batch cache refresh has been causing a lot of pain, I wanted to find out when it is appropriate to refresh cache (reverse engineering and identifying the events - object changes - that would necessitate a refresh). I ended up building a SQL query to identify whether a migration of a project (say part of weekly/fortnightly production support release) would require a 'HCM SOA - Refresh Cache' just based on the objects it contains.

Before I share the details of the SQL query, I would like to share some of my notes since I did not find any information that was straight forward or easy to understand specifically on HCM Registry - Refresh Cache.

HCM SOA Registry:

HCM SOA Registry, like any other SOA Registry, provides a mechanism for service registration, discovery and binding.

SOA Registry Example:


Reference: Web 2.0 Architectures

HCM SOA Registry:


PeopleBooks Reference: Understanding the HCM Interface Registry

My Process/Flow Diagram: HCM SOA Registry

How do we access HCM SOA Registry?

Main Menu > Set Up HRMS > System Administration > HCM Registry

Service Registry:


Transformation Registry:


Where does HCM SOA Registry data get stored?

According to Doc ID 658098.1: HCM Service Framework Error When Adding, Updating, or Viewing Person Data in Campus Solutions:
"The HCM Service Registry (Set Up HRMS > System Administration > HCM Registry > Service Registry) captures the meta-data about the HCM SOA services: input and output signatures, implementation application classes, web services, component interfaces, etc. This meta-data is stored on the HC_REGISTRY portal (PeopleTools > Portal). This portal contains no other data."

How do we access this HC_REGISTRY portal where the HCM SOA Registry is stored?

- Navigate to Portal – Structure and Content: Main Menu > PeopleTools > Portal > Structure and Content.
- Replace the default portal (EMPLOYEE) with HC_REGISTRY in the URL.

For example:

https://www.test.edu/psp/ps/EMPLOYEE/HRMS/c/PORTAL_ADMIN.PORTAL_OBJ_LIST.GBL
>>>>
https://www.test.edu/psp/ps/HC_REGISTRY/HRMS/c/PORTAL_ADMIN.PORTAL_OBJ_LIST.GBL


HCM SOA Registry Hierarchy:


PeopleSoft Rowset Cache and how is it used by HCM SOA Registry?

- PeopleTools stores application data in a database cache to increase system performance.
- The RowsetCache contains a rowset, and serializes the contained rowset to binary form for speed.
- The RowsetCache class enables you to access this memory structure, created at runtime, and shared by all users.
- As with most PeopleTools objects, RowsetCache objects are cached to memory and file, but they are also cached to the data base.
- Rowset cache is stored in PSCONTDEFN and PSCONTENT.

PeopleBooks Reference:
PeopleSoft Rowset Cache
Using PeopleSoft Rowset Cache

According to Doc ID 658098.1: HCM Service Framework Error When Adding, Updating, or Viewing Person Data in Campus Solutions:
"The meta-data stored in the HC_REGISTRY portal is needed at run-time in order to execute the service. To speed up the retrieval of this meta-data at run-time, it is stored in cache, using PeopleTools Rowset Cache objects."

Layers of HCM Registry Metadata Caching:


App Server Cache*: As with most PeopleTools objects, Rowset cache also gets cached at the app server layer.

HCM Registry - Online Refresh Cache:
  • Main Menu > Setup HRMS > System Administration > HCM Registry > Service Registry > Refresh Cache
  • Refreshes HCM SOA Rowset Cache (PSCONTDEFN and PSCONTENT) with current HCM SOA metadata (HC_REGISTRY Portal).
HCM Registry - Batch Refresh Cache:
  • Main Menu > Setup HRMS > System Administration > HCM Registry > Refresh HCM SOA Portal Access.
  • Refreshes security on HC_REGISTRY portal.
    • Makes sure all folders and CREFs in HC_REGISTRY are PUBLIC.
    • DOES NOT add any roles. Adding a default role to all users is now a deprecated functionality. Refer: Doc ID 1370324.1 - FAQ on Refresh HCM SOA Portal Access - Question 1.
  • Refreshes HCM SOA Rowset Cache (PSCONTDEFN and PSCONTENT) with current HCM SOA metadata (HC_REGISTRY Portal).
SQL to identify if a migration (list of projects) requires a HCM SOA - Refresh Cache:

Based on the HCM SOA Registry Hierarchy diagram above, we can see that all metadata (HC_REGISTRY Portal) and interfaces (App Classes, SQL Views, Messages) are PeopleTools Managed Objects. So the below SQL looks at PeopleTools metadata to figure out if a list of projects (part of a release) contain any objects associated with HCM SOA Registry.

-- Test Value for &&1: 'HCM900_MP11_D','PRJ812865','PRJ889693','PRJ889694','PRJ882259'

/* HCM Registry Objects - Content References */
SELECT 'HC Registry objects (CREFs) found in release. Run SOA Refresh Cache.' AS Found,
  'HC_REGISTRY'                                                               AS OBJECT,
  OBJECTVALUE3                                                                AS PORTAL_OBJNAME
FROM PSPROJECTITEM A
WHERE A.projectname IN (&&1)
AND A.OBJECTTYPE     = 55
AND OBJECTVALUE1     = 'HC_REGISTRY'
UNION

/* Interface Objects - Application Classes (Services, Types, Exceptions) */
SELECT 'HCM metadata objects (services/types/exceptions) found in release. Run HCM SOA Refresh Cache.' AS Found,
  TO_CHAR(I.PORTAL_ATTR_VAL)                                                                           AS OBJECT,
  I.PORTAL_OBJNAME
FROM PSPRSMSYSATTRVL I
WHERE I.PORTAL_NAME   = 'HC_REGISTRY'
AND I.PORTAL_REFTYPE  = 'C'
AND I.PORTAL_OBJNAME IN
  (SELECT A.PORTAL_OBJNAME
  FROM PSPRSMSYSATTRVL A
  WHERE A.PORTAL_NAME   = 'HC_REGISTRY'
  AND A.PORTAL_REFTYPE  = 'C'
  AND A.PORTAL_ATTR_NAM = 'TYPE'
  AND TO_CHAR(A.PORTAL_ATTR_VAL) IN ('EXC', 'SRV', 'TYP')
  )
AND I.PORTAL_ATTR_VAL           like '%:%'
AND TO_CHAR(I.PORTAL_ATTR_VAL) IN
  (SELECT REPLACE (A.objectvalue1 | | ':' | | A.objectvalue2 | | ':' | | A.objectvalue3 | | ':' | | A.objectvalue4, ': ')
  FROM PSPROJECTITEM A
  WHERE A.projectname IN (&&1)
  AND objecttype       = 58
  )
UNION

/*
Interface Objects - Views */
SELECT 'HCM metadata objects (views) found in release. Run HCM SOA Refresh Cache.' AS Found,
  TO_CHAR(I.PORTAL_ATTR_VAL)                                                       AS OBJECT,
  I.PORTAL_OBJNAME
FROM PSPRSMSYSATTRVL I
WHERE I.PORTAL_NAME   = 'HC_REGISTRY'
AND I.PORTAL_REFTYPE  = 'C'
AND I.PORTAL_OBJNAME IN
  (SELECT A.PORTAL_OBJNAME
  FROM PSPRSMSYSATTRVL A
  WHERE A.PORTAL_NAME             = 'HC_REGISTRY'
  AND A.PORTAL_REFTYPE            = 'C'
  AND A.PORTAL_ATTR_NAM           = 'TYPE'
  AND TO_CHAR(A.PORTAL_ATTR_VAL) IN ('IVW')
  )
AND PORTAL_ATTR_NAM             = 'IMPLEMENTATION'
AND TO_CHAR(I.PORTAL_ATTR_VAL) IN
  (SELECT REPLACE (A.objectvalue1 | | ':' | | A.objectvalue2 | | ':' | | A.objectvalue3 | | ':' | | A.objectvalue4, ': ')
  FROM PSPROJECTITEM A
  WHERE A.projectname IN (&&1)
  AND objecttype       = 0
  )
UNION

/*
Interface Objects - HCM Transformation Maps */
SELECT 'HCM metadata objects (messages) found in release. Run HCM SOA Refresh Cache.' AS Found,
  TO_CHAR(I.PORTAL_ATTR_VAL)                                                          AS OBJECT,
  I.PORTAL_OBJNAME
FROM PSPRSMSYSATTRVL I
WHERE I.PORTAL_NAME   = 'HC_REGISTRY'
AND I.PORTAL_REFTYPE  = 'C'
AND I.PORTAL_OBJNAME IN
  (SELECT A.PORTAL_OBJNAME
  FROM PSPRSMSYSATTRVL A
  WHERE A.PORTAL_NAME             = 'HC_REGISTRY'
  AND A.PORTAL_REFTYPE            = 'C'
  AND A.PORTAL_ATTR_NAM           = 'TYPE'
  AND TO_CHAR(A.PORTAL_ATTR_VAL) IN ('TRF')
  )
AND PORTAL_ATTR_NAM            IN ('MSGNAME', 'TO_MSGNAME')
AND TO_CHAR(I.PORTAL_ATTR_VAL) IN
  (SELECT OBJECTVALUE1
  FROM PSPROJECTITEM A
  WHERE A.projectname IN (&&1)
  AND A.OBJECTTYPE     = 37
  );


If the query returns results then we need to run HCM SOA - Refresh Cache. If not, there is no need.

Note: This post is only focusing on the need (if any) for running the HCM SOA - Refresh Cache as a post step to migrations. This does not mean that there would not be other circumstances (outside of migrations) where the Refresh Cache might be necessary.

Wednesday, November 25, 2015

Implementing no CAPTCHA reCAPTCHA in PeopleSoft

This post is based on a great discussion concerning security on the OTN forums.

The requirement was to solve the problem of bots/hacker websites hijacking users to their malicious locations (masquerading the legitimate PeopleSoft site), scraping the credentials from the users and then posting the data into the PeopleSoft signin page in a typical phishing attack scenario.

If you read through the discussion, you will notice some very valid questions, concerns and suggestions provided by Greg Kelly from Oracle and others around how to ensure that such phishing emails and attacks can be prevented.

Outside of that discussion, traditionally CAPTCHA has been used in several websites to prevent bot attacks. Now Google's reCAPTCHA project is being used more commonly since its inception in 2009. The latest version (no CAPTCHA reCAPTCHA) has significant user experience improvements. Additionally, the reCAPTCHA API version 2.0 is now a RESTful API which makes server side validation a lot easier. Another great incentive to use Google's no CAPTCHA reCAPTCHA is the fact that it is FREE!

Before going down the path of implementing reCAPTCHA, please consider accessibility and user experience implications and test accordingly. Click here for an article that talks about accessibility features of reCAPTCHA.

Here are the steps to implement Google reCAPTCHA API version 2.0 in PeopleSoft.

Note: I am currently using a HCM 9.2 PUM Image 12 - PeopleTools 8.54.08.
Reference Document: Developer's Guide

Step 1: Sign up for an API key pair

Please click here to sign up on the Goolge reCAPTCHA website. Once you sign up for an API key pair to your site, you will be provided with two keys - secret key and site key.

Step 2: Client side integration

In this case, let us assume that we want to add reCAPTCHA to the PeopleSoft signin page. So the signin page will be our client side content where we would add the reCAPTCHA code.

Here are the instructions from the Google reCAPTCHA documentation:


Let us add the above code snippet to the PeopleSoft signin page (signin.html).

Note: We can locate the signin.html file in the following directory on the web server.
<PIA_HOME>/webserv/<DOMAIN>/applications/peoplesoft/PORTAL.war/WEB-INF/psftdocs/<site_name>/

Add the following script inclusion code just before </HEAD> as shown:
<!-- CSK reCAPTCHA - Start -->
<script src='https://www.google.com/recaptcha/api.js'></script>
<!-- CSK reCAPTCHA - End -->


 Add the following div (reCAPTCHA) in an appropriate location on the content page. I chose to add it right before the submit button which could be referenced by <input name="Submit" type="submit" title="<%=137%>" class="ps-button" value="<%=137%>">.

<!-- CSK reCAPTCHA - Start -->
    <div class="g-recaptcha" data-sitekey="<ENTER_YOUR_SITE_KEY_HERE>" align="center"></div>
    <br/>
<!-- CSK reCAPTCHA - End -->


Note: If you are on PeopleTools 8.54 then you might also want to perform the same customizations to signin_fmode.html file as well. This is due to a known issue that will be fixed in PeopleTools 8.55. Refer: E-FLUID - Fluid HomePage Sign Off Link Calls fmode=1 in URL, Skips Custom signout.html Page (Doc ID 2001761.1).

Please bounce and clear the cache on your web server domains. Let us now see the reCAPTCHA plugin in action on the client side.






We are not done yet! Once verified, the reCAPTCHA integration would additionally add a string with the name "g-recaptcha-response" to the payload when the user submits (form post). This string would be a key that is generated specifically for our site. The string needs to be validated on the server side which we will explore in the next section.

Step 3: Server side integration/validation

This is the step where we verify the string provided by reCAPTCHA for validity by making a REST API call. Instructions from Google reCAPTCHA documentation.


For more details: Refer API documentation.

In this case, since we are trying to validate the reCAPTCHA response string provided by the PeopleSoft signin page, the best place to add the validation logic would be in the SignOn PeopleCode.

Let us now add a new row/entry in the sequence of Signon PeopleCode events as shown in the following screenshot. I am referencing a custom function name which I will explain shortly.


Record: CSK_RECAPTCHA
Field Name: FUNCLIB
Event Name: FieldFormula
Function Name: CSK_RECAPTCHA_CHECK

Note: After making any changes to Signon PeopleCode we must bounce the app servers for them to take effect.

Now let us see how to write some custom code to validate the reCAPTCHA response string. For reference, I pasted the entire peoplecode at the very end of this post.

Click on image to zoom in!


Note: In this case, I am using Apache Commons HttpClient Java Libraries to make the REST API call. Please refer to my previous blog posts that have more details on this topic (Part I and Part II).

Details on custom function validate_reCAPTCHA_JSON is provided below. For the purposes of JSON parsing, I am using a server side scripting technique described by Jim Marion in his blog post

Click on image to zoom in!


Message Catalog Entry that contains the JSON Parsing Script:


Script for reference:

var result = (function() {

     var json = JSON.parse(json_string);

     if (json.success) {
          return "true";
     } else {
          return "false";
     }

}());


This completes our server side integration/validation. Now we are relatively free of bot attacks! :)

Note: The same feature can be applied to any content page within the PeopleSoft application as well. If not easier, the effort should be the same as what we just went through in this post.

PeopleCode Functions for reference:

Function validate_reCAPTCHA_JSON(&json As string) Returns boolean;
  
   Local string &success;
  
   /* Instantiate ScriptEngine Manager and Engine objects */
   Local JavaObject &manager = CreateJavaObject("javax.script.ScriptEngineManager");
   Local JavaObject &engine = &manager.getEngineByName("JavaScript");
  
   /* Pass JSON string */
   &engine.put("json_string", &json);
   /* Get JSON Parse JavaScript from Message Catalog */
   Local string &jsFunction = MsgGetExplainText(26000, 1, "NONE");
  
   If &jsFunction <> "NONE" Then
      &engine.eval(&jsFunction);
      &success = &engine.get("result").toString();
   End-If;
  
   If Upper(&success) = "TRUE" Then
      Return True;
   Else
      Return False;
   End-If;
  
End-Function;

Function CSK_RECAPTCHA_CHECK()
  
   /* Get reCaptcha parameter from the Request */
   Local string &reCAPTCHA = %Request.GetParameter("g-recaptcha-response");
  
   If &reCAPTCHA = "" Then
      /* Fail Authentication */
      SetAuthenticationResult( False, %SignonUserId, "", False);
   Else
      /* Do further validation if required. Refer: https://developers.google.com/recaptcha/docs/verify */
      /* Post user's reCAPTCHA response and server's private key to API: https://www.google.com/recaptcha/api/siteverify */
      try
        
         /* Using Apache HttpClient for REST - Post Method */
         Local JavaObject &jHttp, &jMethod, &filePart, &partArray, &mPartReqEntity;
        
         /* Initialize HttpClient and set parameters */
         &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
         &jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);
        
         /* Initialize PostMethod */
         /* !!!!!! Avoid hardcoding !!!!!!!! Replace below URL with a URL definition that is configurable. */
         Local string &sURL = "https://www.google.com/recaptcha/api/siteverify";
         &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PostMethod", &sURL);
         &jMethod.setFollowRedirects( False);
        
         /* Add Multi-Part Message - Start */
         /* Create String Part - secret */
         &secretPart = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.StringPart", "secret", "<ENTER_YOUR_SECRET_KEY_HERE>");
         /* Create String Part - response */
         &responsePart = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.StringPart", "response", &reCAPTCHA);
         /* Add Parts to Part Array */
         &partArray = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.Part[]", &secretPart, &responsePart);
         /* Create Multi-Part Request Entity */
         &mPartReqEntity = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity", &partArray, &jMethod.getParams());
         /* Add Multi-Part Request Entity to the Post Method */
         &jMethod.setRequestEntity(&mPartReqEntity);
         /* Add Multi-Part Message - End */
        
         /* Invoke PostMethod */
         Local integer &return = &jHttp.executeMethod(&jMethod);
         Local string &responseBody = &jMethod.getResponseBodyAsString();
        
         If (validate_reCAPTCHA_JSON(&responseBody)) Then
            /* reCaptcha success: allow user */
            SetAuthenticationResult( True, %SignonUserId, "", False);
         Else
            /* reCaptcha failure: deny */
            SetAuthenticationResult( False, %SignonUserId, "", False);
         End-If;
        
      catch Exception &ex
         /* Unknown Exception */
         SetAuthenticationResult( False, %SignonUserId, "", False);
      end-try;
   End-If;
End-Function;

 

Tuesday, October 14, 2014

AAWS - Targeted Error Handling

While troubleshooting AAWS issues (Admission Applications Web Services delivered in Campus Solutions) in a Production Environment, I found the following options that might come in handy.

Let us take AAWS - Submit Application (SAD_SUBMITAPPL) service operation as an example for this blog. Note: The same approach could be extended to any other AAWS service operation.

The problem or difficulty with troubleshooting this service operation is that the faults generated are very generic in nature and does not help with identifying the root cause of the problem.

Here is an example of a fault message generated by SAD_SUBMITAPPPL:

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <faultcode>Client</faultcode>
      <faultstring>An Error occurred processing this request (14098,286)</faultstring>
      <detail>
        <MSGS>
          <MSG>
            <ID>14098-206</ID>
            <DESCR>Error during Application submit, Contact the Administrator</DESCR>
            <MESSAGE_SEVERITY>I</MESSAGE_SEVERITY>
            <PROPS/>
          </MSG>
        </MSGS>
      </detail>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

While I can understand why AAWS faults are generic, potentially to mask the nasty error messages from being displayed to the end user, it is my personal opinion that this type of fault message is unacceptable especially for a high volume web service such as AAWS (from a service maintenance point of view). Let us explore how we can put controls in place to be able to identify the root cause for this error in real-time.

Using Delivered Campus Service Oriented Architecture Logging (Doc ID 1511543.1):

This document details couple of options.
  1. Setting up the regular logging at the routing level. This does not really add much value in the case of AAWS.

    Logging:



    Results:



    You will notice that there are no errors logged for the synchronous transaction.

  2. Setting Log Type and Threshold using delivered Campus Service Oriented Architecture (SOA) Logging.



    We can set the Logging Type to Database or File. For this example I chose the Database option. For the Log Threshold we have many options. The 'All' option would provide a lot of detail and something like 'Severe' option would probably give us what we want (in terms of errors).

    The result of this logging should be available in the PS_SCC_INTEG_LOG table. Use the following SQL to get the most recent entries first:

    select * from PS_SCC_INTEG_LOG order by 1 desc;

    You will notice that SCC_INT_LOG_MSG (where SCC_INT_LOG_LEVEL=2) would contain the error message that we are after. In my case, I found that my error message was as follows:

    "Transaction Manager Exception: Error Saving: XXX_CUSTOM_STG tempid: 579 (0,0) SCC_COMMON.ENTITY.StagedEntity.OnExecute  Name:save  PCPC:16872  Statement:322 Called from:SCC_COMMON.ENTITY.ChildEntity.OnExecute  Name:save  Statement:101 Called from:SCC_C"

    Now, this would tell us exactly why and where (peoplecode statement) the error occurred. This helps greatly in comparison to the Generic Error Message (Error during Application submit, Contact the Administrator).

    While this is very useful for short term/unexpected troubleshooting, one downside of the Campus SOA Logging is that it is not specific to a service operation. So if we turn on logging it would take effect for all delivered service operations that are represented using the Campus SOA. You will notice that if we have this logging turned on in a Production Environment then the table PS_SCC_INTEG_LOG would quickly fill up. Another scenario where this logging might fall short is if we want to send back real-time meaningful response/fault messages for the consumer to process and take action.
Now that we have exhausted delivered options (please correct me if I missed anything!), let us look at a targeted error handling approach (returning appropriate exceptions in the fault message) involving a minor customization. Note: While customizations would involve cost and maintenance considerations, it is generally the case of whether the benefits outweigh the effort and maintenance. I will let you make the decision based on the circumstances in your organization.

AAWS Targeted Error Handling - Customizing the Handler:

The OnRequest Handler code for the AAWS - SAD_SUBMITAPPL is implemented in the following class and method:
Class: SCC_OLA.HANDLERS.Admissions.OnExecute
Method: submitApplication

Let us take a look at a snippet of the delivered code that deals with part of the error handling which I customized:


Here is the same snippet of delivered code with my customization:


Let us examine my customization in detail:

         /* XXX - SV - 20141013 - Test Start */

         Local SCC_COMMON:ENTITY:LOG:MessageEntry &msgEntryCust = create SCC_COMMON:ENTITY:LOG:MessageEntry();
         Local array of string &parms = CreateArrayRept("", 0);
         &parms [1] = &e2.ToString();
         &msgEntryCust.DataPopulateV1(14098, 181, &msgEntryCust.Severity_Error, &parms, "", "", "");
         &returnError.writeEntry(&msgEntryCust);

         /* XXX - SV - 20141013 - Test End */

I made use of the MessageEntry class to create another message detail (<MSG> section), populate the message detail with the exception information and append it to the &returnError object which is the fault message.

Note: I used the same message set number and message number (14098, 181) that is referenced in the logError method right at the start of this exception handling section. 
&p_logger.logError(MsgGet(14098, 181, "", &e2.ToString()));

Let us see the results of this customization.

<SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
  <SOAP-ENV:Body> 
    <SOAP-ENV:Fault> 
      <faultcode>Client</faultcode> 
      <faultstring>An Error occurred processing this request (14098,286)</faultstring> 
      <detail> 
        <MSGS> 
          <MSG> 
            <ID>14098-206</ID> 
            <DESCR>Error during Application submit, Contact the Administrator</DESCR> 
            <MESSAGE_SEVERITY>I</MESSAGE_SEVERITY> 
            <PROPS/> 
          </MSG> 
          <MSG> 
            <ID>14098-181</ID> 
            <DESCR>Transaction Manager Exception: Error Saving: XXX_CUSTOM_STG tempid: 583 (0,0) SCC_COMMON.ENTITY.StagedEntity.OnExecute  Name:save  PCPC:16872  Statement:322
Called from:SCC_COMMON.ENTITY.ChildEntity.OnExecute  Name:save  Statement:101
Called from:SCC_COMMON.ENTITY.StagedEntity.OnExecute  Name:saveChildren  Statement:374
Called from:SCC_COMMON.ENTITY.StagedEntity.OnExecute  Name:save  Statement:303
Called from:SAD_ADM_APPL.ApplicationManager.OnExecute  Name:saveApplication  Statement:70
Called from:SCC_OLA.HANDLERS.Admissions.OnExecute  Name:submitApplication  Statement:595
Call
</DESCR> 
            <MESSAGE_SEVERITY>E</MESSAGE_SEVERITY> 
            <PROPS/> 
          </MSG> 
        </MSGS> 
      </detail> 
    </SOAP-ENV:Fault> 
  </SOAP-ENV:Body> 
</SOAP-ENV:Envelope>

Highlighted in orange is the marker for the custom message that was added and highlighted in green are the details of the custom message.

You can see how we can improve the details in the fault messages enabling both technical and functional staff to quickly identify the problem with the application and take corrective action. This is very effective especially when there could be application submission peaks where we can expect thousands of application requests in a day.

Note:
  • Please test (test and test!) this thoroughly before applying the suggested customization to your Production Environment (if you think this might be useful).
  • In the submitApplication method used in this example there are a 4 occurrences of &returnError.writeEntry method being invoked. It is recommended that each of those are appropriately extended using the approach in the sample code and example provided in this blog.
  • Customization Environment Details: Campus Solutions 9.0 (Bundle 34) and PeopleTools 8.52.22.