23 June, 2011

'Growl' style notification messages for APEX

A question was asked in this thread on the APEX forums that got me itching to do a science experiment.
The basic question was this:

"Is it possible to produce 'Growl' style notifications in place of the standard APEX Success and Failure messages?"
In short the answer is an unequivocal 'Yes', and here's how:

First, unless you're a JavaScript whiz and can write your own, you'll need to search out some sort of JavaScript library that provides the Growl style notification. After a quick Google search I found this page...


I chose to search for jQuery related notification systems because of the fact that jQuery is already integrated into APEX 4 and that would mean that there would be less in terms of external JavaScripts for me to load and manage.

After looking at the individual option there, I chose to work with Gritter for a number of reasons.
  1. I liked the look and feel of it's output. To me it felt the most like what I am used to seeing from Growl.
  2. The JavaScript is very light. In total it's about 400 lines long un-minified. Much of that is white space and comments which means that minified it's going to be minute.
  3. It pushes most of the heavy lifting back onto jQuery, where it should be, and the author doesn't try to over engineer the solution.
You can choose what ever library you wish, but in this example I'll be using Gritter.

The first thing you need to do is put the Gritter JavaScript where it can be accessed by APEX. As a general rule of thumb, it's a very bad habit to get into to put your own code into the /i/ directory provided by Oracle. So we create a directory on our web server to hold all of our custom code, normally named /c/. Inside this directory I created a directory to hold the gritter objects. I ended up with the following directory entries:


The next thing to do is to include these scripts into your application. I wanted to see if I could completely replace the standard way APEX handles SUCCESS and FAILURE messages, so I want these scripts to be available on every page. There are two ways I could do this: I could create an After Header region on Page Zero that loads the scripts, or I could edit the page template and insert the script calls there.

To make things as quick and easy as possible to load and troubleshoot, I chose to create a Page Zero region as follows:

Region Type: HTML Text
Template Type: No Template
Display Point: After Header

and include the following code:

<link href="/c/gritter/css/jquery.gritter.css" type="text/css" rel="stylesheet" />
<script src="/c/gritter/js/jquery.gritter.min.js" type="text/javascript"></script>
After loading the scripts and doing a few tests, I found out a few things...

  1. You can use JavaScript in the Success and Failure message of any validation or process and it will be executed. News to me and something I'll file away for later use!
  2. This isn't scalable as you'd have to change every message within your application to a JavaScript call.
  3. Because of the way JavaScript deals with nested quotes within strings, life gets extremely interesting when the message you're trying to relay to the end user contains either single or double quotes.
To make this work at the application level without forcing the developer to use JavaScript for every message we need to go a step higher and look at the templates. If you're unfamiliar with APEX templates you may not know that within a page template there are two sub-templates for the Success and Notification (failure) messages. By editing these areas within your page template you can move the handling of the JavaScript up so that the developers don't have to worry about it. They can treat the success and failure messages as they always have.

To alter the template, navigate to the shared components for the application, click on Templates and edit the page template that you’re using throughout your application. In most cases there will probably only be one template that you’re using, but for more complex applications there may be 2 or 3 you need to edit. You really only need to edit the templates that are used on pages you want to use the growl notification. In my case, there was just one.

Once you edit the template, you’ll need to scroll down to the Subtemplate region. This is where the Success Message and and the Notification (Fail) message templates are defined.

In the Picture below you’ll see the code in both regions that replaced the original code included in the template.


In both cases, the first thing the code does is create a DIV, giving it an ID that we can grab ahold of later and sets its CSS style to “display:non”. This will keep the DIV from displaying until the Gritter script styles it. The contents of the DIV is the appropriate message template replacement variable, #SUCCESS_MESSAGE# and #MESSAGE#.

The next bit of code is a call to a piece of JavaScript code that we’ll talk about in just a moment. The first call, to growlSuccess takes two parameters. First is the ID for the DIV so the script can get a handle on it, and the second is the duration for how long the notification should be displayed. In this case, 5000 is about 5 seconds. The second call, to growlSticky only takes one parameter, the ID of the DIV. This function creates a “sticky” notification that the user will need to dismiss. The reason I created this one is because you want to make sure the end user sees and acknowledges the any error message.

