I’ve had a few requests from people to document how I use the  PeopleCodeTools syntax highlighter in Sublime Text. Here’s a quick overview.

Firstly, the source code is freely available on github, for those that would like to contribute to it. And for those unfamiliar with installing this plugin using Sublime Text, all you need to do is first install Package Control, and then install the ‘PeopleCodeTools’ plugin from Package Control.

The plugin should work for PeopleCode methods (in Application Classes), Functions and Event PeopleCode when using ctrl/cmd + r to bring up the Goto Symbol prompt. Here’s an example of searching for Event PeopleCode on a PeopleCode dump:

Event PeopleCode

Here’s another example of searching for method PeopleCode:

Method PeopleCode

The extensions of the PeopleCode files need to end in either .ppl or .pcode.

I’ve also created syntax highlighters for .tracesql files. Although bear in mind that .tracesql files can sometimes generate code with unmatched quotes resulting in messed up syntax highlighting:

Messed up syntax highlighting

For this specific issue I’ve created a tool to tidy up .tracesql files (also available in the plugin). To run the tidy tool, run the “PeopleCode Tools: Tidy PeopleCode Trace” tool from the command palette:


The syntax highlighting should now look okay:

Tidied syntax highlighting

I’ve noticed that the syntax highlighting plugin slows the opening time for very large files (i.e. 50 MB or greater) due to the fact that the plugin uses regular expressions to create scopes. For this reason, I usually open up a PeopleCode dump at the start of my day and peruse it when needed. I’ve also noticed that the tidy command can take up to 60 seconds on 15MB tracesql files, so please be patient.

Also, when searching for text within large files, I’d recommend disabling the ‘Highlight matches’ option when searching large files:

Disable Highlight matchesIf ‘Highlight matches’ is not disabled, the search will try to instantly match every single character you type. I’m yet to figure out a way to toggle this functionality on and off, so I have to manually de-select it for now.

I’ve also noticed that if you are using the BracketHighlighter plugin, you’ll need to disable it by running ‘BracketHighlighter: Toggle Global Enable’ from the command line. If not, the response times for pretty much anything you do will be quite slow.

That’s all for now. Hope you guys find this plugin useful!

I’ve added another tool to the PeopleCodeTools Sublime Text plugin that allows you to extract the call stack from a PeopleCode trace. You can find it on the PeopleCodeTools repository on github along with the syntax highlighters for PeopleCode and PeopleSoft trace files.

For those unfamiliar with installing this plugin, please see my previous post: PeopleCodeTools – Syntax Highlighting for Sublime Text

This tool only applies to PeopleSoft Trace Files that have at a minimum the following trace parameters:

4044 Trace

To extract the call stack, open the .tracesql file (generated with the trace flags) in Sublime Text  and then run the “PeopleCode Tools: Extract PeopleCode Call Stack” command from the command palette:

Extract PeopleCode Call Stack - Run

The call stack of the trace file should then be extracted and formatted:

Extract PeopleCode Call Stack

I find this tool particularly useful when looking through large trace files and trying to understand where and in what context a particular line of code is invoked. For the most part, this tool works pretty well. I’ve been trying to fix bugs as I discover them. If you’ve installed the PeopleCodeTools plugin using Package Control, you should automatically receive these updates.


Here are some cross-browser bookmarklets I wrote that should allow you to navigate to a particular component irrespective of what environment you’re in:

PeopleCode Trace

SQL Trace


User Profile

Permission Lists

Process Monitor

To install, simply just drag the links onto your bookmarks/favourites bar.

To add your own, use the following as a template, replacing the <Menu>.<Component>.<Market> where appropriate:

javascript:var a=window.frames.location.pathname.match(/^\/ps[pc]\/(.+?\/)(.+?\/)(.+?\/)/),b=a[1];-1<b.indexOf(“_”)&&(b=b.substr(0,b.indexOf(“_”))+”/”);void window.open(“/psp/”+b+”_newwin/”+a[2]+a[3]+”c/UTILITIES.TRACE_SQL.GBL“,””,””);

I find them especially useful in the following situations:

  1. When you have to work with multiple environments and always need to go to these components
  2. When you don’t have access to the Navigation bar (e.g. when logged in using a certain role, or even when logged in to a different portal).

Although here are some important caveats:

  1. They only work once you have logged into your environment of choice.
  2. You need to have the appropriate security assigned to the logged in user before being able to navigate to these components.

I encountered the issue mentioned on the following page:


I was trying to disable a save warning that was occurring on a secondary page that I was manually populating. I purposely de-selected all of the Set Component Changed fields on the page and even added hidden fields (eg. key fields) on the page so that I could de-select the Set Component Changed values for all of the fields in the record:

