Wednesday 28 December 2011

OBIEE FANS

One of my friend was writing excellent blog articles on OBIEE software. I would like to share the website with you guys.

OBIEE FANS

Saturday 3 September 2011

Overloading %SubmitScriptName

As discussed in the previous post, all actions in a component that eventually require a server trip would invoke %SubmitScriptName for submitting the page. As such, it sometimes provide a convenient point for performing javascript modifications on the page.

This is achieved by storing a reference to the original function, and redefining %SubmitScriptName to perform your custom logic — invoking the original function as needed.

The following sample scenarios may help to illustrate this technique.

Objective: Display a javascript confirmation dialog (i.e., an Ok/Cancel pop-up dialog) prior to performing an action. In this example, the dialog is displayed when the component Save action is invoked.

Note that in this problem, it’s not possible to use the PeopleCode MessageBox function because the message generated by PeopleCode for Ok/Cancel will not be a pop-up dialog. It is also inefficient, because it requires a page refresh.

Sample Solution: Insert an HTML Area at level 0 of desired page, with the following content:

Explanation: When the script above is executed on the body of the page, a reference to the original function is stored in orig_%SubmitScriptName. %SubmitScriptName is then redefined to a custom function. Now when the user performs an action and %SubmitScriptName is invoked, it would be the custom function that gets called.

Inside the custom function, it checks if the action being performed is the targeted action. If so, then a confirm dialog is presented. The custom function exits without invoking the original function if the cancel option was selected. The above coding trick is possible because functions are objects in javascript. The .apply method is a javascript feature that allows orig_%SubmitScriptName to be invoked with the same arguments used to call the current function.

Objective: When the page is submitted, lock all fields, buttons and links to prevent the user from resubmitting the page while the server is processing the request.

Sample Solution: Insert an HTML Area at level 0 of desired page, with the following content:

Explanation: After the original function is invoked, the modified function loops through all the visible form fields (this would include the buttons) and disable them. It is important that the disabling of fields is performed after the form is submitted. This is because browsers do not include disabled fields on the data sent to the server.

Afterwards, the modified function loops through all the hyperlinks and disables them by canceling the default action of the click event.

Objective: There is currently no PeopleCode events associated with scroll actions. For some reason, you want to detect in PeopleCode whenever the user performs a scroll action.

Sample Solution: Create a subpage with the following fields:EVENT_LOG_SBP subpage

Here, the 2 editboxes are invisible with Modifiable by JavaScript property set to checked. Insert the subpage at the level 0 of desired page. Set the content of the HTML Area with the following:

Now on the PeopleCode side, the following template code could be used on DERIVED_WORK.ACTION_DESCR.FieldChange:

If All(DERIVED_WORK.ACTION_DESCR) Then   Evaluate DERIVED_WORK.ACTION_DESCR   When = "hpers"      /* Personalize action was performed */      Break;   When = "hfind"      /* Find action was performed */      /* Search text can be retrieved using %Request.GetParameter("ICFind") */      Break;   When = "hviewall"      /* View All action was performed */      Break;   When = "hexcel"      /* Download to Excel action was performed */      Break;   When = "htop"      /* View First action was performed */      Break;   When = "hup"      /* View Previous action was performed */      Break;   When = "hdown"      /* View Next action was performed */      Break;   When = "hend"      /* View Last action was performed */      Break;   When = "htab"      /* Show All Columns action was performed */      Break;   When-Other      Evaluate Left(DERIVED_WORK.ACTION_DESCR, 3)      When = "srt"         /* Sort Column action was performed */         /* Column # is Substring(DERIVED_WORK.ACTION_DESCR, 4, 1) + 1 */         Break;      When = "tab"         /* View Tab action was performed */         /* Column # is Substring(DERIVED_WORK.ACTION_DESCR, 4, 1) + 1 */      End-Evaluate;   End-Evaluate;End-If; REM Clear the hidden field buffers;DERIVED_WORK.PAGE_FIELD_NAME.SetDefault();DERIVED_WORK.ACTION_DESCR.SetDefault();

Explanation: Prior to invoking the original %SubmitScriptName function, the modified function inspects the value of the 2nd parameter (arguments[1]). If the pattern matches a scroll action: DERIVED_WORK.PAGE_FIELD_NAME is populated with the scroll page field name, and DERIVED_WORK.ACTION_DESCR is populated with the action code.

On the server side, DERIVED_WORK.ACTION_DESCR.FieldChange is executed because of the change. The 2 hidden fields’ values needs to be cleared at the end of the PeopleCode, in order to capture when the same scroll action is performed consecutively.

Take Note: On the server side, the FieldChange event is executed before the action is actually performed. This means that if you check the TopRowNumber property of the rowset when a View Next is performed, you won’t get the new value.

The above 3 sample solutions can be combined into one. See this in action.

When performing the modification on %SubmitScriptName as illustrated above, it may be rightful to be concerned about future incompatibilities. For example, what if a future service pack or version changed the parameters for %SubmitScriptName? Would it totally break your component?

Because of this, it is prudent to check that scripts calling %SubmitScriptName are passing our expected parameters. Otherwise then, the modification is skipped. This can be achieved by performing the following check at the start of the redefined %SubmitScriptName function:

  %SubmitScriptName = function() {    // invoke the original function if the parameter signature changed    if (arguments.length!=2 ||     !(arguments[0].nodeType && arguments[0].nodeType==1 && arguments[0].tagName && arguments[0].tagName=='FORM') ||     !(typeof(arguments[1])=='string')) {       orig_%SubmitScriptName.apply(this,arguments);      return;    }

Also, the sample solutions presented above have the javascript embedded in the HTML Area as constant. This is just to simplify illustration. The best way is to place javascript code in an HTML definition and link to it using a %JavaScript meta-HTML, as described here.

Related Posts

Using MsgGetText to Concatenate Strings

Lately, I’ve been using the MsgGetText() built-in function to concatenate adhoc strings in PeopleCode. For example, instead of the following:

Local string &TEXTLINE = "Value of " | &fld1name | " is " | &fld1value | ".";

Using MsgGetText, it can be re-written as follows:

Local string &TEXTLINE = MsgGetText(0, 0, "Value of %1 is %2.", &fld1name, &fld1value);

I find that the latter is easier to read and modify compared to the first, especially if there are a lot of values being concatenated.

What about performance? Wouldn’t the MsgGetText code needlessly query the database for message (0, 0)? Fortunately, I think not. Some tests with SQL trace turned on — and the cache freshly cleared — show that a query to the message catalog for message (0, 0) is never performed by the application server. A wonderful optimization.

Friday 2 September 2011

Set Processing 101

When I was reading the What’s New with Batch Processing in PeopleSoft Enterprise Oracle OpenWorld presentation some time ago, the following slide caught my attention:

What are the Problems with AppEngine

These programs can be complicated – and for a programmer they’re differentSame logic can be used Batch and Online – Really? Different transactional modelTemp table behavior is very differentNo restartabilityEasy to write a poor performing App Engine Program Since the introduction of PeopleCode, poor performing programs are the norm

Admittedly, I don’t have a lot of experience writing batch programs on Application Engine. But I believe the primary reason it is so easy to write poor-performing AE programs is that AE batch programs are better suited to be programmed using set processing. Set processing requires a different mind set to what procedural programmers are used to. I am new to it as well, so I find that this discussion in ITToolbox, and this followup provides valuable insights on how to perform set processing. Steve’s technique of what he calls partial cartesian joins is quite useful as well, especially for those not running an Oracle database.

PeopleSoft Search

If you’ve been browsing my blog directly, you may have already noticed the PeopleSoft Search link on the site’s header. This is simply a Google Custom search engine pointing to sites containing relevant PeopleSoft technical content. This includes mostly forums and blogs.

I find this useful when I need to search for keywords that are not specifically related to PeopleSoft. Following is an example result when searching for “excel”:
Sample Search result

I still have trouble filtering out RSS from the results, if anyone can help me with that.

Now, if you’re browsing my site using Firefox 2, you may also notice the following auto-discovered PeopleSoft Search item on your search bar:
Firefox Search Engines

Following is how the auto-discovered search would like it IE7:
IE7 Search Engines

This plugin is packaged using the OpenSearch standard, as described in this Mozilla article.

The plugin can also be installed by clicking the following link:

Install PeopleSoft Search

ExcelToCI Error Occurred in Routine sendSOAPRequest_SubmitToDB: The Operation Timed Out

When I was trying to upload about 7000 rows using ExcelToCI for a custom component, i was getting  the following error,


Error occurred in routine sendSOAPRequest_SubmitToDB:
Error:
Number: 2147012894
Description: The operation timed out


After checking the web server and appserver access log, I found the following issues and i have followed the following steps to resolve the issues,


1.I have found that ExcelToCI uses SERVERXMLHTTP MSXML 6.0 object to send the SOAP request to the webserver,
Set xHTTP = CreateObject(“MSXML2.SERVERXMLHTTP.6.0?)
This request had a default 30 second timeout for receiving a packet of response data from the target server,
Check the link : http://msdn.microsoft.com/en-us/library/ms760403 for more details on timeouts.


2. After checking the webserver access log (PIA_Access.log), i have observed that some of the POST requests are taking about 59 seconds to complete and hence the error was occurring.


To resolve this issue, i have changed the VB Macro code in ExcelToCI spreadsheet as follows


=======================================================


Added  this line before xHTTP.send xDoc.xml in Staging And Submission Module under function sendSOAPRequest_SubmitToDB
Dim lResolve, lConnect, lSend, lReceive As Long
lResolve = 60 * CLng(1000)
lConnect = 90 * CLng(1000)
lSend = 90 * CLng(1000)
lReceive = 120 * CLng(1000)


xHTTP.setTimeouts lResolve, lConnect, lSend, lReceive
=======================================================


Even after changing this value, the ExcelToCI was still failing.  Once again I checked the web server & appserver log and found that after loading about 50 to 60 rows, request is taking more than five minutes to respond and appserver is killing the appserv thread and therefore I was getting the error ‘The Operation timed out’.


To overcome the issue,one can increase the XMLHTTP timeout and also increase the appserver timeout or find out why a request is taking more than 5 minutes to complete. Using Precise i3 performance monitoring tool and also the live Oracle session, I have found out the following issues,


1. Component Interface was firing sql to fetch location code description, using a view that was not correctly joined with other large table using location code.


2. A Save Edit Peoplecode was written at Level 2 to fetch some data from the Oracle table using SQL Exec. This was causing this sql to fire 160,000 times as it was firing for every row in the scroll as new rows are being added.


I have followed the below steps to improve the performance

Removed the related display field from the page. Alternative option was to tune the sql for related display field.Moved the save edit code to field edit, so that it fires only for the newly inserted rows. Alternative option was to write conditional logic to see if row is changed.

After the above changes, the process finished inserting 7100 rows in 23 minutes. Only two request exceeded the default timeout. One took 32 seconds to respond while the other 35 seconds.


I have also noticed that if chunking factor is reduced to 1 to have smaller number of rows processed, PSAPPSRV is restarting due to recycle count of 5000 being reached, and this results in a login Error and HTML (invalid XML) data is being sent to the excel. The only solution to this issue is to increase the recycle count temporarily and change it back to original. Fortunately this parameter is dynamic and does not require restarting the appserver.


Changing the Userid When Triggering the Subscription PeopleCode

The IntBroker(IB) Class method: SwitchAsyncEventUserContext can be used to change the context of the peoplecode running inside the subscription peoplecode. This has to be used by IB only (Checks are available to validate it) and can only be used for IB events that are fired asynchronously (OnRoute, OnSend, OnNotification, etc.). One use case would be, if someone is submitting a process request from a self-service user id and they do not want to give access to query security to each users who are triggering the message. This method is added in PT 8.50 and is not available for lower tools release.


For more information use: E-IB: User Security required on target db for asynchronous messages in 8.48.0x [ID 654592.1]


PeopleBook definition for this method is as follows:


SwitchAsyncEventUserContext


Syntax
SwitchAsyncEventUserContext(UserID, LanguageCode)
Description
Use the SwitchAsyncEventUserContext method to switch the user context within an Integration Broker asynchronous event
Parameters
UserID
Specify the user ID as a string, to which the context has to be  switched.
LanguageCode
Specify the language code, as a string for the user ID
Returns
A Boolean value: true if the switch user was successful, false otherwise.
Example
&returnValue = %IntBroker.SwitchAsyncEventUserContext(“VP1?, “ENG”);


E-UPG Alter Error: Unable to Retrieve Current DDL Space. Alter Processed Failed. (76,47)

An Alter process during the Tools Only Upgrade  failed with the following error:


ERROR:
————
SQL Build process began on 3/17/2004 at 4:06:26 PM for database ****.
Error: ACCESS_GRP_LANG – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: AE_SYNCGEN_AET – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: AELOCKMGR – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: AERUNCONTROL – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: AERUNCONTROLPC – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: AETEMPTBLMGR – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: APPMSGARCH_AET – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: APPR_HDR_LNG – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)
Error: APPR_RULE_HDR – Unable to retrieve current DDL space name.  Alter processed failed. (76,47)
Error: Fatal error in function BldAlter on call to function GetOldRecDefn.  Return code = 1. (76,6)


