Category Archives: Web Apps

Using Oracle JET from APEX

This post contains statements about possible future functionality. These are not official statements. They are speculative, subject to change, and should not be relied upon.

Reading svenweller’s recent article Integrate Oracle JET into Apex 5.0 got me thinking about this topic. I’m very busy working on Interactive Grid in APEX 5.1 right now but this is an important topic and there is a need to get some information out sooner rather than later. I’m not going to go into how JET and APEX are great, why it makes sense to use them together or provide step-by-step instructions for doing so. See svenweller’s blog for that.

By now most APEX developers have heard that we plan to include Oracle JET based charts in APEX 5.1. It is generally easy to use 3rd party JavaScript libraries with APEX. Here I want to talk about why Oracle JET is a special case and give some tips for making them work together. I want to share what we have learned so far in integrating JET charts with APEX. I should mention that I am not the main person working on the chart feature.

What makes using Oracle JET with APEX tricky is that JET requires you to use RequireJS. So the same issues apply if you were to integrate any code that uses RequireJS with APEX. It is not specific to Oracle JET. Furthermore, you would have similar issues trying to use JET with any traditional web app that isn’t already using RequireJS.

Is RequireJS bad? No. Is APEX somehow at fault? No. What’s going on here? Its complicated…

The traditional way of using JavaScript on a web page is to put it in script tags and call it. Lots of libraries? No problem. Just figure out what order to put all the script tags in. Each script file adds some global symbols for the others to use. Namespace objects are used to reduce the number of globals — its a kind of modularity. This is what APEX does. It is conceptually simple.

Then modules were invented as a way to keep code, well, modular and explicitly define what your module exports and what dependencies you have on other modules. Just one script tag and the module system (in this case RequireJS) does all the loading. The only globals are from the module system (define, require, requirejs). This is also conceptually simple but different concepts.

There is nothing wrong with either of these ways of building web apps. I have nothing against modules. I like using the Node.js module system. But APEX has a long history and simply cannot switch over to using RequireJS modules without breaking existing applications.

These are two very different worlds that don’t mix well. Its hard to ease into using modules because of what happens when the existing non-module code and the new module code wants to share a library.

If you are the creator of a handy library you want to increase your user base by being usable in both worlds. (I’ll use Hammer.js as the example simply because it is a library that both JET and APEX Universal Theme use.) Its easy to do, just add at the bottom of your code something like the following:

// this is just slightly simplified from the actual hammer.js code
if (typeof define == "function" && define.amd) {
    define(function() {
        return Hammer;
    });
} else {
    window.Hammer = Hammer;
}

Now the library can be used in a module system if the page is using one or just define a global for the traditional way.

But if a single page has some code that uses RequireJS and some code that uses the traditional way and both want to use the same library (Hammer.js in our case) there is a problem.

A) If the hammer.js script tag is loaded after require.js it defines an anonymous module as shown above and then as soon as you do anything else with RequireJS you get the error: Mismatched anonymous define() module. The reason is that RequireJS insists that all anonymous modules are loaded from a define or require call. The assumption is that as soon as RequireJS is on the page you are using the new modular way.

B) If the hammer.js script tag is loaded before require.js it defines its global Hammer object so that traditional code can use it. Then when module code uses require(['hammer'...]...) or something equivalent it will get a new copy of the Hammer object. You can prove this with the following code:

require(["hammerjs"], function( h ) { console.log( h === window.Hammer );});

If the the new module code and the global Hammer object were the same it would print true but it prints false. At least there is no error and it seems to work but… Ideally we would like to avoid this. Depending on what the library does it could result in more than just wasted memory.

We had a similar problem with jQuery where after RequireJS was used by JET Charts all our APEX jQuery UI widgets were essentially “gone” because there were two different jQuery objects ( $ !== apex.jQuery ). Note jQuery is a special case in that it defines a named, not anonymous, module so it doesn’t suffer from the error in case (A). You may also say that it is best to always use apex.jQuery rather than $ and you are correct but not everyone follows this rule all the time. And we still don’t want to waste memory on duplicate copies of libraries.

With this background out of the way here are my recommendations.

  • Load require.js as late as possible because problem B is much easier to deal with than problem A. (How to deal with problem B is coming up.)

    RequireJS would like to be the first (and only) script tag on the page but it doesn’t have to be. In order to keep any RequireJS aware libraries such as hammer.js or jQuery from calling define, require.js should be included after them. The best way to do this is to add require.js to a page in page attribute JavaScript: File URLs.

    With this approach you don’t need to throw out hammer.js just to use Oracle JET. Hammer.js is useful when running your app on touch devices.

  • You don’t need to use data-main on the require.js script tag. It is not required, just a convenience. Your code that includes the call to requirejs.config can be handled like any other JavaScript code. If you put it in a file, reference that file in JavaScript: File URLs (after require.js). It can even go inline by putting it in JavaScript: Execute when Page Loads.
  • To get around the problem of loading multiple copies of a library add the following code after the call to requirejs.config and before any calls to require
    define( 'hammerjs', [], function() {
        return Hammer;
    });
    define( 'jquery', [], function() {
        return apex.jQuery;
    });
    

    What this does is define the library module with a name in the RequireJS module system so that it will not be loaded again. It is important to use the same name that the library uses in the config paths object passed to requirejs.config. This can be extended to other libraries if needed.

    Note: If different versions of a library are needed then you may just have to let two copies be loaded. In this case remove the corresponding call to define.

  • You probably don’t need to use knockout. I don’t know for sure if this is true for all JET components but it is true for JET Charts. APEX 5.1 is not using knockout at all. I have nothing against knockout. However, it is of most benefit if it is used pervasively through out an app. Otherwise it is just another another library to load for which there are other ways to do what it does. That said, if you want to use it go ahead.

At this point I don’t know what if anything APEX 5.1 will do to make integrating Oracle JET (or RequireJS in general) easier. For now I hope this helps anyone trying to use JET with APEX 5.0.

How to identify Survey Builder respondent

It has been a while since I have worked on the APEX Survey Builder packaged application but I still get questions about it. One question that comes up repeatedly is how to associate the questionnaire responses with the person that responded. At first this question surprised me somewhat because survey research is about populations not individuals so surveys should be anonymous. To quote Designing an Effective Survey by Mark Kasunic:

“A survey, when conducted properly, allows you to generalize about the beliefs and opinions of many people by studying a subset of them”

Survey research lets you say with confidence “87% of our customers feel that the produce makes them more productive” not that John Snyders thinks he is more productive after using the product.

Continue reading How to identify Survey Builder respondent

APEX Item Submission

In his 3 part series ending with APEX and the Order Items are Submitted, Martin D’Souza did a great job explaining how APEX page items are submitted and why you can’t reorder the DOM in arbitrary ways. If you haven’t read it already it I strongly recommend that you do so. I can’t improve on how he explained it but I have just two things to add.

Why does APEX do this?

I was very confused by this when I first joined the APEX team. I think that others especially people with front end web development experience will also wonder why APEX uses p_arg_names and p_tnn names rather than the more traditional way where you get to name your inputs as you please. For example <input name="phone_number"...>.

Martin explains that the p_arg_names values are used to map the post parameter values back to the APEX item metadata. The other part of the puzzle has to do with how HTTP post parameters are passed into the APEX engine. The interface between the web listener and APEX Engine maps post parameters to PL/SQL procedure formal parameter names. So there is actually a PL/SQL procedure with formal parameters named p_arg_names and p_t01, p_t02…p_t200. The same procedure is used for all apps and all pages so this is why fixed names must be used.

A subtle and unfortunate consequence.

If you have used any APEX applications you have undoubtedly run into the situation shown in the following image where the browser auto complete feature offers suggestions that have nothing to do with the current field.

Auto Complete

How a browser implements the auto complete feature is up to the browser (meaning there is no common specification that must be followed) but the primary method of choosing what values to show is the name attribute. Fields with the same name tend to show the same auto complete choices. The underlying assumption that browsers are making is that web developers choose meaningful names for input fields such as firstName, phone_number, etc. With APEX this assumption fails. Because the name attribute is assigned automatically and sequentially, it is the order of the form item on the page that determines what auto complete values will be shown.

I’m a little surprised that more people haven’t complained about this. Its a tricky problem to solve and it may not even be worth solving. How bothersome do you find this?

Scoring Rock Climbing Competitions

The last two years or so I have been very busy working on APEX 5.0. This is the main reason for not posting anything in so long. It’s not that I was so busy with work that I did nothing else, but just that I didn’t have the motivation to write. I should have plenty to write about APEX soon. But this post is about another interest of mine; rock climbing.

My youngest daughter climbs competitively and I try to climb at least twice a week when I bring her to team practice. The local climbing comps consist of proud parents watching their kids climb the hardest routes they can and then, when the scorecards are turned in, waiting around for an hour or more while the scores are tallied. It is not uncommon for people to leave, get lunch, and return before results are announced. In our area, climbing comps typically have 100 or so competitors.

In early 2014 a climbing friend, Matt, who was also responsible for scoring an upcoming competition had some ideas for how to make the scoring go faster. He asked me what it would take to create an app to do scorecard data entry. I saw the project as an opportunity to learn some new technologies I was interested in, specifically node.js, and jQuery Mobile. I picked a mobile web app because it is the best way to reach the widest range of devices with the least effort.

Climbing comps are traditionally scored using an Excel spreadsheet. For each scorecard you look up the row of the climber by name and then enter the number of points for the top 5 climbs and the number of falls (or attempts). The spreadsheet creates a bottleneck because only one person can be doing the data entry. Even if the bottleneck were removed by splitting up the spreadsheet by gender and/or category (or using Google Sheets), the data entry would still be tedious and error prone because of all the numbers that must be typed in. This is why it takes so long to get the results and give out the ribbons so the kids and families can go home and the climbing gym can open for regular business.

I worked a few weekends on the climbing comp mobile web app. I already enjoyed programming in JavaScript and learning node.js was a lot of fun and pretty easy. I chose a thin-server architecture with MariaDB for the database, restify on node.js for the REST resources and static content, and jQuery Mobile for the front end. I specifically wanted to minimize the number of libraries and avoid using a heavy weight MVC framework. This was to reduce the number of new things to learn at once, focus on the things I did want to learn without additional layers, and experience the pain points first hand, so I could better choose what additional libraries or frameworks I might want to add or switch to in the future.

By the time of the first competition, the app was working well enough to be used. The database had to be loaded with climber and route data with command line scripts, but the UI for data entry and reporting results worked. The key point of the app is that the UI closely resembles the score card and it already knows the point value of each route. Data entry is simply a matter of entering the 3 digit climber number from the score card using an on screen keypad, touching each route they topped, and touching the number of falls; 7 taps. The UI is optimized for tablets, but works well on laptops as well, and the UI is responsive so it can even be used on a phone.

On March 15th 2014 we used the climbing comp app for the first time at the Boston Rock Gym. The server and database were running on Matt’s laptop. We had between 3 and 4 people doing data entry on iPad or Android tablets. As scorecards came in, they were divided between the people doing data entry and quickly entered into the app. When time is called, any climbers that are waiting in line get to finish their last climb. By the time the last climber was on the wall, all the other scores had been entered. The owner of the gym had the honor of entering the last scorecard and the scoring was complete before the last climber’s feet touched the ground. The app was a great success. On the down side at least one family, expecting a long wait, left for lunch and returned to find that the ribbons had already been given out.

Since then, the app has been used successfully at two more comps. Before each one I have added new features and fixed bugs. Now climber and route data can be entered or uploaded from the app UI rather than using command line scripts. There is plenty more work to be done but it is just about at a point where others could use it. (Currently, it only works for red point format comps.) ClimbingComp is available on github for anyone to download and use.

Survey Builder Design

One of my first projects after joining the APEX team was creating the Survey Builder packaged application (available in Oracle Application Express 4.2.2). This was my first experience creating an APEX app. A number of people helped out on the implementation (especially on reports) and also helped me learn APEX. I worked on the overall design and functionality and focused on implementing the questionnaire page and questionnaire editing page, both of which required lots of JavaScript. The paper Designing an Effective Survey by Mark Kasunic provided invaluable background information on the survey process and I recommend it to anyone new to conducting survey research.

Survey Builder is a little different from typical APEX apps (if there even is such a thing as a typical APEX app). Here I want to describe a couple of requirements that shaped its design and the resulting APEX implementation. A great thing about APEX is that it comes with a number of fully functional packaged applications such as Survey Builder that you can use as-is, tweak to do what you want or just open up to see how it works. So feel free to install Survey Builder, unlock it, and follow along.
Continue reading Survey Builder Design

REST, APEX, PL/SQL and Me

This past Sunday I gave a talk at the ODTUG Kscope conference in New Orleans titled Implementing RESTful Web Services with Oracle Application Express. The presentation along with sample code and test tool can be downloaded from the APEX collateral page on OTN.

I’ll describe the talk a little more at the end but first I want to tell how I got here. I’m not talking about my flight but rather what’s a Java web developer doing talking about APEX.

I was on the WebLogic Console team, then I moved around a little bit and now I work on the APEX team.

Long ago when I created my first web app with Java I was a Java Developer using Java to make a web app. But as time went on — and along with an industry wide shift in focus from the server to the client — I became a web developer implementing the back-end in Java. I now prefer JavaScript over Java. I also prefer working on the infrastructure for web apps (including making rich UI widgets) compared with just the apps themselves.

For a long time now I have believed that there is an easier way to make web apps and the key is in declarative specification. My ideas for a declarative framework had support within the Console team but projects, priorities, and people tend to shift around. First I was moved to the Fusion Middleware Control team, which has a very good manager and team but ADF was never a good fit for me. Then I got an opportunity to work on an HTML 5 related project that had the potential to realize my declarative framework ideas but that turned out not to be a good fit either. Meanwhile I started to notice that although Oracle advertises ADF as the way to build web apps that there were some internal web apps that were clearly not built with ADF. I looked a little closer at these apps and found this thing called APEX.

I could tell just by looking at the UI design and the HTML, CSS, and JavaScript behind these APEX apps that there was a framework there that knows what html 5 and modern web apps are about and is actively working to get there. I read a little more about APEX and came to understand that APEX really gets declarative rapid app development. I contacted Joel Kallman and let him know what I do, what I understood about APEX, and asked if they wanted my help. Then, bam, just like that I was on the APEX team. (at Oracle bam means 3 months later.)

For the most part I work on JavaScript code in APEX. One thing Joel said to me in our first conversation is: You know APEX is written in PL/SQL right? Sure, I said, but it took a while for this to fully sink in. I figured I would probably need to read PL/SQL but would mostly write JavaScript. I have ended up learning PL/SQL and writing a fair amount of code. I enjoy learning new languages but PL/SQL was never on my list of languages to learn. It may be unusual for a Java developer to switch to PL/SQL — you more often hear of them moving to Ruby or Scala — but I don’t hate it. It does feel like an old fashioned language to me but when it comes to programming the Oracle database there is no better choice. I think it does a great job of fitting in with the SQL style. I like using the right tool for the job. Putting the business logic close to the data makes a lot of sense to me especially compared to the complexity and overhead of object-relational mapping.

I’ve been on the APEX team for just over a year now and I’m very happy. The APEX team is a great bunch of people to work with. Also the APEX community is very active and I’m getting to meet some of them here at Kscope.

So back to the talk I gave. The ability to define RESTful Services in APEX is new in version 4.2. I didn’t work on any of the implementation of it but I have a general interest in REST and experience from creating the REST infrastructure for WebLogic Console so I wanted to try it out. Because APEX RESTful Services is so new it was lacking in examples and documentation but that is starting to change. The latest APEX Listener download includes a doc folder with very helpful information. In my talk I walked through a (mostly) complete example of a REST API for the sample database application, which I believe demonstrates many best practices of REST. I also created a tool for testing RESTful services that has a few features that make it ideal for APEX RESTful Services. Both the example and APEX RESTful Services Test Client are available for download. If you have any comments, questions, or feedback on the test tool or example please let me know.