de-selected Set Component Changed property

Unfortunately I still received the Save Warning. I tried debugging the javascript as was suggested by the author in the link above, but I noticed (along with Dan Kibler [see his comments in the link above]) that the code was breaking before the author’s suggested breakpoints.

I managed to resolve this issue by following Dan Kibler’s advice in using the undocumented PeopleTools function SetSaveWarningFilterSetSaveWarningFilter(True) disables the Save Warning while SetSaveWarningFilter(False) enables the Save Warning. I also managed to resolve this issue by setting to False the SetComponentChanged property of the rowset that was causing the issue.

As a general rule, I propose that if you know the rowset that is causing the issue then you should set the SetComponentChanged property to False since it makes for easier maintenance. The SetSaveWarningFilter option on the other hand, is more of a generic solution for cases where it’s difficult to find out exactly what is causing the issue.

Update: I have changed this post based on Graham’s recent comments regarding Trace Magic since the trace settings that I recommended were not actually compatible with Trace Magic. Please see the following link for information regarding Trace Magic:


However, when manually reading a trace file (e.g. in Sublime Text, Notepad++, etc.) I would recommend the following trace settings:


I still find these settings useful for non-performance related debugging issues.

I was running a PeopleSoft Application Engine process that I suspected was hogging the CPU on a Windows environment. I wanted to see whether this process was in fact the cause of the CPU intensive activities on the database.

Interestingly, I discovered that on a Windows environment, an Oracle instance is composed of one oracle.exe process with many different threads. Each thread represents either a background process (PMON, SMON, etc.) or a foreground user session. So, when you are running Oracle server on a Windows environment and encounter a situation where the server CPUs are nearing 100% utilisation, Task Manager only reveals that oracle.exe is taking up the CPU time. There are no details as to which specific thread or session is responsible for the high load.

Fortunately, I managed to find out which thread was responsible for the CPU hogging by downloading a tool (ProcessExplorer by sysinternals) that supports displaying threads within processes. You can download that here.

Process Explorer shows all the processes that are currently running. After double-clicking on the oracle.exe process, I was able to find the TID (Thread ID) that had the highest CPU utilisation. I then ran the following query in SQL Developer, substituting :1 for the TID that had the highest CPU utilisation.

[sourcecode language=”sql”]
select proc.spid TID, sess.username, sess.osuser,
sess.status, sess.sid, sess.program
from v$process proc, v$session sess, v$bgprocess bg
where sess.paddr = proc.addr
and bg.paddr(+) = proc.addr
and proc.spid in (:1);

This query can be modified to include more columns to be displayed from v$session, v$process and v$bgprocess depending on your specific preferences.

I was also able to identify the specific SQL that the thread was running, by executing the following SQL and substituting :1 for the TID identified earlier:

[sourcecode language=”sql”]select sqlarea.*
from v$process proc,
v$session sess,
v$sqlarea sqlarea
where proc.addr = sess.paddr
and sess.sql_hash_value = sqlarea.hash_value
and proc.spid in (:1);

I was interested to see a clean view of what the bind variables were for the currently executing SQL statement. I used the following query:

[sourcecode language=”sql”]
select * from v$sql_bind_capture
where sql_id = ‘<ENTER SQL_ID HERE>’;

I then created indexes on columns in the SQL statements that I thought were problematic.

It’s also worth noting that if you really need to, you can kill the session by issuing the following command:

[sourcecode language=”sql”]ALTER SYSTEM KILL SESSION;[/sourcecode]

Here’s a class I created to allow FTP from within PeopleSoft. Use it at your own risk:

I was creating a PeopleCode script to populate test persons in my database. I needed the persons to have IDs that would be padded with 0s where necessary. For example:

1. Determine how many people you are creating (eg. 100).
2. Find the number of digits of that number (eg. 100 has 3 digits)
3. Subtract that from the number of the person that you’re currently trying to create an id for (eg. 50 has 2 digits, so 3 – 2 = 1). This will give you the number of zeroes you’ll need to left pad for the id.
4. Encapsulate this number in the PeopleCode Rept function to pad the 0s:

[sourcecode language=”peoplecode”]
Local number &maxIDsToCreate = 100;
Local number &currentIDNumber = 50;
Local string &currentID = "JM" | Rept("0", (Len(String(&maxIDsToCreate)) – Len(String(&currentIDNumber)))) | &currentIDNumber;

I had a series of files with the following names:


One silly assumption that I made was that the FindFiles PeopleCode function returned a sorted array of strings. While this seemed to be the case on Windows environments, it was not the case on UNIX systems. Fortunately all I had to do was sort the array in ascending order after the call to FindFiles: