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!

Wednesday, January 14, 2026

App Classes Versus Function Libraries

If you were to create a reusable code fragment, would you use an App Class or a Function Library? We asked our LinkedIn audience, and this was the result:

Bar chart showing 9 out of 10 developers prefer Application Classes

Do these results surprise you? Here are some insightful comments from the poll participants:

"Application Classes... For so many reasons:
  1. Application Classes hold state across method calls
  2. You get maintenance savings from classes
  3. Application Packages can bundle related code
  4. Classes give you public, protected, and private methods
  5. Encapsulation and state
  6. Clear Namespaces"
"I have always preferred application classes over function libraries because I find the discoverability of functions to be severely lacking. They can be placed just anywhere in any field in any record. And I can never remember the format for the declare statement."
"Don't forget about the variable declarations and type checking, which can avoid lots of problems at Runtime. That is on top of a clear inventory of available methods at the top of the class."
"Hands down application class..."
"My personal problems with functions:
  1. Keep forgetting library records 
  2. Can’t group code without creating a new library
  3. Can't use them for configuration such as IB Handlers"
"I haven't willingly created a new function library in years.
  • Application classes are much neater
  • Nicer to implement
  • Like the OO[P] reference
  • Not nested in other code"
"A bonus of using Application Classes is being able to test any of your code from a delivered component in the PIA with the Application Class Tester. Navigation: Enterprise Components > Component Configurations > Application Class Tester. One of the best development tools that Peoplesoft delivers!"

Let's do a side-by-side comparison of the differences identified in the comments:

App Classes Function Libraries
All variables must be declared
Stateful
Testability
PeopleCode-specific container
Dynamic execution
Object-oriented concepts such as Inheritance and Composition
May be used by frameworks (IB, etc.)
Stateless

While the App Class column has the most checkmarks, is it the right answer for every situation?

All Variables Must Be Declared

Function libraries allow us to use variables without declaring them. An undeclared variable becomes implicitly declared as a generic data type upon first use. The problem with implicitly defined variables is that they support typos. It is really easy to mistype a variable name, which then becomes a new implicitly defined variable.

Application Classes will not compile and save unless you declare every variable. This avoids implicit typos.

At JSMpros, we teach that all variables should be defined at all times. The compilation output window, therefore, becomes a worklist. If a variable appears in the list, either declare or fix it. At the end of the day, anything in the list is a typo.

State

Application Classes are stateful, whereas Function Libraries are stateless. Both have their place. Application Classes must be instantiated prior to use. There are times when I have a code fragment that doesn't require state. Instantiating an object to perform a stateless operation seems like a waste. If the logic does not require state, then Application Classes may be overkill.

Testability

With Oracle-delivered solutions, such as the Application Class Tester, and community projects, such as PSUnit, it may seem that Application Classes are easier to test. But testability has more to do with coding practices than the container. For example, code you plan to test should avoid context-aware functions and variables. Whether you are testing App Classes or PeopleCode functions, you will write test case PeopleCode, which can be as simple as an App Designer-run App Engine.

PeopleCode-specific Container

Function Libraries are PeopleCode functions attached to events in Record Field PeopleCode. This can be challenging to manage. Having a PeopleCode-specific Container, such as an App Class makes a lot of sense. I do wish Function Libraries were stored in their own container. This doesn't impact their functionality, but it does affect lifecycle management and reuse.

Dynamic Execution

As noted in the comments, function libraries must be declared before they are invoked. We could argue that Application Classes have the same requirement in the form of import statements, but that's not exactly the case. One of the most powerful features of Application Classes is that we can instantiate objects, invoke methods, and set properties at runtime without knowing the implementing class at design time. We do this through the PeopleCode functions CreateObject, ObjectDoMethod, and ObjectSetProperty. These three functions allow for fully dynamic PeopleCode. In short, Application Classes don't need to be declared. It is this characteristic that allows PeopleSoft to build frameworks, such as Approval Workflow Engine, Event Mapping, and Integration Broker.

Object-Oriented Concepts Such as Inheritance and Composition

This is a key component to making Dynamic Execution work. We can create frameworks that code to interfaces and abstract base classes, and then use dynamic functions to instantiate full implementations at runtime.

Overall, object-oriented programming is not considered better or worse; it's just different. Poorly designed inheritance hierarchies can cause more problems than they fix. Perhaps what makes them challenging is that a solution is not static. We might create an amazing hierarchical design for the first build, but over time, that design becomes corrupted through changes. Composition is an Object-oriented concept that attempts to overcome the challenges of Inheritance.

