Wednesday, August 05, 2026

SaveEdit, SavePreChange, SavePostChange... Which Event Should I Use?


When a user presses the Save button on a PeopleSoft component, PeopleSoft triggers three PeopleCode events in sequence:

  • SaveEdit
  • SavePreChange
  • SavePostChange

These events allow us to write specialized logic to:

  1. Validate data before saving,
  2. Update other fields within the component, and
  3. Trigger additional business logic, such as synchronizing systems through integration or launching an approval process.

Each scenario uses a different event. Let's review scenario #1: data validation.

  • A page has two fields: start date and end date. We must confirm that the start date precedes the end date.
Which event would you use?
  • SaveEdit
  • SavePreChange
  • SavePostChange

Let's review the behavior of each event to help us determine the best fit. Specifically, we want an event that can stop Save Processing if validation fails. This will keep us from sending invalid content to the database.

  • SaveEdit: Cancelable event.
  • SavePreChange: Cancelable event.
  • SavePostChange: Not cancelable because the data is already in the database.

This leaves two cancelable events: SaveEdit and SavePreChange. But what does PeopleBooks say?

"Important! Never use an Error or Warning statement in any save processing event other than SaveEdit. Perform all component data validation in SaveEdit." (emphasis added.)

Why? Why is it so important that we handle validation in SaveEdit and not SavePreChange?

Let's say we ignore PeopleBooks' advice, and we put data validation in SavePreChange rather than SaveEdit. How many SavePreChange events exist per component? The number is infinite. There is at least one per field associated with the component (Record/Field), as well as at least one per record in the component (Component/Record). We reach infinity when considering Event Mapping, because there is no limit on the number of Application Classes that may be associated with a component's SavePreChange possibilities.

Next, imagine that some of those SavePreChange events assume validation is complete and make changes to the component buffer. But if we put validation logic in one of those SavePreChange events, and that validation fails, what happens to all of those other SavePreChange component buffer updates? Nothing. There is no automatic reset. What if one of those handlers disabled the field that failed validation? How would the user correct the issue? This is why it is so important that we follow PeopleBooks' advice in this case and only validate in SaveEdit.

By the time the component processor reaches SavePreChange, all validation should be complete.

In summary, here is how you should use each Save event:

  • SaveEdit: Cross-field validation. Do not update data or change field properties from this event.
  • SavePreChange: Update data within the component buffer and apply field property changes, but do not perform validation.
  • SavePostChange: Perform any non-component, post-database work: Integrations, Notifications, Workflow, non-component data updates, etc.

At JSMpros, we teach PeopleCode tips daily! Check out our live virtual events calendar and on-demand offerings to enroll in your next course. Interested in learning more about PeopleCode specifically? Then check out these two classes:

Both are available live, live virtual, and on-demand. Contact us, and let's get you scheduled!

Monday, July 27, 2026

When Should You Refactor Your Customizations to Use Event Mapping, Drop Zones, and Page and Field Configurator?



Event Mapping, Drop Zones, and Page and Field Configurator are features designed to reduce the cost of staying current. These features move customizations into a separate, isolated layer so you may apply maintenance with fewer retrofits. In other words, these features remove customizations from the PeopleSoft-delivered codebase.

When should you refactor your customizations to use Event Mapping, Drop Zones, and Page and Field Configurator?

The answer is case-specific, but here are some guidelines to help:

1. Stop Customizing

For new change requests, look for ways to leverage Page and Field Configurator, Drop Zones, and Event Mapping (in that order).

2. Between Maintenance Cycles

If your system is running PeopleTools 8.55 or later, you can begin leveraging Event Mapping immediately. To apply this approach, identify all of your PeopleCode modifications and ask:

Is this a good candidate for Event Mapping?

"Good Candidates" for Event Mapping are PeopleCode changes that can run before or after PeopleSoft-delivered code. With a list of "Good Candidates," refactor each change to use Event Mapping.

The benefit of beginning this process between maintenance cycles is that it sets you up for success during the next maintenance cycle.

The challenge can be motivation. As they say, "if it ain't broke, don't fix it." Which leads to the next guidance:

3. During a Maintenance Cycle

