WHAT THE FUCK IS AJAX AND APEX

Here is a post about a simple AJAX example in Oracle Application Express aka APEX.

Folks speak about their preferred frameworks virtues (yes on APEX side there are some fans, especially in Germany and The Netherlands), sometimes without knowing howto do the same in other frameworks. As an example, in APEX world, i stopped my attention on an article called APEX + Javascript = Ajax (what a surprise) : all is said in the two comments (the second one being mine)

So let’s begin with a very simple example i should implement on an APEX application i worked on recently. This article’s goal will give you a concrete example, and i will finish by a conclusion about integrating Ajax in APEX applications, and compare to a framework i love > Ruby on Rails.

The example :

Imagine a page divided horizontally in two regions :

- The left region contains a list with items.

- The right region contains a form.

The goal is : by selecting one item in the list om the left side, a XMLHttpRequest is done against the server to retrieve some data to load in the form on the right side. The Form contains text fields and combo boxes.

Some explanations about how to proceed with AJAX:

The use case is quite simple :
- When choosing an item of the list (left region), an ‘onchange’ event triggers and we do call a Javascript function, passing the item ID as argument. In this Javascript function we instantiate an XMLHttpRequest object (with right args as URL and parameters) then do the ’send’ to a function on server side (let’s say a controller’s function in RoR or OnDemand PL/SQL procedure with APEX). The Javascript fonction contains the code for the callback, ie a routine to process the received envelope from the server; the response is generally XML, but depending on the needs on client side, we could send back JSON (Javascript Object Notation) , HTML or simple texte.

In our case we’ll use XML : the callback function should parse the XML document, and extract data to load inside the HTML form (in the right region). Accessing form objects will be done in Javascript by DOM scripting (Document Object Model of our HTML page).

Here are the portions of code. First the PL/SQL code used to display the list on my left regions. List items come from a SQL query, then i just use PL/SQL web toolkit to write the HTML :


declare


TYPE ActivCurTyp IS REF CURSOR;
TYPE NumList IS TABLE OF NUMBER;
TYPE DescList IS TABLE OF VARCHAR2(1000);
activ_cv ActivCurTyp;
ids NumList;
descs DescList;

begin
– ACTIVITES
OPEN activ_cv FOR ‘SELECT s_activ, l_desc_court FROM env.activite where s_activ in (’||:ACTIVITES_TEMP||’)';
FETCH activ_cv BULK COLLECT INTO ids, descs;
CLOSE activ_cv;

htp.p('<SELECT NAME="toppings" SIZE=5
onchange=”get_activite(this.value)”>’);
FOR z IN 1..ids.count LOOP


htp.p(’<OPTION VALUE=”‘|| ids(z) ||’”>’||
descs(z)||’</OPTION>’);
END LOOP;
htp.p(’</SELECT>’);

Here is the source code of the Javascript function triggered on the ‘onchange’ event of the list :