May be used by frameworks (IB, etc.)

This feature brought to you by Dynamic Execution. Because we can code to an interface, we don't need implementation details until runtime. This makes App Classes perfect for AWE, IB, Event Mapping, PSUnit, Landing Pages, and much more!


In conclusion, each strategy has its place. Choose Function Libraries in the following situations:

  • There are times when you must use Function Libraries. Signon PeopleCode is a great example.
  • I also choose Function Libraries for stateless routines. If your reusable code fragment is stateless, then the overhead of App Classes may be overkill.

Choose App Classes:

  • If you are building a framework, such as AWE, and want to register future event handlers, Application Classes are the right tool. You, the framework builder, would code to an interface, and later implementations provide the runtime details.


Which do you prefer? Let us know in the comments.

We teach both topics in our on-demand PeopleCode course. Already familiar with Function Libraries and want more information on Application Classes? Enroll in our on-demand course or join us for our next live virtual session!

Tuesday, December 16, 2025

From Idea Labs to Implementation: Access PeopleSoft Global Search with Hotkeys!



Oracle ACE Graham Smith recently posted a fantastic idea to Idea Labs: Put the cursor in Global Search when clicking Home. In a search-centric experience, this makes a lot of sense. And if you like this idea, you don't have to wait for a future PeopleTools release. We can build it ourselves with Event Mapping and a little JavaScript!

To avoid potential conflicts with accessibility and the PeopleTools-delivered tab order, the following implementation uses a keyboard combination (hotkeys) to activate the search bar. This is akin to Apple's Spotlight. I choose CTRL+SPACE. Several years ago, we recorded a SoundByte showing similar functionality:



Let's implement a slightly different version that specifically targets homepages/landing pages.

Here is what we will need:

  1. HTML Definition that contains JavaScript to run when the page loads
  2. Event Mapping App Class to inject our JavaScript
  3. Related Content Service Definition
  4. Event Mapping definition to map the App Class into the Landing Page Content Reference

The JavaScript to implement the request is trivial:

document.getElementById('PTSKEYWORD').focus();

But we are going to lock this into a key handler, so the full JavaScript looks like this:

document.addEventListener('keydown', function(e) {
    if (e.ctrlKey && (e.key === ' ')) {
        var el;

         el = document.getElementById('PTSKEYWORD');

         if(!!el) {
            el.focus();
        }
    }
  });

I threw that JavaScript into an HTML definition named JSM_GS_LP_FOCUS_JS, and then referenced it from my Event Mapping PeopleCode as follows:

import PT_RCF:ServiceInterface;

class PageActivate extends PT_RCF:ServiceInterface
   method execute();
end-class;

method execute
   /+ Extends/implements PT_RCF:ServiceInterface.execute +/
   
   AddJavaScript(HTML.JSM_GS_LP_FOCUS_JS);
end-method;

The remaining tasks are standard Event Mapping:

  1. Create a Service
  2. Assign the Service to the Content Reference Fluid Home
  3. Test

And now you have your Hotkey! Enjoy!

At JSMpros, we teach PeopleTools Tips like this every day! Check out our events page to see what course we are offering next. Prefer to learn at your own pace? Enroll in on-demand training to learn whatever you want, whenever you want, wherever you want.

Monday, December 08, 2025

Branding System Options for Fluid

 The PeopleTools Branding System Options component allows a developer to inject custom CSS and custom JavaScript globally. This is fantastic, but it only applies to Classic/Classic+ (see Oracle Support document 2827970.1). Wouldn't it be nice to have the same functionality for Fluid? Now you can! PeopleTools 8.60 included Global Event Mapping, a feature that allows us to attach JavaScript and CSS to all Fluid components at once! We published a video a couple of years ago describing this PeopleTools feature. You may want to watch the video before continuing with this post:



Let's apply what we learned in the video to our scenario:

1. Create an Event Mapping Service App Class

In Application Designer, let's create a Global Event Mapping App Class. A Global Event Mapping App Class is just like any other Event Mapping App Class. They all start with the same PeopleCode. You may download our Event Mapping PeopleCode template from our GitHub repository. Here is a PeopleCode template to get you started:

import PT_RCF:ServiceInterface;

class FluidBrandingSystemOptions extends PT_RCF:ServiceInterface
   method execute();
end-class;

method execute
   /+ Extends/implements PT_RCF:ServiceInterface.execute +/
   
   If (IsFluidMode()) Then
      REM ** Insert JavaScripts;
      REM AddJavaScript(HTML.ABC123);
      
      REM ** Insert Stylesheets;
      REM AddStylesheet(Stylesheet.DEF456);
   End-If;
end-method;

2. Create an Event Mapping Service Definition

Every Event Mapping solution requires a Related Content Service Definition. As of PeopleTools 8.59, we can use a dedicated page for Event Mapping, but we don't have to. We can create our Global Event Mapping service definition the same way we have always created Related Content Service Definitions. Here is a screenshot of my service definition:



3. Run PeopleCode to Apply Global Event Mapping

Since there is no user interface to manage Global Event Mapping, we must invoke a few lines of PeopleCode to register our Global Event Mapping solution. I like to use App Engines for this, because I can run them directly from App Designer. Here is the PeopleCode I placed in my App Engine:

import PTCS_GLOBALEVENTMAPPING:*;

Local PTCS_GLOBALEVENTMAPPING:GlobalEventMapping &gem = create PTCS_GLOBALEVENTMAPPING:GlobalEventMapping();
Local boolean &bstatus = &gem.CreateGlobalEventMappingConfig("JSM_GBL_BRAND", "JSM_GBL_FL_BRAND");

4. Refactor Your Solution into a Table-Driven Framework (Optional)

Fantastic! We can now add or remove CSS and JavaScript globally by adding and removing lines from our App Class PeopleCode. Alternatively, would you like to maintain your list of assets through an online configuration page? The solution requires a bit more effort, but would involve the following:

  • A table to store JavaScript and Stylesheet names,
  • A page for configuring (likely with grids for JavaScript and Stylesheet assets), and
  • An online component.

I'll leave this final step to you. Personally, I prefer the static code listing, as it performs better (critical for Global Event Mapping), and my list of Stylesheet and JavaScript resources doesn't change very often. I also like the change control required by PeopleCode that would not exist if I had an online configuration table.

As noted in the video, be careful not to break Global Event Mapping. One misstep and your entire system is broken! As also noted in the video, correcting an error is trivial. Just comment out the offending code.


Are you interested in learning more about Event Mapping? Check out our Event Mapping on-demand course, just one of many on-demand classes included with our subscription service.

Tuesday, December 02, 2025

When AI Writes PeopleCode... Fact or Fiction?

I just asked Gemini the following question:

"Is there a PeopleCode variable to detect Fluid Mode vs Classic mode?"

Gemini responded with, "Yes!" I thought, "FANTASTIC!"

Here is the code snippet Gemini suggested:

If %Component.IsFluid Then
    /* Logic specific to Fluid Mode */
    MessageBox(0, "", 0, 0, "Running in Fluid Mode");
Else
    /* Logic specific to Classic Mode */
    MessageBox(0, "", 0, 0, "Running in Classic Mode");
End-If;

Wow! That is some fantastic PeopleCode! But AI is known to hallucinate. Before trusting this code, we have to ask: Fact or Fiction?

Let's start with line 1:

If %Component.IsFluid Then
It appears Gemini thinks %Component is an object. What does PeopleBooks say?
%Component returns an uppercase character string containing the name of the current component, as set in the component definition.
To confirm, let's try compiling it in Application Designer. The following is a screenshot of the compilation result:

Verdict: Fiction.

%Component contains a primitive string, not an object. Since a primitive string does not have methods. The IsFluid method would be invalid.

I followed up with Gemini by asking:

"Can you share your reference for %Component?"

Instead of sharing a bibliography of cited sources, Gemini shared what appeared to be very legitimate documentation that describes Gemini's understanding of %Component. I attached a screenshot for your reference:




I circled the last statement, because it was the only part of this listing that was true:

"Gemini can make mistakes, so double-check it"

But I have to ask: Where did Gemini get its information? 🤔 Like a crack reporter, Gemini would not reveal its sources.

The good news is that Gemini is a fast learner! I fed Gemini a few authoritative PeopleBooks, such as a reference to PeopleCode System Variables, and Gemini generated a new response. This version is clever, but does it work?

Local ContentReference &oCRef;
Local boolean &isFluidMode;

/* Get the ContentReference object for the currently running content.
This object holds the metadata for the component's setup.
*/
&oCRef = %Session.GetContentReference();

If (&oCRef <> Null) Then
    /* Check the IsFluid property on the ContentReference object */
    &isFluidMode = &oCRef.IsFluid;
End-If;

If &isFluidMode Then
    /* Execute PeopleCode specific to Fluid UI */
    /* ... */
Else
    /* Execute PeopleCode specific to Classic UI */
    /* ... */
End-If;

What do you think? Fact or Fiction?

Let's start with the first line:

Local ContentReference &oCRef;

Unfortunately, ContentReference is not a built-in PeopleCode data type. What about this line?

&oCRef = %Session.GetContentReference();

Strike 2! GetContentReference is not a documented method of the Session object.

Verdict: Fiction.

But Gemini is on to something! The Fluid Mode attribute is visible in Structure and Content, so with a bit of PortalRegistry PeopleCode and the new %CRef system variable, you could write a lot of PeopleCode to determine if the current component is using Fluid mode.

I wanted to spend a few more minutes helping Gemini find the correct answer, so I fed Gemini several more PeopleBooks entries, hoping it would derive the correct answer. Each time, Gemini gave me a new, seemingly authoritative but entirely fictitious response, inventing new App classes and creating new functions.

After a few iterations, I decided to share the correct answer with Gemini. PeopleCode has a built-in function to determine Classic from Fluid: IsFluidMode. Here is Gemini's reply:


"This built-in function provides the clean separation of logic needed when supporting the same component in both Fluid and Classic modes (emphasis added)..."

Should we tell Gemini that a single component cannot be both Fluid and Classic?

This was a fun exercise. It was like a PeopleCode puzzle: find the hidden AI hallucination, and solve the puzzle.

How about you? Do you have interesting stories about AI and PeopleSoft? If so, please share them in the comments. We love hearing your stories!

Today, there is no substitute for experience and a strong personal understanding of PeopleCode. Want to become a PeopleSoft development expert so you can better determine fact from fiction? Enroll in the JSMpros All-access training pass and start learning!

Thursday, October 23, 2025

PeopleSoft Reconnect 2025 | Dive Deep



The premiere PeopleSoft conference, Reconnect | Dive Deep, begins in just a few days. If you are not already registered for this live virtual conference, be sure to do so ASAP. If you are already registered, then be sure to log in to the conference app to build your agenda. Some sessions have capacity limits, and you don't want to miss them!

Here is the list of sessions I am presenting at this year's conference:

Monday

  • 4:45pm EDT P-051853, PeopleSoft Test Framework: More than Automated End-user Testing


Tuesday

  • 11:15 am EDT P-051448, Replacing Customizations with Configurations in Campus Solutions
  • 1:45 pm EDT P-051447, Enterprise Components: The "Other" Toolset
  • 4:15 pm EDT P-051446, PeopleSoft Fluid Best Practices


Wednesday

  • 12:30pm EDT P-051861, What's New in 8.62 for Campus Solutions!


Thursday

  • 12:30 pm EDT P-051442, Getting the Most out of PeopleSoft PeopleTools: Tips and Techniques
  • 1:45 pm EDT P-051445, Isolate and Configure: Don't Customize!

As a registered attendee, be sure to check out our virtual booth to watch replays from prior conference sessions. I look forward to seeing you online next week!

Monday, September 08, 2025

Parsing JSON Arrays with PeopleCode

PeopleCode includes built-in support for parsing JSON through a native object called the JsonParser. Let's review a couple of JSON strings and then see how the JsonParser interprets them. First, let's review a JsonObject:

{
  "course": "PT1",
  "description": "PeopleTools",
  "courseType": "T",
  "duration": 4
}

Assuming that the JSON text is in the string variable &jsonStr, then we might parse it with code similar to:

Local JsonParser &p = CreateJsonParser();

If (&p.Parse(&jsonStr)) Then
  REM ** Woo Hoo! It parsed!;
End-If;

Parsing means the JsonParser created an in-memory structure. To leverage the JSON, we need to access that in-memory structure. The JsonParser includes one documented method to access the JSON Structure: GetRootObject(). The GetRootObject method returns a JsonObject. According to the documentation, the following PeopleCode should give us the value of the description attribute from the JSON above:

Local JsonObject &course = &p.GetRootObject();
Local string &descr; = &course.GetString("description");

What about a JSON Array? Here is my concern: There is no GetRootArray method. What if the "root object" is not an "object," but an Array? Here is what a valid JSON Array might look like:

[{
  "course": "PT1",
  "description": "PeopleTools",
  "courseType": "T",
  "duration": 4
}, {
  "course": "PC",
  "description": "PeopleCode",
  "courseType": "T",
  "duration": 5
}]

We would parse it using the same code as above. But how would you access the Array? Since the Parser has a GetRootObject method, let's invoke it, and then ToString the root object to see its JSON output. Here is the PeopleCode:

MessageBox(0, "", 0, 0, "%1", &p.GetRootObject().ToString());

... and here is the JSON:

{[
    {
        "course": "PT1",
        "description": "PeopleTools",
        "courseType": "T",
        "duration": 4
    },
    {
        "course": "PC",
        "description": "PeopleCode",
        "courseType": "T",
        "duration": 5
    }
]}

Do you notice anything unusual about that JSON? Notice the extra curly braces ({}). The "root" object is a JSON object. But here is where it gets interesting. The printed JSON is not valid. An object must have an attribute. The array should be assigned to an attribute. Now, does this matter? I think Oracle is allowed to internally represent JSON any way they desire. You might say that what we did was unexpected. We asked PeopleSoft to print an internal representation, not a true, expected JSON Object. But my question is the same: How do you access the Array that is now inside the root object? Here is the answer:

&p.GetRootObject().GetJsonArray("");

The GetJsonArray method expects an attribute name. We don't have one. So we don't give it one. Just use a zero-length string.

Want hands-on experience with REST services and PeopleCode parsing techniques? Join us on Tuesday, September 23, for two hands-on, live virtual workshops focused on integration! Details for the entire September series are available online.

We teach PeopleTools tips like this every week. Check out our website to see what we are offering next. Prefer to learn at your own pace? Our entire catalog is available online.

Wednesday, August 13, 2025

Five Reasons to Adopt the Application Services Framework

PeopleSoft's Integration Broker has support for REST and JSON. But, it is clear from the metadata, design, and history that Integration Broker favors SOAP and XML (Web Services). Is there a better alternative? YES! As of PeopleTools 8.59, we have a module designed specifically for REST: the Application Services Framework (ASF).

Here are five reasons you should consider ASF for your next integration project:

1. URL Design

REST focuses on objects and data. In an enterprise system, business objects might be Employees, Students, or Vouchers. In ASF, we might call these root resources. Continuing with the Voucher example, we might have the following URLs:

  • .../ap/vouchers
  • .../ap/vouchers/000000012567

When constructing an Application Service, we would have the "ap" service, which would then have a "vouchers" root resource. We could then define URI templates for:

  • vouchers (get a list of all vouchers)
  • vouchers/000000012567 (get a specific voucher)

We would further define HTTP methods, such as GET, PUT, PATCH, or POST, to fetch, update, or create business objects within the respective collections.

The Application Services framework helps us design URLs by first thinking about the module → then the collection → and then the specific object (generic to specific).

When we browse the Internet, we expect to find an organized collection of documents (endpoints) conveniently filed in meaningful folders. Computers browse the Internet, and those computers should expect an organized collection of business "documents" as well.

2. 201 Created Success Status Code

Web Services and SOAP use a protocol within a protocol. The typical Web Service request uses HTTP as the transport protocol and SOAP for the transaction protocol. Therefore, a Web Service might return a 200 HTTP status code to report success even though the SOAP transaction failed.

REST HTTP status codes have meaning. HTTP status codes in the 200 range represent successful responses. The most important HTTP status codes for a PeopleSoft developer are 200, 201, 202, and 204. These are the ONLY HTTP success status codes supported by ASF. Integration Broker REST-based Service Operations, on the other hand, support several other 200-level status codes, but with one critical omission: REST-based Service Operations do not support 201. 201 is the status code for "created." Assuming a PUT or a POST, the proper response may be a 201 - Created. This is critical. If the service handler immediately creates a transaction, then it should return a 201. The Application Services Framework supports this, but traditional REST Service Operations do not.

3. 401 Unauthorized Bad Request Status Code

PeopleSoft takes control of the HTTP Authorization header for several reasons. Here are a couple:

  • To determine if the requester is authorized to access the requested service.
  • To assume the identity of the user making the request, allowing PeopleCode to run as the proper user.

If PeopleSoft determines the requester does not have access (based on roles and permission lists), then PeopleSoft will return the 401 Unauthorized HTTP status code. This happens at the Integration Broker level, and it is fantastic!

But what if your business logic needs to return a 401 Unauthorized? Traditional REST-based Service Operations do not allow this.

Consider the following example. Let's say that a user is authorized for our /ap/vouchers service (the example above). That user might be authorized to access certain vouchers, such as .../ap/vouchers/000000012567, but not .../ap/vouchers/000000012568. This is called row-level security. In this scenario, we should return a 401 - Unauthorized. The user is authorized for the service, but not the data.

Traditional REST-based Service Operations do not allow you to return a 401 Unauthorized EVER. ASF does. 401 is an acceptable failure response from an Application Service.

4. OpenAPI

Metaphorically speaking, OpenAPI is the WSDL of REST. ASF generates OpenAPI specifications for us. We can plug these OpenAPI URLs or downloaded descriptors into various consumers, including Oracle Digital Assistant, Oracle Integration Cloud, Oracle Visual Builder, and more!

5. PeopleCode

ASF was designed to expose Application Classes as REST services. The framework includes an API designed to construct single-row and multi-row responses. The API was designed for REST with support for HTTP status codes and HTTP methods.

6. (Bonus) Metadata Design

ASF metadata consists of:

  • Module
  • Root Resource
  • URI Templates
  • Parameters
  • Result States
  • HTTP Headers
All of these are common and expected REST metadata concepts. Traditional REST Service Operations, on the other hand, include Messages, Services, Service Operations, and Documents; metadata structures that are more appropriate for Web Services than REST.


What to learn more? Create a free account at jsmpros.com and explore our free webinar replays to learn the basics of the Application Services Framework. Next, join us for our three-day live virtual Integration Tools Update course. Prefer to learn at your own pace? This same material is available on demand! Watch the videos whenever and wherever you like, and then complete the hands-on activities on your own server.

Wednesday, July 23, 2025

PTF: Recorder is unable to load... Now What?

I love PTF! With Selective Adoption, Continuous Delivery, and Customization Isolation strategies, PTF is more important than ever. Since Event Mapping, Drop Zones, and Page and Field Configurator don't appear on compare reports (and that is the point), we need a tool like PTF to expose regressions we would have found through the traditional retrofit analysis. The traditional retrofit approach required us to analyze and retrofit every customization. Event Mapping, Drop Zones, and Page and Field Configurator free us to focus on just what broke during the upgrade. And this is why PTF exists. The PTF regression test is how we find what broke. PTF is the linchpin that holds the whole isolated customization strategy together. Without it, we either go live with undiscovered errors or we continue to analyze and retrofit everything.

But what if you launch the PTF recorder and suddenly see this?


What happened? The PTF recorder is a Chrome/Edge plugin. That plugin needs to be loaded for the recorder to function. The PTF application attempts to install this plugin each time it launches the recorder. Depending on your enterprise settings, however, Chrome may deny that request. This is what happened to me. Enterprise customers have been dealing with this since PeopleSoft switched to the Chrome recorder. However, this is what surprised me: I'm simply using a standard Chrome download on an unmanaged server. In fact, PTF used to work just fine on this very server, and this behavior is a recent development. Perhaps Chrome altered its security policy?

Fortunately, this is a known and documented issue. Enterprise customers with highly controlled Chrome environments have been experiencing this issue since PTF switched to the Chrome recorder. Take a look at MOS Doc ID 2922127.1. This document outlines the steps necessary to correct the issue. Following those steps, I launched Chrome as an Administrator by:

  1. Typing Chrome into the Windows Menu and
  2. Right-clicking the Google Chrome entry and choosing Run as Administrator from the popup menu

I then navigated to chrome://extensions/ and turned on Developer Mode:



Finally, I dragged the Chrome extension psTstRecCh.crx file onto the Chrome extension window:



But after a restart, it still didn't work. I could now see the extension listed in Chrome, but it was disabled, and no matter how many times I clicked, it wouldn't enable itself!




Even though the extension was installed, Chrome wouldn't trust it. Even as an Administrator, I could not enable the extension. The final step is to override Chrome's behavior by encouraging it to trust Oracle's PTF extension. We do this through the Windows Registry. The appropriate Windows Registry keys are listed in PeopleBooks under Installing a PTF Client > Configuring Browser Settings. Here is the contents of my *.reg file I imported into my Windows Registry.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome]

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\ExtensionAllowedTypes]
"1"="extension"

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\ExtensionInstallAllowlist]
"1"="boainbfkaibcfobfdncejkcbmfcckljh"

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\ExtensionInstallBlocklist]
"1"="*"

Please note that editing the Windows registry can be risky and potentially cause serious problems, including system instability or even rendering Windows unbootable. Therefore, it's crucial to proceed with extreme caution and only if you are confident in your actions. Always back up the registry before making any changes, and keep detailed records of modifications.

And that was all it took! My PTF recorder is now working as well as ever!

At JSMpros, we teach PeopleSoft tips like this every week. Check out our schedule to see what we are offering next! Have a large group you would like to train? Contact us for scheduling and group pricing.

Monday, June 02, 2025

Have you Considered the Application Services Framework?

 We recently asked the PeopleSoft LinkedIn Community:

Which would you choose to expose a PeopleSoft REST endpoint?

Here were the responses:


The answers surprised me. On the one hand, the IB Service/Service Operation approach was the only option until PeopleTools 8.59. This makes it familiar. However, the Application Services Framework was specifically created for REST. Unlike traditional IB Services and Service Operations, which were designed for SOAP and Web Services, the Application Services Framework focuses on HTTP concepts, such as URL design, status codes, data structures, and more. Here are some benefits the Application Services Framework offers over traditional IB Service Operations:

  • Generates an OpenAPI specification for import by consumer applications.
  • Provides additional HTTP status codes.
  • Uses a PeopleCode API that aligns more closely with REST service design.
  • Eliminates irrelevant metadata creation, such as Message Definitions and Documents.

The Application Services Framework is a REST-specific, REST-focused layer over the top of service-oriented Integration Broker metadata. If you haven't done so already, we recommend reviewing the Application Services Framework. It definitely simplifies REST Service development.

The Application Services Framework is part of our standard Integration Tools training. Join us for our next class to learn more! Already a subscriber? Log in and Get Started!

Tuesday, May 27, 2025

Blueprint 2025


Education sessions at the premier PeopleSoft conference, Blueprint 4D, officially begin in two weeks! Join us in Las Vegas to learn from Oracle product strategy, strategic partners, and Oracle's customers.

The mobile app and agenda are now live. I am presenting the following three fantastic, fun-filled, and educational sessions!

  • Cloud Integration Strategies on Tuesday, June 10 at 5 PM
  • Getting the Most out of PeopleSoft PeopleTools: Tips and Techniques on Wednesday, June 11 at 9:00 AM
  • PeopleSoft Fluid Best Practices on Thursday, June 12 at 3:00 pm.

When we are not in sessions, you can find us in the exhibition hall.

See you there!

Tuesday, May 06, 2025

Which Technology Would You Use for JSON?

We asked our LinkedIn audience:

Which Technology Would You Use to Process JSON?

And they replied:


These answers are fantastic! Based on performance testing and research, PeopleCode native JSON objects, such as JsonObject and JsonArray, perform much faster than the Documents module or external Java libraries. However, there are times when I might choose an alternative.

Java Libraries

PeopleCode leverages the Java Native Interface to provide bidirectional access to Java. Java classes can interact with PeopleCode functions and objects, and vice versa. In addition to the delivered Java API, PeopleSoft provides several key Java libraries, including the Jakarta JSON library. Jakarta stream processing enables us to process enormous datasets. This stands in contrast to native DOM-based JSON parsing, which is limited by the amount of system memory available.

Documents

A document structure may generate either XML or JSON, which might simplify solution development when creating APIs that support multiple output types. Likewise, a document structure is required when creating a REST URI template.

Additional Resources


How about you? What technology would you choose? What are some reasons you might choose an alternative to the native JsonObject and JsonArray?

At JSMpros, we teach JSON processing techniques regularly through our Integration Tools Update course. Check out our online schedule to see what we are offering next! Alternatively, subscribe to gain access to all of our on-demand courses!

Monday, April 21, 2025

Consuming Enormous Datasets with PeopleSoft

Integration Broker is built on the DOM concept, which means it parses data into an in-memory structured document before transforming, processing, or transmitting it. This is fantastic for small and incremental integrations designed to keep two systems synchronized on a per-transaction basis. However, it fails when processing datasets that exceed the amount of available system memory.

An alternative is to use a SAX or stream-based parser that emits events. This type of parser only consumes the memory necessary to emit the next event. Stream-based parsers are highly efficient for one-way, one-time reads through large datasets. Unfortunately, Integration Broker does not support stream-based processing.

While reviewing PeopleSoft's Java class path, I noticed the Jakarta JSON stream-processing Java library. You can find a simple PeopleCode example of processing a JSON file using Jakarta JSON streams in our blog post JSON Stream Processing with PeopleCode. Now that we know how to use Jakarta's stream processing, the next challenge is reading an input stream from an external service. Since Integration Broker does not support streams, we need alternatives. Here are a few Java-based alternatives that readily integrate with PeopleCode through delivered APIs:

  • Java Sockets
  • Java HttpURLConnection
  • Apache HttpClient

