Tuesday, November 10, 2015

JavaScript and PeopleCode Array Parameters

I have been experimenting with scripting PeopleCode using JavaScript. This is possible because Java includes Mozilla's Rhino JavaScript engine. I took one of my experiments to OpenWorld 2015 which shows creating a Microsoft Excel Spreadsheet using POI and JavaScript. Here we are, a couple of weeks later, and I see this in the PeopleSoft OTN Discussion Forum: Java Exception: java.lang.reflect.InvocationTargetException: during call of java.lang.reflect.Method .invoke. Perfect! That is my exact use case from OpenWorld. I just happen to have a code sample to share on the forum. The developer's scenario was a bit more complicated. As you will note from the forum post, the developer needed to invoke SQL.Fetch from JavaScript. The JavaScript version of SQL.Fetch, which uses the PeopleCode Java interface, requires an array of selected columns. My first thought was just to use a standard JavaScript array. Since the SQL only has one column, I just needed an array with one item. This didn't work. JavaScript Arrays clearly are not Java Arrays. Here is an example:

var result = (function() {  
    var ReflectiveArray = java.lang.reflect.Array;  
    var CreateSQL = Packages.PeopleSoft.PeopleCode.Func.CreateSQL;  
    var columns = ReflectiveArray.newInstance(java.lang.Object,
        1 /* number of selected columns */);  
    var results = [];  
      
    SQL = CreateSQL("SELECT OPRDEFNDESC FROM PSOPRDEFN WHERE ROWNUM < 10");  
    while (SQL.Fetch(columns)) {  
        results.push(columns[0]);  
    }  
      
    return results.join();  
      
}());  

Monday, November 09, 2015

Friday, November 06, 2015

OpenWorld 2015 Presentations Available

OpenWorld 2015 presentations are now available in the content catalog. My PeopleTools Tips and Techniques session presentation is available here.

Thursday, October 08, 2015

PeopleSoft Streams from Oracle University

In February of this year, Oracle University launched the PeopleSoft Learning Stream. Oracle's Learning Streams are short, educational vignettes. I was given the privilege of recording 6 streams:

  • Using JavaScript with Pagelet Wizard is a 21 minute video showing you how to use Pagelet Wizard to convert a PeopleSoft query into an interactive D3 chart, a navigation collection into a carousel, a navigation collection into an accordion, and RequireJS for JavaScript dependency management.
  • REST Query Access Service is a 15 minute session showing you how to craft a Query Access Service REST URL.
  • Working with JSON in PeopleSoft Document Technology is a 23 minute video demonstrating how to use the PeopleCode Document, Compound, and Collection objects to read and write JSON.
  • Basic Java API with PeopleCode is a 26 minute session showing you how to use the delivered Java API with PeopleCode. This session covers constructors, instance methods, properties, and static method invocation. Java objects demonstrated include String, Hashtable, Regular Expression Pattern and Matcher, arrays, and String.format.
  • Intermediate Java API with PeopleCode is a 38 minute video that shows you how to configure JDeveloper to write Java for the PeopleSoft Application and Process Scheduler servers and provides some examples of writing and deploying Java to a PeopleSoft application server. Note: in this session you get to watch me attempt to troubleshoot an App Engine ABEND.
  • Advanced Java API with PeopleCode is a 26 minute recording showing you how to use Java Reflection to remove PeopleCode ambiguity as well as how to use JavaScript to avoid reflection.

You can access all of my streams here. From this page you can preview the first 2 minutes of each video or subscribe for unlimited access to all of the videos in the Oracle PeopleSoft Learning Stream.

Wednesday, September 30, 2015

JavaScript on the App Server: Scripting PeopleCode

It has been nearly a decade since I started playing with JavaScript on the PeopleSoft application server. Back then I had to deploy a couple of JAR files to the app server. At that time, maintaining and deploying unmanaged files seemed more headache than benefit. Today Java provides full scripting support through the ScriptEngineManager and embedded Mozilla Rhino JavaScript script engine. Why would I want to script PeopleCode? Here are a few of my favorite reasons:

  • Low-level socket communication
  • Avoid reflection: JavaScript executes all methods regardless of variable type whereas PeopleCode only recognizes the returned type, not the real type
  • Process simple JSON structures that can't be modeled with the Documents module

Here is the PeopleCode required 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();

Here is some JavaScript that converts the variable &json_string into a JSON Array and then iterates over each entry, inserting values into a table. Notice that I'm invoking the PeopleCode SQLExec function from JavaScript.

var result = (function() {
  var SQLExec = Packages.PeopleSoft.PeopleCode.Func.SQLExec;
  var json = JSON.parse(json_string);
  var count = 0;
  json.forEach(function(item, idx) {
    SQLExec("INSERT INTO ... SYSTIMESTAMP", [idx, item]);
    count++;
  });
  return count + " rows inserted";
}());

Where did that &json_string variable come from? Here:

&engine.put("json_string", "[""item1"", ""item2"", ""item3""]");

OpenWorld 2015 Conference Schedule

Just a couple more weeks and we will be enjoying the great weather and hospitality of San Francisco. I am anxiously anticipating another great OpenWorld conference. As always, I look forward to meeting with you between sessions or in the demo grounds. I will be presenting "PeopleSoft Developer: Tips and Techniques [CON8596]" on Monday, Oct 26 at 12:15 p.m. in Moscone West—3007.

I find the OpenWorld/JavaOne content catalog a little intimidating. If you are presenting a PeopleTools topic, please post your session details in the comments below to help the rest of us find PeopleTools-related sessions.

PeopleTools Mobile Book Now Shipping

I received notice yesterday that our latest book, PeopleSoft PeopleTools: Mobile Applications Development (Oracle Press) 1st Edition, is now shipping. Probably the most exciting news is that Amazon has the book listed as the #1 New Release in the Oracle Databases category.

Monday, August 03, 2015

PeopleSoft Spotlight Series: Fluid

Have you seen the new PeopleTools Spotlight series? I just finished the Developing Fluid Applications lesson. This 1-hour video walks you through creating a fluid component, including some of the special CSS style classes, such as psc_column-2. The example is very well done and should get new fluid developers headed down the right path.

Monday, June 29, 2015

ReConnect 2015

It is just a little less than a month until the PeopleSoft ReConnect conference in Rosemont, Illinois. I will be presenting PeopleTools Developer: Tips and Techniques on Thursday from 11:30 AM to 12:20 PM in Grand Ballroom H.

Friday, June 26, 2015

New PeopleTools Mobile Book

My wife and I have been writing another book. We are reviewing proofs now, which means we are getting close to publication. I did a quick search on Amazon and see that Amazon is taking pre-orders: PeopleSoft PeopleTools: Mobile Applications Development. Publication date is currently set for October 16, 2015, which means it will publish just before OpenWorld. Fluid and MAP have been out for about a year. If you guessed that a new PeopleTools mobile book would cover these mobile technologies, you guessed correctly. But I saw no reason to stop there. After describing how to use Fluid and MAP, the book moves on to building responsive mobile applications using standard HTML5 development tools and libraries including jQuery mobile and AngularJS. Just today I spoke with a customer still using PeopleTools 8.50. What are the odds that customer will be using PeopleTools 8.54 in the next year? The second section of this book, using HTML5 is perfect for a customer in this situation because it describes how to connect a modern single page application to a PeopleSoft back end using iScripts and REST services (one chapter for each back end solution). The book finishes with examples of building native and hybrid applications for PeopleSoft using the Android SDK, Apache Cordova (my personal favorite), and Oracle's Mobile Application Framework. Here is a rough outline:

Chapter 1 shows you how to prepare your workstation for mobile development. This includes configuring HTML5 browsers, developer tools, and emulators.

Chapter 2 digs into Fluid, showing two examples of creating Fluid pages. The first is a basic page whereas the second is a two-column responsive page. This chapter covers search pages; toolbar actions; and fluid field, page, and component features. The point of this chapter is to help the reader feel comfortable with Fluid. Fluid includes a lot of new features based on HTML5, CSS3, and JavaScript. I really want customers to understand, however, that they can build Fluid pages using core PeopleTools without any knowledge of the modern web concepts. Of course, you can build some really amazing solutions if you know HTML5, CSS3, and JavaScript.

Chapter 3 explains the new Mobile Application Platform (MAP): what it is, when to use it, and how to use it. A chapter wouldn't be complete without examples, so there are plenty of examples to help you start your next MAP project.

Chapter 4 segues into modern mobile development. The rest of the book takes the user interface outside of PeopleTools. Before moving away from Application Designer, however, we need a data model and a scenario. This chapter presents the scenario and lays the foundation for the rest of the chapters. In this chapter you will work with SQL and the Documents module.

Chapter 5 shows us how to create our first HTML5 front end. I wanted to make this chapter as simple as possible so I used jQuery Mobile. In this chapter the reader will write very basic HTML and have the opportunity to see how jQuery Mobile progressively enhances simple markup to create impressive mobile solutions.

Chapter 6 is the exact opposite of chapter 5. Here I wanted to demonstrate flexibility and performance. This chapter is intentionally designed to provide a challenge for developers. Readers tell me it is a good chapter, perhaps a little intimidating, but very worthwhile. In this chapter you will work with AngularJS, Topcoat, and FontAwesome.

Chapter 7 shows the reader how to build back-end services for Chapters 5 and 6 using iScripts.

Chapter 8 is the same as Chapter 7 but uses REST services instead of iScripts. If you are new to PeopleSoft REST services and want to learn how to configure REST services as well as how to work with Documents to serve JSON from Integration Broker, then you will find this chapter very valuable.

Chapter 9 shifts from HTML5 to native. In this chapter the reader will learn how to use the Android SDK to consume the services built in chapter 8. The point of this chapter is not to teach Android development but rather how to consume PeopleSoft services from Android.

Chapter 10 turns to a native application category described as Hybrid applications. In this Chapter the reader will learn how to convert the Chapter 6 prototype into an on-device application that has access to device specific features such as the camera. In fact, the example shows how to use the Cordova API to take a selfie.

Chapter 11 brings us back to Oracle-specific technology by showing how to build a hybrid application using Oracle's Mobile Application Framework (MAF). I chose to spend a little more time in this chapter to teach some of the specifics of MAF. For example, I wasn't very excited about the default appearance of buttons on Android so I included steps showing how to extend the MAF skin.

Publication is still a few months away, but we are getting close. I'm really hoping to be able to give away copies during my OpenWorld session this year.

Friday, June 12, 2015

HIUG Interact 2015 Presentations Available

The HIUG Interact conference is one of my favorite annual PeopleSoft conferences. I learn a lot from the customer and partner presentations delivered each year. As always, my highlight is interacting with customers.

All of my presentations are now available through the HIUG conference site. Be sure to download the slides because these slide decks contain a lot of information we didn't have time to cover in our sessions. For reference purposes, here is a list of sessions I presented at Interact 2015:

  • What's New with PeopleSoft Reporting - Query, Pivot Grids, BI Publisher
  • Configuring and Utilizing the Interaction Hub -- Deep Dive
  • PeopleTools Developer Tips and Techniques
  • Fluid User Interface and Mobile Application Platform - Deep Dive

Friday, March 06, 2015

Collaborate 2015

Collaborate 2015 is just a few weeks away. I will be presenting PeopleSoft PeopleTools Developer: Tips and Techniques on Tuesday, 4/14/2015 at 3:15 PM in Surf B. If you are presenting a PeopleTools technical session, then please post a comment with your session title, date, time, and venue. I look forward to seeing you next month!

Wednesday, February 11, 2015

Using RequireJS to Manage Dependencies

I have a handful of blog posts describing how to deal with JavaScript dependency conflicts such as multiple library inclusions, namespace conflicts, etc. These workarounds are necessary in portal environments that mash up content from various providers that may use the same libraries. On a portal (Interaction Hub) homepage, for example, you may have a Pagelet Wizard pagelet that uses the jQuery Cycle plugin as well as a Pagelet Wizard pagelet that uses jQuery UI. Both of these pagelets will include the jQuery library, but different jQuery plugins. As each pagelet loads, it will load jQuery and then its required plugins. Both pagelets will try to put $ and jQuery into the global (window) namespace. The last pagelet to load will reload window.$ and window.jQuery causing the browser to drop any previously loaded jQuery plugins.

One technique JavaScript developers use to manage dependencies in a scenario like this is to use RequireJS with Asynchronous Module Definitions (AMD). With RequireJS and AMD, you would define a RequireJS configuration file pointing to each JavaScript library and plugin and then write JavaScript that uses these libraries with a RequireJS closure. This approach keeps custom libraries out of the global namespace and ensures that libraries only load once (not once for each pagelet). PeopleTools 8.54 makes implementing this really easy through the new Branding Objects module and Branding System Options. Let's review an example. Let's say that I have RequireJS, jQuery, and jQuery UI loaded into JavaScript objects in the Branding Objects module as shown in the following image

Now let's say you have your Branding System Options configured to include RequireJS and the RequireJS configuration file as described in the following screenshot:

You could then create a Pagelet Wizard pagelet containing HTML like the following and not worry about dependencies or namespace pollution. Everything would just work

<div id="NAA_DIALOG_TEST_html">
  <style type="text/css">
    @import url(%StyleSheet(NAA_JQ_UI_1_11_2));
    #NAA_DIALOG_TEST_html .dialog { display: none };
  </style>
  <script>
      require(['jquery', 'jqueryui'], function ($) {
        $(document).ready(function() {
          console.log("dialog pagelet is using version " + $.fn.jquery);
          $("#NAA_DIALOG_TEST_html").find("button")
              .button()
              .click(function( event ) {
                event.preventDefault();
                $("#NAA_DIALOG_TEST_html .dialog").dialog();
              });
          });
      });

  </script>
  <button>Show Dialog</button>
  <div class="dialog" title="Basic dialog">
    <p>This is the default dialog which is useful for displaying information.
    The dialog window can be moved, resized and closed with the 'x' icon.</p>
  </div>
</div>

Of course, this assumes that your RequireJS configuration file looks something like this:

/**
 * RequireJS global configuration. Include after RequireJS in branding settings
 * 
 * @returns {undefined}
 */
(function () {
  /**
   * Build a URL based on the current component's URL
   * @param {type} scriptId
   * @returns {String} derived URL for JavaScript
   */
  var getScriptUrl = function (scriptId) {
    var mainUrl = /*window.strCurrUrl ||*/ window.location.href;
    var parts =
        mainUrl.match(/ps[pc]\/(.+?)(?:_\d)*?\/(.+?)\/(.+?)\/[chs]\//);
    return window.location.origin + "/psc/" + parts[1] + "/" + parts[2] +
        "/" + parts[3] +
        "/s/WEBLIB_PTBR.ISCRIPT1.FieldFormula.IScript_GET_JS?ID=" + scriptId;
  };

  require.config({
    paths: {
      /* Using non-standard name because 1.6.2 is not AMD compliant whereas
       * later versions are compliant. Don't want conflict with later version
       */
      'jquery': getScriptUrl("NAA_JQ_1_11_2_JS"),
      'jqueryui': getScriptUrl("NAA_JQ_UI_1_11_2_JS"),
      'jquery-private': getScriptUrl("NAA_JQ_PRIVATE_JS")
    },
    map: {
      // '*' means all modules will get 'jquery-private'
      // for their 'jquery' dependency.
      '*': { 'jquery': 'jquery-private' },

      // 'jquery-private' wants the real jQuery module
      // though. If this line was not here, there would
      // be an unresolvable cyclic dependency.
      'jquery-private': { 'jquery': 'jquery' }
    }
  });
}());

And your jQuery-private module looks something like this:

// http://requirejs.org/docs/jquery.html#noconflictmap
define(['jquery'], function (jq) {
    return jq.noConflict( true );
});

What's up with the getScriptUrl function? JavaScript HTML definitions do not yet support %JavaScript Meta-HTML. The getScriptUrl JavaScript function attempts to perform the same task, but using client-side JavaScript.

Why do we need a jquery-private module? The point is to hide all of our dependencies and just expose them within the RequireJS closure. That way we avoid conflicts with older code that uses jQuery as well as any PeopleTools delivered JavaScript that may user

This technique also works well for loading dependencies. I often use a JavaScript library in a pagelet, with JavaScript executed directly in the pagelet. One challenge I have had is ensuring that my browser parses and processes any JavaScript libraries before JavaScript embedded in a pagelet. RequireJS solves this by first loading the dependencies, and then executing the JavaScript within the define/require function.

Note: For this to work properly, it is important that your JavaScript libraries are either AMD compliant or can be appropriately shimmed. Current versions of jQuery and jQuery UI are AMD compliant. The older version of jQuery UI that ships with PeopleTools 8.54 and earlier is NOT AMD compliant. Instead, I downloaded the latest jQuery UI and uploaded it using the new Branding Objects module. To work successfully, the jQuery UI CSS must be updated to use %Image() for each image resource and each image must be uploaded using the Branding Objects component.

Thursday, February 05, 2015

Alliance 2015

I am looking forward to seeing everyone at the Alliance conference in Nashville next month. I was just reviewing my schedule and see lots of interesting technical sessions (as always). If you have room in your schedule, I invite you to attend my session on Tuesday, Mar 17, 2015 from 11:15 AM to 12:15 PM in Presidential D. The session is titled PeopleSoft PeopleTools Developer: Tips and Techniques. If you can't make it to my session, then perhaps I'll see you shortly thereafter at Meet the Experts from 1:45 to 2:45 (table 11)? I'll be around the conference all week and will be working in the demo grounds when I'm not attending sessions. See you in a few weeks!