The last piece of the puzzle is the javascript that kicks off the Gritter script. Again, I chose to implement this on Page Zero.

Region Name: GRITTER - JavaScript
Region Type: HTML Text
Template Type: No Template
Display Point: After Header

And the code in this region is as follows.

<script type="text/javascript">

function growlSuccess(vRegion, vLength){
// Get the message out of the DIV created by the page template
var vMessage = document.getElementById(vRegion).innerHTML;
// Instantiate the gritter message.
// (string | mandatory) the heading of the notification
title: 'SUCCESS',
// (string | mandatory) the text inside the notification
text: vMessage,
// (bool | optional) if you want it to fade out on its own or just sit there
sticky: false,
// (int | optional) the time you want it to be alive for before fading out
time: vLength
return false;

function growlSticky(vRegion){
// Get the message out of the DIV created by the page template
var vMessage = document.getElementById(vRegion).innerHTML;
// Instantiate the gritter message.
// (string | mandatory) the heading of the notification
title: 'MESSAGE',
// (string | mandatory) the text inside the notification
text: vMessage,
// (bool | optional) if you want it to fade out on its own or just sit there
sticky: true,
// An image to place inside the gritter notification
return false;


This is the definition of the two functions that we called in the template code. The comments in the code should document what it’s doing fairly well. But the main thing to understand are is the call to gritter.add. This is the “magic” code that creates the Gritter “floating message”.

Referencing the Gritter documentation, you’ll see that there are quite a number of options that I’m not using. I wanted to keep things fairly simple just to make sure I wasn’t fighting against complexity in the early stages. I did go an extra step and put an image inside the sticky message type that is used for Notifications, to differentiate it from the Success Message.

Here’s the end result...


Hopefully this not only answers the question, “Is it possible”, but also shows you that there is way more to APEX than meets the eye. You can use JavaScript in a number of places that you wouldn’t expect. I’m continually pleasantly surprised at the flexibility of APEX.

EDIT (6/24/11) - Patrick Wolfe, completely independently, has created a Dynamic Action plugin that does much the same thing (see the demo here). The reason I went down this path is because the DA Plugin isn’t easily implemented for the APEX Success and Failure message. Anyway. Interesting that two people solved a strikingly similar problem and came up with much the same solution!

22 June, 2011

It's been quiet... Too Quiet!

You have probably noticed that this blog has been very quite for the last few months... Well, there is a reason for that.

Apart from the books that I've been involved in writing, we at Sumneva been working feverishly to put the finishing touches on our first product, sumnevaSERT. And today, we release it into the wild.

And with all of scary security breaches that have happened recently, the release couldn't have come at a better time.

For those of you who aren't familiar, sumnevaSERT is a simple yet powerful tool that outlines potential security risks in any Oracle APEX application and provides recommendations on how to mitigate them. You can the Sumneva news post about it here, and get more information about it here. Or

You can also come and see us at ODTUG KScope11. We'll have a booth in the exhibition hall and will be giving a vendor presentation on securing your APEX applications.

Now that the release is out in the wild, hopefully I'll have a bit more time to finish some half completed blog posts and get back out into the world a bit more.

But keep an eye out, because sumnevaSERT is just the beginning. We plan to continue to support our mission to make developing secure and performant APEX applications even easier.

Watch this space!

10 June, 2011

Oracle Author Podcast.

I recently had the pleasure of co-authoring the APress book, Beginning Oracle Application Express 4. It was both a trying and rewarding experience, but I'm glad I did it.

A couple weeks ago I also participated in creating a Podcast about the book. 

Here's some information about it...

A conversation with Patrick Cimolini, Martin D'Souza, and Doug Gault; Authors of Beginning Oracle Application Express 4.  David Peake, Principal Product Manager for APEX, chats with some of the authors of the book. They will discuss various aspects about the book including the main reason for the book, who the book is focused towards, and some behind the scenes information about it's writing.