function get_activite(pValue){
var get = new htmldb_Get(null,html_GetElement(’pFlowId’).value,
‘APPLICATION_PROCESS=getActivite’,0);
if(pValue){
get.add(’TEMPORARY_APPLICATION_ITEM’,pValue)
}else{
get.add(’TEMPORARY_APPLICATION_ITEM’,'null’)
}
gReturn = get.get(’XML’);
if(gReturn){
var l_Count = gReturn.getElementsByTagName(”item”).length;
for(var i = 0;i<l_Count;i++){
var l_Opt_Xml = gReturn.getElementsByTagName(”item”)[i];
var l_ID = l_Opt_Xml.getAttribute(’id’);
var l_El = html_GetElement(l_ID);
if(l_Opt_Xml.firstChild){
var l_Value = l_Opt_Xml.firstChild.nodeValue;
}else{
var l_Value = ”;
}

if(l_El){

if(l_El.tagName == 'INPUT' || l_El.tagName == 'TEXTAREA'){
setValue(l_ID, l_Value);
} else if(l_El.tagName == ‘SELECT’) {
html_SetSelectValue(l_ID,l_Value);
}
else{
l_El.innerHTML = l_Value;
}
}
}
}
get = null;
}

On server side here is the process On Demand, coded in PL/SQL :

DECLARE
v_s_activ NUMBER;
v_z_mnemo VARCHAR2 (10);
v_l_desc_court VARCHAR2 (1000);
v_l_desc_long VARCHAR2 (2048);
v_c_depart VARCHAR2 (4);
v_c_metier VARCHAR2 (4);
v_c_grou_activ VARCHAR2 (4);
v_s_util NUMBER;
v_c_processus VARCHAR2 (10);

CURSOR cur_c
IS
SELECT
s_activ,
z_mnemo,
l_desc_court,
l_desc_long,
c_depart,
c_metier,
c_grou_activ,
s_util,
c_processus
FROM env.activite
WHERE s_activ = TO_NUMBER (v (’TEMPORARY_APPLICATION_ITEM’));
BEGIN
FOR c IN cur_c
LOOP
v_s_activ := c.s_activ;
v_z_mnemo := c.z_mnemo;
v_l_desc_court := c.l_desc_court;
v_l_desc_long := c.l_desc_long;
v_c_depart := c.c_depart;
v_c_metier := c.c_metier;
v_c_grou_activ := c.c_grou_activ;
v_s_util := c.s_util;
v_c_processus := c.c_processus;
END LOOP;


OWA_UTIL.mime_header (’text/xml’, FALSE);
HTP.p (’Cache-Control: no-cache’);
HTP.p (’Pragma: no-cache’);
OWA_UTIL.http_header_close;
HTP.prn (’<body>’);
HTP.prn (’<desc>this xml genericly sets multiple items</desc>’);
HTP.prn (’<item id=”P9_S_ACTIV”>’ || v_s_activ || ‘</item>’);
HTP.prn (’<item id=”P9_Z_MNEMO”>’ || v_z_mnemo || ‘</item>’);
HTP.prn (’<item id=”P9_L_DESC_COURT”>’ || v_l_desc_court ||
‘</item>’);
HTP.prn (’<item id=”P9_L_DESC_LONG”>’ || v_l_desc_long || ‘</item>’);
HTP.prn (’<item id=”P9_C_DEPART”>’ || v_c_depart || ‘</item>’);
HTP.prn (’<item id=”P9_C_METIER”>’ || v_c_metier || ‘</item>’);
HTP.prn (’<item id=”P9_C_GROU_ACTIV”>’ || v_c_grou_activ ||
‘</item>’);
HTP.prn (’<item id=”P9_S_UTIL”>’ || v_s_util || ‘</item>’);
HTP.prn (’<item id=”P9_C_PROCESSUS”>’ || v_c_processus || ‘</item>’);
HTP.prn (’</body>’);
EXCEPTION
WHEN OTHERS
THEN
OWA_UTIL.mime_header (’text/xml’, FALSE);
HTP.p (’Cache-Control: no-cache’);
HTP.p (’Pragma: no-cache’);
OWA_UTIL.http_header_close;
HTP.prn (’<body>’);
HTP.prn (’<desc>this xml genericly sets multiple items</desc>’);
HTP.prn (’<item id=”P9_ERRM”>’ || SQLERRM || ‘</item>’);
HTP.prn (’</body>’);
END;

In a next article , i will write the equivalent code pour Ruby on Rails, and you’ll see how short it is.

Conclusion :

What do we see in this example?

A lot of code to write the simplest Ajax functionnality for a database-backed web application. For people writing Web 2.0 apps with RoR, it can be surprising :
- On server side, we see we do not have any help with kind of ORM (but PL/SQL is a procedural language): in fact the PL/SQL code is stored in the database, so no need of a new layer, let’s code directly our SQL query.

For the XML response , no helpers like in RoR, to serialize an object to XML..everything should be written from scratch (souvenirs souvenirs)

- On client side, although Apex gives some facilities with Javascript for the XMLHttpRequest call and DOM scripting, we’re far from Prototype and Scriptaculous frameworks included in RoR. The main difference with Ajax stuff in RoR : here we used XML , so on client side let’s say we have a kind of overrhead as parsing XML, extracting data, DOM scripting. In RoR, with RJS, the technics is the Javascript Remote scripting (as known at the beginning of years 2000) : on server side we flush some Javascript on the response, including the HTML code of the new Web Clip to display in the page (ie. innerHTML). RoR folks had a pragmatic approach, to provide finally the same effect (and better if we consider advanced effects inside scriptaculous)

AJAX in APEX is possible but costs a lot , and we lose significantly in productivity.

APEX and RoR are not ’silver bullets’ : each framework is good in certain domains and not others .

Even if it’s possible with RoR, working on legacy databases is quite heavy, whereas easier with APEX.

APEX can beat RoR to display simple forms and reports : the web based IDE of Apex, includes Wizards helping you to create your page in a ‘push button’ manner. But sounds like scaffold in RoR? Yes and no.

The scaffold is a starter app implementing a complete CRUD, that should be reworked before production. In APEX you do the same through wizards, but the page could be revamped with predefined templates and ready for production.

in RoR, you are free then to rework on the scaffold, depending on your skills.

In APEX, everything you need to do that doesn’t exist in the Wizard needs PL/SQL and Javascript hack , and it can become a nightmare, because when coding a component to integrate in your APEX application, don’t forget to test its integration with APEX : you could be surprised of the encountered side effects (for your info, the example in this page, gave me many problems: when using this Ajax call that fills the form, then i couldn’t submit to create the record in database. After one day of investigation, i will break it completely and return to a classic Web 1.0 method…great no?)

So for the future, i will forget Ajax in my APEX applications (if i should continue to work with APEX), and continue to use RoR for Web 2.0.

Finally , you could ask : But, who does use APEX? I would say first: the people having experience with PL/SQL and who never wanted to learn any other language like Java, PHP, .NET or Ruby. Even in the Web stuff , APEX is well adapted for people having experience with Client Server applications and who want access smoothly to web applications without the skills. APEX is a kind of framework that could not really be extended (as Struts or RoR) : so well adapted for people wanting to have a framework off the shelf that couold be used as is. Finally, having an Oracle culture helps for APEX.

When working with APEX, you should embrace the philosophy behind : doing a lot of stuff via Wizards, who loves it? Me, not really. Even if i see powerful features inside APEX, i do not consider we really develop with APEX: most of time we push buttons with our mouse.

As a general manner, i do not like develop an application only with Wizards. We all know that Wizards generate code (sometimes a lot): then when everything works it’s marvellous, but the day there are problems, don’t be there! Generated source code, and generated XML configuration files are painful to debug and maintain.
Nota: an API exists in APEX , and you’re free to use it if you want write your components from scratch.

14 Responses to “WHAT THE FUCK IS AJAX AND APEX”

  1. Denes Kubicek Says:

    Laurent,

    The title of my blog was a pun. I thought it is a funny word game. I didn’t even want to reply to the comments from Venkat.

    In my opinion you are taking it to seriously. Usually, the comments like yours result out of a lack of understanding - you even describe ApEx as a lot of “push buttons”. I respect the fact that you prefer RoR. That is O.K. The only thing I have a problem with is your choice for the title of this blog posting. Such comments are typical for humorless people.

    Denes Kubicek

  2. Dimitri Gielis Says:

    Hi Laurent,

    Nice article, although I don’t agree ;-)

    As you say, there exists an API, so if you prefer you can use the API and not use the wizards… APEX is declarative, so very easy to make screens and use buildin features, but if it doesn’t exists you can integrate/develop it yourself. We already did some heavy testing with for ex. the integration of the Yahoo and Google web 2.0 frameworks.

    Nevertheless my biggest complaint about your article is this sentence: “So for the future, i will forget Ajax in my APEX applications (if i should continue to work with APEX), and continue to use RoR for Web 2.0.”

    This is so untrue… you should have a look at APEX 3.1 and APEX 4.0… especially APEX 4.0 will be full of AJAX.
    Have a look here: http://dgielis.blogspot.com/2007/06/sneak-preview-oracle-application.html
    or http://carlback.blogspot.com/2007/09/apex-40-preview_14.html

    Nevertheless, I respect your choice for RoR, but don’t say APEX is not web 2.0 ;-)

    Thanks,
    Dimitri

  3. lbois Says:

    I had some conversation with you (Denis) yesterday evening, here was my first answer :

    Recently, on my last project, somebody did a proposition about using ApEx , and leave RoR (whereas a complete webtop has been built during more than 4 months with RoR :-( …a webtop, imagine a web application fully ajaxified ..Think of YouOS). They thought ApEX would be the silver bullet. But no, there is not silver bullet…even RoR is not the silver bullet.
    ApeX is good, in certain domains,as RoR is good, in a certain context. I know there are quite middle complex applications done with ApEX , but the main goal to change of technology : the productivity first.
    Working with predefined templates or components in ApEX is great: it could beat RoR, i think…but when you should integrate some of your code to build components not in the predefined ones from ApEX, it significally decrease in productivity, and finally what is the gain near RoR? No gain.

    Recently i should add some Ajax stuff, very simple ( see example in the blog ) : load data in a formular…and yes, when you come from RoR, it’s really chocking you know… ;) really poor integration of Ajax in APEX, and lots of things should be written in several lines of code, whereas you do it simply in one line in RoR.
    I encountered some problems like posting my form after an Ajax update of my form..i tried to understand..then two choices came to me :
    - break the code and redo the screen classically in web 1.
    - do it as a fully Active Form (asynchronous submit against On Demand process)..it is what i chose.
    But i lost one day.

    My article is about this, and is not named : ApEX is a big s… ..no, it’s not what i think..but Ajax in ApeX is quite shitty, and yes it’s what i think.

    Now i suggere you to check RoR and play with it, try Ajax & RJS in your sample, and compare.

    I explained in my article that in RoR (especially Prototype+scriptaculous fmks) the technics is not the same, more pragmatic, and you have many Ruby helpers ..you can do lots of great effects without a line of Javascript in RoR.
    See Google Web Toolkit too, with Java…many things can be done with Java : great when you’re not a Javascript expert.
    It would be nice to be able to do the same in ApEx, really…

  4. Carl Backstrom Says:

    There is nothing stopping from using any 3rd party javascript library you want in an Application Express, I’ve used dojo, prototype and especially jQuery with great success in Application Express

    Also they way you’ve written your particular piece of code if sort of deceptive. As the most of it can be reused. You actually only have 4 lines of custom javascript.

  5. Louis-Guillaume Carrier Says:

    Your comments on APEX make me beleive that you are not really used to the Framework. If you know well APEX and javascript, there’s no problem using AJAX. For me, the only down site to APEX is the ’search engine optimization’ that is absent.

    Take time, and you’ll master APEX. Like everything else, if you don’t put a minimum of time, you won’t be fast at coding.

  6. lbois Says:

    Dimitri,
    I’m like St Thomas : wait and see APEX 4.0..
    I do not say APEX is not Web 2.0 : clearly web 2.0 is not only the technology Ajax , but includes all the functionnalities you provide in a web app to help your users to be more actors than consumers when surfing the web (collaborative approach, social networking & bookmarking are some examples). And yes, it should be possible to build web 2.0 applications with APEX of course…but i just say i won’t use this tool for this, but will use RoR or Java.
    Give me some URLs of public Web 2.0 applications done with APEX, i’m very interested.
    I give you a list of applications done with RoR : http://happycodr.com/

  7. lbois Says:

    Louis Guillaume : i know we could integrate third party libraries, and i began to do this (to simplify my Javascript)
    It was not really my choice to use APEX on my project : it has been sold as a RoR ‘killer’, on a ‘productivity’ point of view … I jumped to Apex quite easily thanks to a previous experience with its ancestor.
    That is not my opinion : as i said to Denis, neither Apex or RoR is a silver bullet. Apex has some gains comparing to RoR, that could lost once you need to do more complex functions (it’s my case in my current work with Apex)

    I totally agree with you when you say you become productive after some time, to be totally operationnal…i try to explain it to people having changed our first techno (RoR) for another (Apex)

  8. lbois Says:

    Carl,

    Yes, i know we could integrate third party libraries, and i began to do this (to simplify my Javascript).

    4 lines of Javascript ok…but less lines of Javascript with RoR for this simple tip: i could do it with RJS without a line of js and only one line of Ruby : the main advantage of RJS is that you have Ruby helpers over Prototype/Scriptaculous.

    I would pleased if you could compare Ajax in Apex with Ajax in RoR on your side…then you should understand my point of view.

  9. Carl Backstrom Says:

    Deceptive might be the wrong word, I apologize. But you didn’t rewrite the code in the most efficient and reusable manner, and the line breaks make it look bigger than it is.

    What you did is use someone’s example based on my original example http://apex.oracle.com/pls/otn/f?p=11933:88 At least mine was meant to be generic it was more a basic HowTo for people that don’t have much experience with AJAX + APEX, I don’t include you in on this as you bring up some valid points and are things we are specifically working on, I’ll mention a bit more on that later.

    Now for the meat of the issue.

    The XML can be generated using Oracle’s XML functions which saves a ton of code in the OnDemand Process, it can get that code down to 2 or 3 lines. I didn’t do this in my example to help simplify it.

    The javascript can be rewritten into two functions. One that is specific to what you are doing and one that can generically set items in a page. Take a look at this http://forums.oracle.com/forums/thread.jspa?messageID=2162717.

    I would like to see the corresponding RoR code, which you mentioned you put up, plus you have to remember all the page and application code you need to write in RoR that you don’t have to in Application Express.

    Prototype is very nice, I’ve used it in a couple APEX applications. The shows another thing we try take into account with our javascript library. There are a many third party libraries out there jQuery , dojo, ext and on and on and we want to make sure that they can be used easily with APEX. In fact anything we can do to make it easier , like namespacing our javascript (well most of it) we are moving torwards.

    Finally like I mentioned before we have been working on new functionalities in next APEX version to help greatly with this. There will be a generic way to set item values in a page, all item types. And new JSON functionality to return standardized and not standardized JSON from APEX which will makes this much easier.

    I just wrote this example in our dev box and it was three lines of PL/SQL (code be bigger depending on how many items your setting) and three lines of javascript.

    At the end of the day, postings like yours keeps us on our toes and help us improve the product, so keep it up :)

  10. Patrick Says:

    “In a next article , i will write the equivalent code pour Ruby on Rails, and you’ll see how short it is.”

    When are you going to write this article? Just curios how that looks like in RoR.

    Patrick

  11. psalmu Says:

    Just wondering: before writing that PL/SQL code (and commenting “On server side, we see we do not have any help”), did you look at the built-in DBMS_XML* packages, e.g. DBMS_XMLGEN…? Which db version are you using?

  12. lbois Says:

    Sure the code RoR will be published soon…still working on ApeX

  13. lbois Says:

    For DBMS_XML* packages, e.g. DBMS_XMLGEN… i’m sorry for the “On server side, we see we do not have any help” … By Server side, i’m so used to three tiers applications than i thought of app server.
    Of course, for ApEx as everything is in the database (except resources like css files, pictures, …), we should consider database capabilities, and especially with Oracle 10g.

  14. What the fuck… with APEX, Part 2. « Laurent’s Weblog Says:

    [...] I’d like to insist for people who were first (very) surprised by the title of my first article , the problem is not the product APEX in general : i think many features are nice in APEX and in [...]

Leave a Reply