SOLUTION:
————–  
In the PSSTATUS table, the OWNERID column data was in lowercase. When the data got converted into upper case, the error got resolved and the Alter script ran without any issues.


Page Data is Inconsistent With Database

If the message ‘Page data is inconsistent with database’ appears while saving the page, please refer the following resolution in MOS (My Oracle Support).


E-AS: How to Trace “Page data is inconsistent with database” error? [ID 655907.1]


Step 1: Set the following in psappsrv.cfg


TracePPR=1
TracePPRMask=32767


Step 2: Go to the PIA and before logging on, add & trace=Y (uppercase) at the end of the web address and press the ‘Enter’ key in the keyboard. Check the first five SQL options and for PeopleCode the ‘List Program’ & ‘Each statement’ options.


Step 3: Log in to PIA and reproduce the error.


Step 4: Check the trace, especially the portion which contains the below information:
PSAPPSRV.28630    1-167605 11.00.03    0.001 Record RO_LINE_ATTR.ROW_LASTMANT_DTTM database value “2007-06-11-10.58.44.000000? page value “2007-06-11-10.05.30.000000?
The trace should clearly show the field that is producing the error as well as the values that are populated both on database side and on page side.


The most common reason to encounter this issue is:


When you use a view to select data into a scroll based on a table and no Auto select option is turned on. The number of columns in view and scroll area base table differs and the additional column in base table contains not null values. Auto update for scroll can be used to change the value of the field in a scroll and save it.


To resolve this issue, add same number of columns to view similar to the base table or if possible, make the same view as a base record for the scroll that is used for selection.