This may be one of the best opportunities to apply Page and Field Configurator, Drop Zones, and Event Mapping for several reasons:

  • Applying maintenance will automatically identify customizations through the Compare and Report process. This is your "isolation strategy" worklist.
  • The maintenance process forces you to retrofit and/or refactor your customizations.
  • Application updates will include new Drop Zone locations and updated features in Page and Field Configurator.

The challenge of adopting these isolation strategies during a maintenance cycle is the added risk of introducing new concepts on an already-stressed timeline.

4. All of The Above!

The best strategy may be a combination of all three. First, stop customizing and adopt isolation strategies for all new requests. Second, look for customizations you created that you can isolate through Page and Field Configurator, Drop Zones, and Event Mapping. This will give you the experience necessary to comfortably retrofit additional customizations during the maintenance cycle.

PeopleSoft Test Framework

Isolating customizations does not eliminate the retrofit step. It reduces the amount of retrofits required per maintenance cycle. Embedded customizations must be retrofitted with every maintenance cycle. Isolated customizations, such as Event Mapping, Drop Zones, and Page and Field Configurator, however, only require a retrofit when they break. And this is the challenge created by Isolation Strategies: Customizations become invisible. They do not show on compare reports. They don't appear on lists of impacted customizations.

If retrofitting shifts from every customization to just broken customizations, how do we find what is broken? PeopleSoft Test Framework regression tests. Every time you isolate a customization, you create a regression test. Regression tests are usually short and trivial to create. When applying maintenance, you run your regression test library to identify what broke, and that list of broken customizations becomes your new, shorter retrofit list.

Want to learn more? We offer on-demand training for several of these isolation strategies:

Or join us for our next Configure, Don't Customize live virtual course!

Monday, July 13, 2026

PeopleTools 8.62 is Missing a Critical Code Enabler... Now What?


PeopleCode is fantastic, but it has limitations. With GetJavaClass and CreateJavaObject PeopleCode functions, Java is the perfect language to bust through that capability wall. Need a regular expression processor? Java has you covered. Base64 encoding Unicode characters? Java can handle that too.

But there is one challenge: Java supports a feature called "overloading." An overloaded method is defined multiple times, each with a differing parameter type or number. Unfortunately, PeopleCode can't natively map between the various Java types, so it can't determine which overloaded method to invoke. This forces us into a complicated, illegible combination of PeopleCode and Java reflection.

This is where JavaScript enters the story. JavaScript provides a convenient way to bridge PeopleCode and Java. Here is a simple PeopleCode example that uses Java to invoke JavaScript:

Local JavaObject &manager =  CreateJavaObject("javax.script.ScriptEngineManager");
Local JavaObject &engine =  &manager.getEngineByName("JavaScript");

REM ** Evaluate a simple JavaScript;
&engine.eval("var result = Math.random();");

REM ** Access the value of the JavaScript variable named result;
Local string &result_text =  &engine.get("result").toString();

This code ran flawlessly on PeopleTools 8.61, 8.60, 8.59, and many earlier releases. But that is not the case with new releases. Java used to bundle the Nashorn JavaScript Engine, but discontinued this practice in Java 15 (PeopleTools 8.61 bundled Java 11 LTS). So what are some alternatives?

  • Move your code into Java.
  • Leverage Java through PeopleCode and Reflection.
  • Install a JavaScript script engine.

Move Your Code into Java

Chapter 11 of our PeopleSoft PeopleTools Tips and Techniques book shows you how to write and deploy your own custom Java to a PeopleSoft instance to be run on the App Server or Process Scheduler Server (App Engine). Java written for PeopleSoft has full access to the PeopleCode API, including classes and functions through the PeopleCode.jar file. Because your Java application is running on the App Server (or App Engine), it has full access to the database via SQLExec, Rowsets, etc.

Note: Once the Java Runtime Environment (JRE) loads a class into memory, you must restart the JRE to deploy changes. Since development is often an iterative process, this means you will need to restart the JRE each time you deploy updated Java class files to your App or Process Scheduler server. For an App Server, restarting the JRE means restarting the App Server. So while this compiled Java alternative may seem better architecturally, constant App Server restarts during development significantly increase development time (not to mention the annoyance factor).