Although PeopleCode offers incredible support for Java, the real challenge lies with method and constructor overloading. PeopleCode identifies target Java methods and constructors through parameter count, not parameter type. Java overloading doesn't play well with PeopleCode. The solution I use to overcome method overloading is to leverage Java's support for JavaScript as a translation layer or a "glue." PeopleSoft exposes all functions and objects to Java. Therefore, all PeopleCode functions and objects are also available to JavaScript.

The following is a sample JavaScript that can run from PeopleCode to stream load data into a PeopleSoft table. It uses Jakarta for stream processing and Apache HttpClient to connect to the external service. Both of these external libraries are included with PeopleTools. Notice the use of PeopleCode functions, such as CreateSQL, as well as Java objects such as HttpGet.

I use PeopleCode similar to the following to run JavaScript from PeopleCode. You can find several examples of using Java's ScriptEngineManager on our blog.

Local JavaObject &manager = CreateJavaObject("javax.script.ScriptEngineManager");
Local JavaObject &engine = &manager.getEngineByName("JavaScript");
Local String &script = "JavaScript goes here";
Local Any &result;

&engine.eval(&script);

&result = &engine.get("result");

At JSMpros, we teach PeopleTools and PeopleCode tips like this in every class. Check out our online schedule to see what we're offering next. Would you prefer to learn at your own pace? Purchase a subscription to access all of our on-demand content at discounted rates!

Wednesday, February 26, 2025

Function Library or Application Class?

When we discover redundancies while writing code, the DRY principle (Don't Repeat Yourself) encourages us to refactor our code into reusable definitions. Reasons cited for writing DRY code include:

  • Code that is easier to maintain,
  • Code that scales better as system load increases, and
  • Reduced redundancies in process logic.

With PeopleCode, we have two reusable options:

  • Function Libraries
  • Application Classes

We asked our LinkedIn audience which option they would choose.


The poll results show that 76% would choose Application Classes! Wow! 76% will defer to Object-oriented programming. This is one of those questions that has no right or wrong answer. Both are effective. But is there a more correct answer? Is there a time when using one over the other is more appropriate?

Let's consider App Classes first. Every App Class involves object creation overhead, which means using objects has a cost. But there are two features App Classes contain that set them apart from Function Libraries:

  • State: App Classes have an internal state. App Classes have private, internal variables that persist beyond method invocation.
  • Dynamic Execution: At runtime, we can create objects, set properties, and invoke methods that didn't exist during design time. Function libraries can't do this.

If I know that my solution will require internal state or dynamic execution, I choose App Classes; function libraries are not an option.

Here are a few other reasons people choose Application Classes over Function Libraries:

  • To leverage dynamic testing frameworks such as PSUnit.
  • Extensible framework development through inheritance and composition.

Is there a place for function libraries in modern PeopleCode? This is an interesting question that I think Oracle answers for us. If you look through Oracle's Fluid-specific PeopleCode, you will see a lot of references to Fluid-specific Function Libraries. Why? If you don't need internal state or dynamic execution, then a Function Library may be the fastest, lightweight option.

Consider the following example (adapted from Base64 Encoding with Emoji):

/****
 * You may find a subset of supported character sets in the Javadoc:
 * https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html
 */
Function base64_encode(&textToEncode as string, &charSet as string) returns string
   Local JavaObject &encoder = GetJavaClass("java.util.Base64").getEncoder();
   Local JavaObject &bytes = CreateJavaObject("java.lang.String", &textToEncode).getBytes(&charSet);

   return &encoder.encodeToString(&bytes);
End-Function;

Does it make more sense to expose this reusable algorithm as a Function Library or Application Class method? What do you think? If you choose App Classes, why? If you prefer Function Libraries, we would love to hear your reasons!

At JSMpros, we teach PeopleTools and PeopleCode tips like this in every class. Check out our online schedule to see what we're offering next. Would you prefer to learn at your own pace? Purchase a subscription to access all of our on-demand content at discounted rates!

Tuesday, February 25, 2025

HEUG Alliance 2025!

 


The HEUG Alliance 2025 conference is just over a week away, and I can’t wait! My travel is booked, my bags are packed, and I've added sessions to my agenda through the Alliance Conference App!

I will be presenting the following sessions:
  1. Getting the Most out of PeopleSoft PeopleTools: Tips and Techniques
    - Date: Monday, March 10, 2025
    - Time: 1:30 PM
    - Location: Room 265

  2. PeopleTools Integration Strategies
    - Date: Tuesday, March 11, 2025
    - Time: 9:45 AM
    - Location: Room 265  
I look forward to seeing you there!