Wednesday, March 24, 2021

Announcing PeopleSoft Fluid Day! A one-day Fluid Webinar

Announcing PeopleSoft Integration Day! Are you ready to learn Fluid? Or, do you already know Fluid, but want to learn more? Join us online Thursday, May 20, 2021 for a full day Fluid Development Experience! Space is limited so register now!

Register Now!

Here are some of the topics we will cover and questions we will answer:

Classic versus Fluid

Both Classic and Fluid use App Designer to create solutions. Both support drag and drop page design. So what are the differences? And if you know Classic, what do I need to learn to be proficient with Fluid?

Mobile

Isn't Fluid mobile? If so, why aren't my grids responsive? What mobile-friendly options exist for grids?

Drag and Drop

PeopleSoft homepages allow us to drag and drop tiles. AWE allows us to drag and drop fields. How can I implement Drag and Drop on my own Fluid pages?

Branding

What does it take to create a branding theme for a PeopleSoft instance? How do you brand both Classic and Fluid? Do I have to use Branding Macros with Fluid? Are there alternatives?

Drop Zones

Where can I use Drop Zones? What can I do with them? What if a component doesn't have Drop Zones? Are there limitations with Drop Zones? Since Drop Zones and Event Mapping don't appear in compare reports, how do we know what to review after a system update?

PeopleSoft Test Framework (PTF)

How do you implement PTF? Are there any challenges to using PTF with Fluid? Are there special considerations for PTF with Event Mapping and Drop Zones?

Do you have a group of 10 or more? Contact us at info@jsmpros.com for a quantity discount!

Register Now!

Wednesday, March 17, 2021

Where do you terminate SSL for PeopleSoft?

Most PeopleSoft implementations have some sort of firewall/load balancer appliance in front of PeopleSoft. As an administrator, one question we have to answer is, "Where do we terminate SSL?" And the answer seems so obvious, most don't even ponder the question. What is the obvious answer? Terminate at the load balancer. Why? Because that is why they exist. SSL/TLS is what they do, and they do it well. What's the alternative? Carry SSL all the way to Weblogic, and terminate at the PeopleSoft web server. Weblogic is amazing at what it does, but it isn't a security appliance. And that is why the obvious answer is to terminate at the load balancer. But here is my question:

Are you reencrypting the traffic between the load balancer and PeopleSoft?

Do you encrypt all the way to Weblogic or do you terminate at the load balancer, thereby passing sensitive information in plain text behind the firewall?

Over the last several years I have heard fantastic security presenters recommend SSL termination at the load balancer level (for good reason). But they always end encryption at the load balancer. They don't encrypt behind the firewall. Why not? The most common reason is performance. Encryption isn't free. And if encryption is expensive, why encrypt behind the firewall? Here are two reasons:

  1. Your network might not be as secure as you think it is. A great example is NASA's breach implemented through a Raspberry PI.
  2. PeopleSoft-delivered service operations expect encryption.
As a developer, I defer to the network infrastructure design team. If they say the network is secure, I take their word for it. But take a look at reason #2. There are several PeopleSoft-delivered service operations that verify encryption at the Weblogic level. If I want to use those delivered service operations, I either need to:
  • Carry SSL/TLS all the way to Weblogic or
  • Modify the Service Operation.
Which would you prefer?

Monday, March 01, 2021

PeopleSoft Open Source Projects

Open Source Initiative keyhole

Did you know there is a vibrant PeopleSoft Open Source community? PeopleSoft is the most flexible ERP solution available. If we need additional functionality, we can build it. And that is exactly what several talented developers have done, and they've shared their solutions with us. Check out some of these amazing open-source projects and repositories:

Please note, I have only tested a few of these projects, and make no claims about their state or function. My objective with this post is awareness.

Do you have a solution others could benefit from? Have you thought about sharing it as an Open Source project?

Do you have a project you would like added to the list? let us know in the comments!

Wednesday, February 24, 2021

Setting IB Request Content Type

In our Integration Day 2021 One-day Webinar, we showed how to send SMS from PeopleSoft through Twilio. What makes Twilio interesting is that Twilio expects URL encoded form data. As you may know from using Integration Broker, PeopleSoft is quite happy sending and receiving JSON or XML. But what about other content types, such as application/x-www-form-urlencoded? You may know that you can set most HTTP headers using something like:

&request.IBInfo.IBConnectorInfo.AddConnectorProperties("Content-Type", "application/x-www-form-urlencoded", %Header);

That's a mouth full! But the weirdest thing happens when trying that trick with URL encoded form data. PeopleSoft URL encodes the entire body! Wait, isn't that correct? No, actually. When you and I create the body, we create the proper key=value&key2=value2 pairs. Proper URL encoded form data would look something like this:

key=This+is+some+encoded+data&key2=value2

Keys, ampersands, and equals signs should not be encoded (unless part of the value). But PeopleSoft URL encodes everything as if there were no keys. Here is what that same string above looks like when PeopleSoft finishes with it:

key%3DThis%2Bis%2Bsome%2Bdata%2Bto%2Bencode%26key2%3Dvalue

It is just supposed to URL encode the values. Or better yet, just let us URL encode the values. What's the workaround?

&request.SegmentContentType = "application/x-www-form-urlencoded";

This solution is a little strange because we aren't using a multi-part, segmented message, but it works!

While performing research for this post, I came across MOS Doc ID 2187249.1, which asks for an enhancement to allow additional, hopefully even custom, Content Types, so it appears URL encoded form data isn't the only issue. But lucky for us, we have SegmentContentType as a workaround!

Are you interested in learning more about PeopleSoft Integration Broker and integration strategies? Join one of our live virtual top-rated Integration Tools Update courses!

Friday, February 05, 2021

PeopleCode to Move a File... sort of

You ever need to move a file through PeopleCode? Perhaps an App Engine program that needs to move generated content into the process output directory? I found myself in that position today. Surely there is a PeopleCode function for that... right? If you have one, please share it, because it seems the Internet doesn't know about it. A quick Internet search turned up several examples of using Exec with mv. I'm always weary of Exec. If I have to use the command line, I prefer to control it through the Java Runtime (see Exec Processes while Controlling stdin and stdout). Speaking of Java, can we borrow anything from the JRE? I did find my old ITToolbox response showing how to use java.io.File.renameTo to move files. It is still a great solution, but with multiple mounted file systems... well... it actually might fail. So I got to thinking... what about using java.nio? Here is an example:

Local JavaObject &jSource = CreateJavaObject("java.io.File", "c:\temp\JSM_TEST.log").toPath();
Local JavaObject &jTarget = CreateJavaObject("java.io.File", "c:\temp\JSM_TEST_moved.log").toPath();

Local JavaObject &jFiles = GetJavaClass("java.nio.file.Files");
Local JavaObject &jOptions = CreateJavaObject("java.nio.file.CopyOption[]");

&jFiles.move(&jSource, &jTarget, &jOptions);

And, what if you want to overrwrite the destination? Try it with copy options:

Local JavaObject &jSource = CreateJavaObject("java.io.File", "c:\temp\JSM_TEST.log").toPath();
Local JavaObject &jTarget = CreateJavaObject("java.io.File", "c:\temp\JSM_TEST_moved.log").toPath();

Local JavaObject &jFiles = GetJavaClass("java.nio.file.Files");
Local JavaObject &jStandardCopyOptions = GetJavaClass("java.nio.file.StandardCopyOption");
Local JavaObject &jOptions = CreateJavaObject("java.nio.file.CopyOption[]", &jStandardCopyOptions.REPLACE_EXISTING);

&jFiles.move(&jSource, &jTarget, &jamp;Options);

For more details about copy options, take a look at the Java Docs.

Are you ready to take your PeopleSoft development skills to the next level? Check out our latest course offerings at jsmpros.com. Prefer a custom agenda? Contact us for details.

Thursday, January 21, 2021

Integration Broker OnError Method

Do you know what happens when an Integration Broker handler App Class throws an Exception? REST, SOAP, or plain XML over HTTP all behave mostly the same. By default, PeopleSoft returns the error message to the client. This is great! It means you and I don't have to write error handlers, right? Actually, I hadn't given it much thought until working with REST. With REST, I want to leverage HTTP status codes. For example, if a REST client requests data that doesn't exist, I want to return a 404 status code. But if you throw an exception from an OnRequest REST handler, the default Integration Broker OnError handler returns a 200 (success) status code and an HTML content type. An exception should not return a 200. Fortunately, we can override the REST HTTP response code through the recently documented OnErrorHttpResponseCode and OnErrorContentType properties of the the Request Handler interface (see MOS document 2026747.1 for more details). You set these properties from a handler's OnError method, which is the method Integration Broker invokes when the handler method throws an exception. So here is a snippet from our Integration Tools Update course:

method OnRequest
   ...
   SQLExec(...);
   
   If (%SqlRows = 0) Then
      throw CreateException(0, 0, "Item not found");
   End-If;
   
   ...
end-method;

method OnError
   /+ &request as Message +/
   /+ Returns String +/
   /+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
   
   REM Create fault response;
   ...
   
   %This.OnErrorHttpResponseCode = 404;
   %This.OnErrorContentType = "application/json";
   
   Return "<response string goes here>";
end-method;

Notice the code throws an exception when no rows are found. When OnRequest throws an exception, Integration Broker invokes the OnError method, and the OnError method returns a hard-coded 404. So, let's think about this a little more... as you see, the OnError handler ALWAYS returns 404. What if something else goes wrong? Shouldn't I see another status code? Great question! That's a topic we'll save for another post. But let's address a different issue. What happens if your OnError handler throws an exception? PeopleSoft drops the OnError handler and returns the response it would have returned without an OnError handler, meaning a status code of 200 with HTML content type. It's sort of like PeopleSoft invoked your OnError method, which threw an exception and PeopleSoft said, "Oh, just kidding," and reverted to its default behavior.

Now, let's say you are testing your OnError handler, but it seems like Integration Broker is ignoring you. I mean, no matter what status code you set in your OnError method, PeopleSoft returns a 200. First, if this is happening to you, chances are high, your OnError method is throwing an exception. But how can you troubleshoot this? Here is my debugging strategy: Open a file object and print lines. For each line in the OnError handler, I print a line to my log file. I can then open the log file and see when PeopleSoft stopped printing to my log (I'm basically tracing my own code).

OK. Now, let's say you have all of the bugs worked out of your OnError handler, and you are ready to move to production. How can you ensure PeopleSoft will return a 400-level status code if the OnError handler throws a runtime exception? Wrap your code with a try block to catch errors. You then retain control over the HTTP response code and content type.

Are you interested in learning more about Integration Strategies? We believe Integration is one of the most important PeopleTools technologies for today's distributed enterprise. Visit ibupdate.jsmpros.com to see when we are offering our next Integration Course. Have a group of developers to train? Contact us for special group pricing!

Tuesday, January 12, 2021

Is PeopleSoft Fluid Mobile-ready? Grids

Vertical scrolling on mobile is perfectly acceptable. But horizontal scrolling is an absolute no-no! So if Fluid is mobile, why is my Fluid grid so wide? Why doesn't it reflow into a vertical rendering? Great question! A Flex Grid is the Fluid version of the plain-old Classic Grid. The only difference is the Flex Grid stretches to fill its container, whereas a Classic Grid's width is fixed. The Flex Grid is likely the most common Grid type for desktop, but it doesn't fit well on smaller form factors, as you may have experienced. So what can we do? The most common solution is to use PeopleCode to change the grid type. In the post Is PeopleSoft Fluid Mobile-ready? Setting the Browser Viewport, we said that Fluid + PeopleCode = Mobile, which holds true for grids. We can use PeopleCode to transform a Flex Grid into a mobile-friendly type, such as a List Grid, Div Grid, or Data Grid. Here is an example:

If %Request.BrowserDeviceFormFactor = %FormFactor_Small Then
   /* change to LIST grid */
   &grid.Layout = %ListGrid;
End-If;

PeopleCode alternatives include:

  • Stacked Grid Group Boxes,
  • Stacked Grid Group Boxes with Suppress-on attributes, and
  • Custom CSS with breakpoints

With this in mind, let's extend our Fluid development formula to: Fluid + PeopleCode + Style Classes + Attributes = Mobile.

We cover grids in great detail in our Fluid 2 course, including Flex, List, Div, and Data grid types, and how to transform grids using PeopleCode and CSS. Checkout fluid.jsmpros.com to see when we are offering it next. Do you have a group of developers to train? Contact us for special group pricing!