Leverage Java through PeopleCode and Reflection

Java's overloaded syntax is challenging in PeopleCode, so we must invoke overloaded methods and constructors via the Java Reflection API. While certainly possible, the code is just as challenging to read as it is to write. You may find several examples of Java Reflection in PeopleCode on our blog.

Install a JavaScript Script Engine

What makes this approach appealing is its flexibility in deployment and its simple code. Unlike compiled Java code, JavaScript does not require a server restart. And just like Java code, JavaScript running in the App Server (or Process Scheduler) has full access to the Java API, PeopleCode, and your database.

You may expose any JSR 223 compatible script engine (JavaScript, Groovy, Jython, JRuby, etc.) by including the appropriate jar file in the PeopleSoft CLASSPATH. There are several documented ways to extend the PeopleSoft CLASSPATH, but the most common is to add your jar file locations to the Add to CLASSPATH property in your app and process scheduler configuration files.

Nashorn

Nashorn is the JavaScript engine included with Java 11 LTS (PeopleTools 8.61). If you have scripts and PeopleCode written for earlier versions of PeopleTools (such as 8.61), this may be your fastest path to compatibility.

The standalone Nashorn JavaScript engine requires the ASM library to compile JavaScript dynamically. As of this writing, a working deployment would include:

  • asm-util-9.10.1.jar
  • nashorn-core-15.7.jar


To deploy Nashorn, you would:

  1. Download the latest version of asm-util and nashorn-core,
  2. Place them in a folder available to your app server, and
  3. List them in the Add to CLASSPATH variable of your app server configuration file.

Other JavaScript engines include Rhino and GraalVM/GraalJS, with Oracle recommending GraalVM. If you choose to move forward with GraalVM, be sure to check out org.graalvm.polyglot.Context, which is recommended over the JSR 223 ScriptEngineManager approach.


The other day, we needed to receive a large amount of data from a cloud provider. To avoid crashing the server, we chose stream processing. Unfortunately, this is not an Integration Broker-supported feature, so we chose to use the Jakarta and Apache HttpClient libraries included with PeopleTools. You can read more about this solution in our post Consuming Enormous Datasets with PeopleSoft. To avoid Java Reflection, we chose JavaScript on the app server.

How about you? Have you experienced situations where you hit the PeopleCode capability limit? If so, what strategy did you use to deliver a solution?

At JSMpros, we teach PeopleTools tips like this daily. Visit our live virtual events calendar to schedule your next class.

Our classes are available live, live virtual, and on-demand. Want to learn more? Contact us, and let's get you scheduled.

Monday, June 15, 2026

Parameterized Landing Page Section Templates

Dynamic Sections are a powerful feature of PeopleSoft’s modern Landing Pages that use App Classes to render data-driven results. Many sections, such as My Direct Reports, My Queries, My Expense Reports, and My Advisees, require no parameters, with each having its own App Class. But what if you want to leverage the same business logic across multiple sections? How would you pass parameters to your Dynamic Sections?

For example, imagine you are an Integration Broker administrator responsible for ensuring smooth operations across your PeopleSoft environment. You know how challenging it can be to keep track of integration queues, especially when operations get stuck in New status. Wouldn’t it be helpful to have a dynamic landing page section that automatically lists these problematic operations, complete with links to investigate each one?


Note: A dynamic section such as this one is perfect for an Integration Administrator Dashboard, but may not be a candidate for a consolidated Landing Page.

Here is a screenshot of my section configuration:



But just as important as messages stuck in New status are messages in Error status. It was while creating the "Messages in Error Status" dynamic section that I noticed the similarities. The code for the Messages Stuck in New Status and Messages in Error Status classes is nearly identical. In keeping with best practices, I applied the D.R.Y (Don't Repeat Yourself) principle and refactored that shared logic into a common base class. Here is what my class hierarchy looks like:




The base class declares an abstract property, and each implementation provides a value for that property. This is the beauty of object-oriented programming: shared logic and multiple implementations. But do you know what else we have? Multiple configurations. Each App Class will have its own section configuration. If we create Landing Page Section Templates, then we would have one template for each App Class.

Is there a way to parameterize the App Class or Section template so we can use just one App Class (IBMsgStatusLoader) and have it derive the desired status from a parameter? Yes, in fact, there is! At the bottom of a Section configuration, you will find Section Attributes:


We use Section Attributes to identify stylesheets and style classes. The delivered Landing Page API exposes these two specific attributes as section properties. But what about other Section Attributes? Can you define your own attribute keys? We traced it and discovered that Section Attributes are stored in the PSPTHPAGATTR table. We can access a section's attributes through the SQL:

SELECT PORTAL_ATTR_VAL
  FROM PSPTHPAGATTR
 WHERE PORTAL_NAME = :1
   AND PORTAL_OBJNAME = :2
   AND PORTAL_OBJNAME_PGT = :3
   AND PORTAL_ATTR_NAM = :4

We can extract a section parameter, therefore, using the following PeopleCode:

SQLExec(SQL.TRN_LP_SCTN_ATTR_VAL, &portalName, &tabName, &sectionName, &attributeKey, &attributeValue);

The Portal name, tab name, and section name are available in the Loader constructor through the &oTab and &oSection variables:

&m_portalName = &oTab.PortalName;
&m_tabName = &oTab.TabName;
&m_sectionName = &oSection.SectionName;

You may find a copy of our Parameterized Section Loader base class in our PeopleCode Templates GitHub repository.

What section templates would you like to parameterize? Leave us a comment to let us know!

At JSMpros, we regularly teach best practices for Fluid, PeopleCode, and Landing Page. Check out our online events calendar to see what course we are offering next! Prefer on-demand? Check out our Course Catalog for a variety of PeopleTools courses covering Fluid, Landing Pages, Application Classes, and much more!

Thursday, April 16, 2026

PeopleSoft Reconnect Live 2026 at Blueprint 4D!



Looking for the premier opportunity to connect with PeopleSoft customers and dive deep into PeopleSoft's product strategy? Join us at PeopleSoft RECONNECT Live, part of Blueprint 4D! With the conference just a few weeks away, we're excited to unveil our session lineup:
  • Session - P-052187: What's New in 8.62 for Campus Solutions
    Monday, May 4, 2026, 3:45 pm CT | Room: Miro
    Discover the latest updates in 8.62, with a special focus on PeopleTools Landing Pages for Campus Solutions. Whether or not you're a Campus Solutions customer, this session is packed with insights for anyone interested in PeopleTools.
  • Session - P-052181: Getting the Most out of PeopleSoft PeopleTools—Tips and Techniques
    Tuesday, May 5, 2026, 9:00 am CT | Room: Topaz
    Explore practical tips for using PeopleSoft PeopleTools, including Fluid, Integration, and Java. Take advantage of this opportunity to discover innovative ways to expand your PeopleSoft toolkit.
  • Session - P-052189: Enterprise Components—The "Other" Toolset
    Thursday, May 7, 2026, 9:00 am CT | Room: Metropolitan
    Learn about valuable tools available to PeopleSoft developers beyond the standard PeopleTools suite. We'll discuss how to access these tools, best practices for using them, and why different applications may offer different versions.
  • Session - P-052186: Replacing Customizations with Configurations in Campus Solutions
    Thursday, May 7, 2026, 11:00 am CT | Room: Madrid
    Event Mapping, Drop Zones, and Page and Field Configurator are important tools for Campus Solutions, but there is a twist! Join Jim Marion on Thursday to learn techniques to help you build more robust, maintainable solutions.
We are ready to connect and collaborate. See you in Dallas!

Monday, April 06, 2026

Fluid, Classic, or Classic Plus?

Let's say you are going to build a brand new component in PeopleSoft Application Designer. Would you build it using

  • Classic,
  • Classic Plus, or
  • Fluid?

Here is how our LinkedIn audience answered that question:


Why Fluid?

Over 50% of our audience chose Fluid, and here are some reasons:

Strategic Direction

Fluid is Oracle's strategic direction. This means everything new that Oracle builds will be built in Fluid. If Fluid is Oracle's strategic direction, perhaps it should be ours as well?

Accessibility

Fluid generates better markup for screen readers and other accessibility features. If you must comply with the New Rule on the Accessibility of Web Content, then Fluid is your best option.

Mobile and Touch Friendly

Fluid is touch-friendly out of the box. Data entry fields have more space around them, and buttons are larger to facilitate touch. Through adaptive style classes and adaptive PeopleCode, Fluid can render better on mobile, whereas Classic renders the same across all devices.

Styling and Layout

Fluid offers more flexibility than Classic through grid types, HTML elements, and the PeopleCode function AddStylesheet.

Is Classic Still Relevant?

With so many good reasons to choose Fluid, is there still a case for Classic? We believe the answer is, "YES!" Many PeopleSoft-delivered business processes are 100% Classic. If you are extending an Oracle-delivered business process with a new component, it might make sense to build that component in Classic. Otherwise, your new component would be the only Fluid component in the business process. Another reason to choose Classic is that you prefer Classic features, such as highly flexible Related Content at the bottom of the page or traditional Scroll Areas.

Where Does Classic Plus Fit?

Classic Plus is Classic with a different skin. All Classic features apply to Classic Plus. Development for Classic Plus is nearly identical to Classic. Since Classic Plus requires more area, the only development consideration is spacing: Is there enough room?

Classic Plus makes Classic content look like Fluid, but not behave like Fluid. It just changes the PeopleSoft theme to look like Fluid. Classic Plus is a great way to make your existing Classic pages merge with a new PeopleSoft-delivered Fuid experience. Alternatively, Classic Plus is a great way to make PeopleSoft's Classic content merge with your new Fluid content.

So what do you think? As you consider new components, will you create them in Classic, Classic Plus, or Fluid?

At JSMpros, we teach PeopleTools tips like this daily! Check out our live virtual events calendar to schedule your next class. Interested in learning more about Fluid specifically? Then be sure to check out our Fluid-specific collection!

All of our classes are available live, live virtual, and on-demand. Want to learn more? Contact us, and let's get you scheduled!

Tuesday, February 10, 2026

Is GenerateComponentPortalURL Still Relevant?

Let's say you need to link from one PeopleSoft component to another. How would you generate the link? Perhaps FieldChange PeopleCode on a button or hyperlink? If so, what PeopleCode function would you use? GenerateComponentPortalUrl? PeopleCode includes functions such as GenerateComponentPortalUrl for generating URLs. But are these functions the best approach?

The URL generation functions create a URL to any menu/component combination. Provide these functions with PeopleTools metadata, and they will craft a URL. But here is the problem:

They have no regard for the Portal Registry.

Many Oracle-delivered Fluid solutions use framework components, such as PT_AGSTARTPAGE_NUI (Activity Guides and Navigation Collections) and PT_FLDASHBOARD (Dashboards). These framework components use Query String attributes, such as CONTEXTIDPARAMS. With Framework components, it is not enough to just create a menu/component/market URL with a function like GenerateComponentPortalURL. We must also consider the additional Portal Registry attributes.

Here is an alternative: Use the Portal Registry API. Instead of using GenerateComponentPortalURL, leverage the Portal Registry metadata. Here is a PeopleCode fragment to get you started:

method getCrefAbsoluteContentUrl
   /+ &crefId as String +/
   /+ Returns String +/
   Local ApiObject &PTPortal = %Session.GetPortalRegistry();
   Local ApiObject &CREF;
   
   If &PTPortal.Open(%Portal) Then
      &CREF = &PTPortal.FindCRefByName(&crefId);
      &PTPortal.close();
      Return &CREF.AbsoluteContentURL;
   Else
      Return "";
   End-If;
end-method;

I would place this code in a common, reusable container for future use. Now, what do you think, should we put this code in an Application Class or a Function Library?

Use generation functions, such as GenerateComponentPortalUrl, when you don't have a Content Reference. Otherwise, consider using the Portal Registry.

At JSMpros, we teach PeopleCode tips every week! Check out our live virtual events calendar to schedule your next class. Interested in learning more about PeopleCode specifically? Then check out these two classes:

Both are available live, live virtual, and on-demand. Want to learn more? Contact us, and let's get you scheduled!