Another reason could be using SQLExec in SavePostChange to update the Base Table Record and therefore changing the value.


Thursday 1 September 2011

AWE – eMail Template SQL Object(s)

You must create SQL Object(s) if you wish to use binds values in your email notifications.


Below is an example of how a SQL object can be created to populate an email template:


SELECT A.TRANSACTION_NBR


,A.EMPLID


,B.NAME


,A.TRANS_DT


FROM PS_EXP_RPT_HDR A


,PS_PERSON_NAME B


WHERE A.EMPLID = B.EMPLID


AND A.LINEID =:2


In this example, the AWE will look to populate the %2 bind with TRANSACTION_NBR, the %3 bind with EMPLID, the %4 bind with NAME, and the %5 bind with TRANS_DT. Also note the “:1” bind in the where clause of the SQL Object. It is  mandatory requirement to have all of the keys from your header record (or line level record depending on the notification) bound into the where clause. The AWE uses the header record keys to retrieve the correct row from the SQL Object.


PeopleSoft – Remedy Integration

Client: Leading Healthcare Solutions Provider


Solution: PeopleSoft – Remedy Integration


The client was a leading Healthcare Insurance, Medicare and Medicaid Programs provider and they wanted to integrate their existing PeopleSoft system with the Remedy, IT service management suite, to synchronize and get single source of truth of their asset information. The Drivestream team studied the client’s complex business processes to understand the data flow between the Remedy and their PeopleSoft system and proposed an auto-trigger dual integration program, which would run as a part of night job. The team configured PeopleSoft integration broker to send and receive data from the Remedy system and also built a process to segregate the valid data in PeopleSoft that has to be sent across to the Remedy system. The systems were seamlessly integrated and the client was able to get a holistic view of their asset information.


Prompt Values Specified on Add Mode Search Record is not Enforced When Using ExcelToCI

While creating component interface, by default it will not enforce the prompt values specified on Add search record and will allow you to enter values even though they are not valid. This issue occurs when inserting new rows using ExcelToCI as it allows the user to enter invalid values without giving any error message.


To avoid this issue, open up the Add Mode Search Record for the component and go to Record field properties for the search fields and check the Search Edit check box.  This will enforce the use of valid values when adding a new row using component interface used in ExcelToCI. By default, Search Edit is not enabled.


Below is the description of this field in PeopleBooks.


Search Edit is enabled only if Search Key is selected. Selecting this option enforces the required property and table edits on the search page. It also enforces these edits under circumstances where the search page would normally be bypassed. With this option, the user no longer has the ability to perform partial searches on this field.


Below is the MOS (My Oracle Support) link related to this issue.


E-CI: Component Interface Does Not Validate Record Edits (Against Prompt table) When Using Create [ID 664377.1]


Does Row Level Security Work in ExcelToCI? (Doc ID 972241.1)


As per the above resolution, row level security is not enforced using ExcelToCI.


User is Unable to see Pagelet on a Home page

If a user is not able to see Pagelet on a Home page despite having access to it, then it indicates that the Webserver Pagelet cache is corrupt. The only way to overcome this issue is to restart the webserver. But if this problem occurs during the middle of a day, then the below steps can be followed to force the webserver Home page Pagelet cache refresh.

Add a new page to Home page tab as a required fix (PeopleTools –> Portal –> Structure and Content –> Portal Objects –> Home Page –> Tabs ->Home).

Go to the tab – ‘Content Tab’ and add the new Pagelet as required fix and select the column (usually the last column). Save it and re-login with the id of the user who is not able to see the Pagelet. After this step, the user should be able to see the missing Pagelet. Remove the newly added Pagelet, as it is no longer needed. The following sql can be used to determine which Pagelet that user has access to.

SELECT * FROM PSPRUHTABPGLT where oprid = ’7420060' ORDER BY portal_col_num,portal_row_num;

For further reference, please visit MOS (My Oracle Support) and see the following resolution.

E-PORTAL: What Are The Tables Used By Portal Technology? [ID 651342.1]

Tags: , , , ,

Application Engine Program: PSPAL::Abort: Unexpected Signal Received

When we create an Application Engine program which refers to a State Record, and migrate it to other environment without migrating the State Record, it will get migrated successfully. When we try to run this program on the Batch Server, the following error message will appear.


Record XYZ not defined (108,505)
1341: 1301685557: PSPAL::Abort: Unexpected signal received
1341: 1301685557: PSPAL::Abort: Location: /vob/peopletools/src/pspal/exception_sigaction.cpp:492: RecoverableSignalHandler
1341: 1301685557: PSPAL::Abort: Generating process state report to /xxx/xxx/scripts/LOGS/psae.1341/process_state.txt
1341: 1301685557: PSPAL::Abort: Terminating process now.


In Windows
2564: 1301686035: PSPAL::Abort: Unrecoverable exception received
2564: 1301686035: PSPAL::Abort: Location: E:\pt85010b-retail\peopletools\SRC\pspal\exception_winunhandled.cpp:577: PSPAL::UnhandledExceptionFilter::RecoverableExceptionFilter
2564: 1301686035: PSPAL::Abort: Abort diagnostics generation is currently disabled
2564: 1301686035: PSPAL::Abort: Terminating process now.
PeopleTools 8.50.10 – Application Engine


Record XYZ not defined (108,505)
Message Set Number: 108
Message Number: 505
Message Reason: Record XYZ not defined (108,505)


Solution


Copy the missing AET Record to the target database and its application engine program will work fine.


Menu Items Not Getting Displayed in PeopleSoft PIA Page

In the PeopleSoft PIA page, some of the menu items might not get displayed due to it’s expire date – ’2010-12-31'. This issue can be tackled by following the below mentioned steps,

Run the below script to update the PORTAL_EXPIRE_DT

  update PSPRSMDEFN set PORTAL_EXPIRE_DT=’2099-12-31' WHERE PORTAL_EXPIRE_DT=’2010-12-31'


  SELECT PORTAL_EXPIRE_DT from PSPRSMDEFN where PORTAL_EXPIRE_DT <> ’2099-12-31'

In the PIA page, goto PeopleTools–>Portal–>Portal Security Sync and enter the new Run Control ID and run the process

After the sucessful run of the process,

Restart the process scheduler, the application server and the web serverClear the cache and the browser cache

All the menu items  in the PIA page will get displayed.


Wednesday 31 August 2011

Restrict external access to PeopleSoft with Squid


I recently had to expose a client’s PeopleSoft installation to the outside world, which I did in the usual manner (additional PIA in the DMZ etc).


We wanted to use the “closed by default, open by exception” approach, so we would start by blocking access to everything and then open the areas we needed access to URL by URL.  I suspected that the final ‘URL Whitelist’ might take many iterations to get right and as the Reverse Proxy in the DMZ was outside of my control I needed to trial it somewhere else first.


I commandeered one of our less frequently used environments and went about searching for a quick/free method of blocking access.  After trying a few different approaches I settled on Squid, the open-source forward-proxy / web-caching server.  Although it’s better known for running on Unix systems, there is a Windows implementation and it can operate perfectly well as a reverse-proxy.


Once I’d downloaded and unzipped the binaries, and installed it as a service (using this helpful write-up as a guide) it was just a case of setting the rules.


In the ACLs section I added my bad and good URLs:

acl bad_url urlpath_regex *DEV*acl good_url urlpath_regex "c:\squid\etc\good-urls.squid"

This would block any URL with DEV in (my chosen environment was DEV), but then allow any URLs in the ‘good-urls.squid’ file.  I then had specify in the http_access section what to do with these ACL groups.

http_access allow good_urlhttp_access deny bad_urlhttp_access allow all

It took me a few goes to get this right as the last line confused me for a while, but luckily there are copious notes in the provided .conf file:



If none of the “access” lines cause a match, the default is the opposite of the last line in the list.  If the last line was deny, the default is allow. Conversely, if the last line is allow, the default will be deny.


I was happy leaving my PeopleSoft environment on port 80 and Squid on 3128 as this is just a temporary setup for my testing.  Obviously Squid would be on port 80 if this was a production setup.


I amended the default port line thus:

http_port 3128 defaultsite=xxx.yyy.com

(where xxx is the hostname and yyy is the domain name)


And finally I added this line:

cache_peer 127.0.0.1 parent 80 0 originserver default

I used 127.0.0.1 as Squid is on the same host as the PIA, and the rest is for forwarding.


In the Web Profile ‘Virtual Addressing’ tab, add the reverse proxy details.  This willensure that PeopleSoft uses the reverse-proxy port number.  Bounce the PIA.


If you want a nice custom ‘Access Denied’ page instead of the default Squid one, they can be found in ‘C:\squid\share\errors\English’.  They have no file extension, but they’re HTML so a cinch to amend.


This is largely going to vary depending upon what you want to expose to the external users.  A lot of what we opened up were custom pages so there isn’t a lot of value sharing the full file here.  Having said that, here is a snippet of our file:

*login**css*/psp/ps/EMPLOYEE/HRMS/h/**/cs/ps/cache/**/ps/images/**/psc/ps/*viewattach**/psp/ps/EMPLOYEE/HRMS/c/ROLE_EMPLOYEE.GP_SS_EE_PSLP.GBL**/ps/ckeditor/**/psc/ps/EMPLOYEE/HRMS/c/HRS_HRAM.HRS_CE.GBL**/psp/ps/EMPLOYEE/HRMS/c/HRS_HRAM.HRS_CE.GBL**/psc/ps/EMPLOYEE/HRMS/s/WEBLIB_TIMEOUT.PT_TIMEOUTWARNING.FieldFormula.IScript_TIMEOUTWARNING*/psc/ps/EMPLOYEE/HRMS/\?cmd=expire*/psp/ps/EMPLOYEE/HRMS/\?cmd=expire*/psp/ps/EMPLOYEE/HRMS/\?cmd=logout

Lines 1 and 2 sort out the signon page.


Line 3 is the Employee Portal homepage.


Lines 4 and 5 are for images.  Lines 6 and 8 are for viewing attachments and the Rich Text editor.


Lines 7, 9 and 10 are sample PeopleSoft pages/components.


The remainder deal with the timeout and signout links.


(Assuming that your PIA site is ‘ps’)


And you’re done.  There are a few little quirks to note.


Firstly, every time you change your URLs file you’ll need to restart the Squid service, but it’s a quick process so doesn’t hold you up too much.


Secondly, PeopleSoft frequently uses the ‘?’ special character as a URL delimiter so Squid only matches against the characters before this point.  There are several occasions when you need to match against the full URL which is why I’ve used url_path_regex in the ACL section above.  This allowed me to escape the special characters so that the log-out, time-out and view attachment links work ok.

Be the first to like this post.

PeopleSoft and IE9


It seems that IE9 behaves slightly differently to other browsers when displaying some PeopleSoft pages, and this results in pages that look a little odd.  Areas of whitespace appear between page objects, and fields that are nicely laid out in other browsers are mis-aligned in IE9. Strangely it doesn’t happen on the homepage, but it does on every other page.


Here’s an example:


So what causes it, and what can be done about it?


It seems as though the disparity between the homepage and other pages is caused by the browser switching between the Standards and Quirks rendering modes. I’ve performed cursory testing in Firefox (v4.0), IE (v8.0 and v9.0) and Chrome (v10.0) and they all render the PeopleSoft homepage in Quirks mode by default and other pages in Standards mode.  I suspect that this is due to the lack of a doctype in the homepage – as this is present in other pages.


There’s an excellent bookmarklet here which tells you which render mode you’re currently in (although you can also use browser specific tools like Firefox developer’s toolbar and the IE Dev Tools).


Regardless of which mode Firefox and Chrome are in they render the page correctly (and by this I mean ‘as we are used to seeing it’, it may not be syntactically correct!).  The same is true for IE8, it’s just IE9 that displays the page differently if in Standards mode (which it will be for all pages other than the homepage.


So, how do we fix it?  I basically insert a directive into the PeopleSoft HTML template for all non-homepage pages telling IE to act like an earlier version.  It’s not the most elegant solution but it seems to do the trick, at least until something official comes along.


Open PT_HNAV_TEMPLATE and look at the 4th line.  It should look like this:




Comment this line out and add a line below, thus:





You shouldn’t even need a Web or App Server reboot.  The new template forces IE9 to behave like IE7 and displays your PeopleSoft pages correctly.

Be the first to like this post.

Changing the Favicon in PeopleSoft – The “How to”


Last week I posted a blog entry highlighting why I think adding a favicon to PeopleSoft can be a helpful visual aid for your users.  This post walks through how I did it – note: I’ve only tested this in Tools 8.50.


It’s probably a good idea to have one for each environment excluding Production that shows the environment name, and then have Production as the corporate logo (or your PeopleSoft system logo etc).  I created my 32×32 pixel images in GIMP as it can save as a .ico file, but any graphics package will do (as will this online ico creator).  I didn’t experiment with other sizes or file formats, let me know if you do and I’ll update the post.


Upload your icons as images in App Designer.


We need to create a function to provide the correct image for each environment as we’ll be calling this from more than one place.  I added my function to WEBLIB_PT_NAV.ISCRIPT1 as we’ll be customising it later anyway.

Function GetFavicon() Returns string Local string &Favicon; Evaluate %DbName When = "DEV" &Favicon = %Response.GetImageURL(Image.<>); Break; When = "TST" &Favicon = %Response.GetImageURL(Image.<>); Break; ...etc... End-Evaluate; &Favicon = ""; Return &Favicon;End-Function;

You need to amend both PT_HNAV_TEMPLATE and PT_IFRAME_HDR_SWAN HTML templates so that the code for the Favicon can be passed in.


Amend PT_HNAV_TEMPLATE thus (I’m just showing the top 6 lines – lines 4 and 5 are the ones I’ve added):

%bind(:23)
...

Amend PT_IFRAME_HDR_SWAN thus (I’m just showing the top 5 lines – lines 3 and 4 are the ones I’ve added):

%bind(:25)...

Note: Your bind numbers may vary. You can check they’re correct when we get to the calling functions shortly.


The final step is to amend the PeopleCode so that the string provided by our GetFavicon function is passed into our HTML definitions.  Open PT_BRANDING.BrandingBase.  Scroll down to where the delivered code is declaring functions (it’s around line 155 for me) and declare the function that you created in Step 2.


Next, find method ‘getIframeHeaderHTML’ and scroll down to near the bottom.  You’ll see a call to one of the HTML objects that you just amended ‘PT_IFRAME_HDR_SWAN’.  Add your function as a parameter to the end thus:

&hdrHTML = GetHTMLText(HTML.PT_IFRAME_HDR_SWAN, &charSet, ... , &hoverNavLoc, GetFavicon());

As a double-check, you should also make sure that it’s the same number parameter as the bind variable that you added in the previous step.


You’ll need to make a similar change for the other HTML template.  Open WEBLIB_PT_NAV.ISCRIPT1.FieldFormula and search for the function ‘buildIframeTemplate’.  Again, scroll down to the end of the function and add your function as a parameter to the end:

Return GetHTMLText(@("HTML." | &templateHTMLObjName), &charSet, &requiredToolsSS, ... , &ptcxmCollapseImgURL, GetFavicon());

Again, make sure that the parameter number matches the bind number in the HTML file (PT_HNAV_TEMPLATE) earlier.


You should be able to sign in and see the results immediately.  Good luck and let me know how you get on!

Be the first to like this post.

Error in Recruitment – Build Applicant Search


This probably won’t help a great many people, but for the small minority it does help it might save them a lot of time …


There’s a problem with the Applicant Search process in HR9.1 (we’re currently on MP2).  When you build the Applicant Index it starts the HRS_SRCH_IDX process.  This App Engine starts one or more HRS_SRCH_APP processes.  Sometimes HRS_SRCH_APP runs to Success, other times it doesn’t.  Initially we thought this was down to locking (if there are more than one running simultaneously one was trying to delete from a table that the other was inserting into), however we set the concurrency to 1 and this was still occurring.


Examining the log files we could see that it loops through all languages in the system (regardless of how many languages had been installed) and creates a subdirectory under ps_cfg_home\data\search\HRS_ResumeText\\ for each language. The process gets as far as Italian and then fails (it creates an ITA directory and all the containing files, but does not create JPN – the next language).


We checked out customer connection My Oracle Support and there wasn’t a great deal.  The only relevant post we could find was this one which suggested deleting the JPN language from PSLANGUAGES (and I suspect all of those following JPN).  Unfortunately we need multi-language support so this wasn’t a viable option for us.  There wasn’t anything on Google either so we were on our own.


Looking through the log files we found this:
mkvdk - Verity, Inc. Version 6.2.0 (_nti40, Jan 30 2008)
Error   E0-1509 (Drvr): dlopen() returned:
Error   E0-1510 (Drvr): Error loading driver library 'D:\ps_home\verity\winx86\_nti40\bin\locbasis.dll'
Error   E0-1203 (Language): Error reading language definition file: D:/ps_home/verity/winx86/common/japanb/loc00.lng
Error   E0-1230 (Language): Could not create locale japanb
Error    (): Fatal error - exiting
mkvdk done
mkvdk: VDK error -200: couldn't create VDK session
Both of the files referenced in the error message (locbasis.dll and loc00.lng) are present and read/write to the Process Scheduler user account though, so this wasn’t much help.


The code in the App Engine calls a fair sized chunk of Application Package PeopleCode, but eventually I found the logic that creates the directories/Verity Search collections.  The last command issued before the error was:


bin\server\winx86\mkvdk -create -collection -locale japanb d:\ps_cfg_home\data\search\HRS_ResumeText\TST\JPN -logfile d:\ps_cfg_home\data\search\HRS_ResumeText\TST\veritybuild.log


When I run this in a command prompt window (after setting the ps_home env var) I get the following error message:


The program cannot start because MSVCP71.dll is missing from your computer.


Interesting, so I have a missing dll.  Using Process Monitor (the SysInternals one, not PeopleSoft Process Monitor) I can see that it’s looking for the dll in ‘\verity\winx86\_nti40\bin\’.



Once I located a copy of the DLL and copied it there the HRS_SRCH_APP process ran fine and the directories were created for all languages.


So why is this file missing?  I believe it’s an issue of Oracle assuming that Microsoft bundles it in Windows, and Microsoft no longer doing so.  See this from Microsoft:



The shared CRT DLL has been distributed by Microsoft in the past as a shared system component.  This may cause problems when you run applications that are linked to a different version of the CRT on computers that do not have the correct versions of the CRT DLL installed. This is commonly referred to as the “DLL Conflict” problem.  To address this issue, the CRT DLL is no longer considered a system file, therefore, distribute the CRT DLL with any application that relies on it.

Be the first to like this post.

OpenWorld 11 / Suggest a Session on Oracle Mix


I’ve never been to OpenWorld and I’d love to go.  There are so many US based PeopleSoft people that I’d love to meet.


I noticed the ‘Suggest a Session’ post on the Oracle Mix blog and thought I’d give it a go.  I’d be petrified at the thought of talking to an audience the size that you get over there, but sometimes you have to try these things.


I’m a bit late to the game, but if anyone fancies either of the topics I’ve put forward I’d appreciate a vote:


Case Study: Deliver engaging Self Service with an additional PeopleSoft portal



Join me for a Case Study of how a green-field PeopleSoft retail client in the UK used HR9.1 and PeopleTools 8.50 to turbo-charge the user experience of their Employee and Manager Self Service users. This will be a demo intensive session as I walk through the steps to deployment and show how you can deliver a genuinely engaging interface for your employees without needing products from outside the Oracle stable. The retail client is live in the UK and coming to the US soon!


Case Study: How The Cloud accelerated the PeopleSoft project of a UK retailer



Join me for a walk-through of how we used ‘the Cloud’ to dramatically speed-up the PeopleSoft implementation for a greenfield UK retailer. This isn’t another “theoretical cloud talk”, I’ll detail how it worked in practise. It improved our access requirements, reduced infrastructure costs and gave us access to more powerful servers and greater resilience than we’d otherwise have been able to afford. I’ll walk you through the initial decision, explain how everything was set up and demonstrate the benefits delivered to the project. I’ll also describe other occasions where the flexibility of PeopleSoft in the cloud has been invaluable.


Click on the headers to go to the voting page (you’ll need to sign-up for Mix if you don’t already have an account).


Thank you!

Be the first to like this post.

Custom toolbars on PeopleSoft Rich Text Boxes


If you’re on Tools 8.50 or 8.51 you’re probably familiar with the new Rich-text edit boxes by now.  They allow you to amend the text with formatting, colour, links, images etc.  This is how a field looks when the default Rich Text toolbar is applied:


This is all very good when the field is in a nice empty page, where there’s plenty of space for a large toolbar.  Many pages have a lot of fields on, and the addition of a bulky toobar might make the page appear busier and more crowded.  Also, some users may get confused with the wide choice of buttons available.


I faced a similar issue today.  I needed to have the user enter some text and be able to embed links, but because of the design aesthetics of where the results would be output, I wanted to discourage the user from having lots of different colours, font sizes etc. So I wanted to reduce the toolbar so it had just two buttons – add link and remove link.


It turns out that there’s a pretty simple way of customising the toolbar. 


Against the Page Field properties of the Long Edit box there is an Options tab (you probably used it to make the field Rich Text).  The first drop-down allows you to select alternate configurations (they’re all HTML Objects).  There isn’t a delivered one that did what I wanted, so I took an existing one and modified it.


I opened an existing one (‘PT_RTE_CFG_PTPPB’) and took a look at the contents:


FCKEditor configuration file for Pagelet Wizard HTML Data Source
-->
CKEDITOR.config.skin='office2003';
CKEDITOR.config.toolbar =
[
['Source','-','Maximize','Preview','Print','-','Cut','Copy','Paste','-','Undo','Redo','-','Find','Replace','-','HorizontalRule','Table','imageUPLOAD','Link','Unlink','SpecialChar'],
['Format','Font','FontSize','-','Bold','Italic','Underline','Strike'],
['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','NumberedList','BulletedList','Outdent','Indent','-','TextColor','BGColor']
];


It’s pretty clear to see that each toolbar button is represented by an entry in the CKEDITOR.config.toolbar section. I cloned the delivered one and reduced the toolbar section down to:
CKEDITOR.config.toolbar =
[
['Link','Unlink']
];


This had the desired effect of reducing the toolbar to exactly what I needed, but it had introduced an unwanted bottom section which shows the HTML tags for the edit box.



There was nothing in the config file that I’d specified that had introduced this, so where had it come from?


It turns out that when you specify a config file, it overwrites the default values.  After a good deal of searching I located them in:


\webserv\\applications\peoplesoft\PORTAL.war\\ckeditor\config.js


Not only does it specify the defaults for the toolbar, but it also contains the lines:


config.resize_enabled = false;
config.removePlugins = ‘elementspath’;


Once I’d added these two lines to my config HTML object my rich text box displayed exactly as required – a much simpler and more compact edit box containing just the toolbar buttons that I want:


Be the first to like this post.

Changing the Favicon in PeopleSoft


A Favicon (short for favorites icon, also known as a shortcut icon, website icon, URL icon, or bookmark icon) is a small logo that appears next to the website URL in the browser address bar.  This website has the favicon from WordPress, as that’s the blogging platform that I use.


Although adding a favicon made the web surfing experience marginally more attractive (the favicon also appears in your bookmarks/favourites menu to make it easier to identify each website, for example) it was pretty unimportant to us in the PeopleSoft world.  Now that tabbed browsers are starting to proliferate into company workstation rollouts the favicon is starting to become more useful.


As an example, can you identify these 9 favicons from my open browser tabs (I’ve redacted the text from a couple as they’re pretty easy):



I’m quite a fan of finding methods to make it easy to differentiate your PeopleSoft environments.  I think it’s a useful productivity tweak to be able to instantly know whether you’re in DEV, TST or PRD without having to check the address bar and parse through the URL (for less technical business users especially).


Wouldn’t it be useful to have a different Favicon for each environment?  That way you can easily tell which tab you need.  When you’re trying to find a specific environment that you’ve logged into, how useful is it to go from this:


to this:



And with grouped taskbar buttons being the default in recent versions of Windows, it’s also handy to go from this:



to this:



So how is it done?


It’s not a big customisation, although it does obviously touch a couple of Tools objects.  I’ve written it up here.

Be the first to like this post.