Over the last few years, the use of AJAX has exploded across the internet. Incorporating AJAX into web pages gives them a dynamic element that many users prefer. In the eCommerce industry, AJAX has made its way into many key areas of the web applications. There are costs to weigh when considering AJAX in an ATG application.

Pros:

  • A sleeker user experience – no waiting for full page reloads
  • Take load off of the application server – load the full page once, and only use ajax to reload what is needed

Cons:

  • You need to be an expert to mesh ATG and AJAX
  • Breakdown of the M-V-C design pattern
  • Much more work to support users that don’t use javascript
  • Longer implementation times due to writing more complicated code

In the following sections, the pros and cons of using AJAX in ATG applications will be weighed, along with some common problems, solutions and best practices.

Base Knowledge

To get started in implementing ajax in ATG applications, it’s important to realize that ajax isn’t some baseline skill. Learning how to implement ajax successfully into ATG applications requires a pyramid of knowledge:

Each layer in the pyramid builds on another. Many people underestimate the prerequisites before diving straight into an AJAX implementation. It’s important to have a firm grasp on all concepts in the pyramid.

AJAX can be done without jQuery, but why reinvent the wheel? jQuery is the standard in ATG applications these days.

Meshing ATG & AJAX

Many people fall into the traditional rut of using javascript as a shim for adding little bits of dymaic functionality. They insert inline scripts everywhere. Unfortunately, these behaviors carry over into AJAX implementations, which results in really bad code.

It’s very important to ensure javascript design principles are upheld, otherwise AJAX combined with ATG will make things a nightmare.

Loading sections of a document using AJAX

In the simplest example, AJAX can be used to dynamically load a section of a document. Often times, you’ll want to reload a div based on some kind of javascript event firing. Dynamic content rendering via AJAX may also be part of your CDN strategy. This isn’t anything ATG-specific, but is included for completeness.

The traditional way to do this is:

$.ajax({

url: ‘/foo/bar.jsp’,

success: function(data) {

$(‘#foo’).html(data);

}

});

By knowing a little deeper jQuery, the above simplifies down to:

$(‘#foo’).load(‘/foo/bar.jsp’);

It’s really as simple as that.

Querying Information

Stepping it up, what if you want to AJAX load some specific data from ATG, and not just a jsp? One way I prefer is to write a jsp that queries the backend and returns a json response:

1. Write the JSP

There’s a wonderful json tag library that generates json objects using jsp tags. It can be downloaded here.  A very simple jsp might look like:

<dsp:page>

<dsp:importbean bean=”/atg/userprofiling/Profile”/>

<json:object>

<json:property name=”firstName”><dsp:valueof bean=”Profile.firstName”/></json:property>

<json:property name=”lastName”><dsp:valueof bean=”Profile.lastName”/></json:property>

<json:property name=”registrationDate”><dsp:valueof bean=”Profile.registrationDate”/></json:property>

</json:object>

</dsp:page>

2. Call the JSP

To call this, use the long-hand AJAX function call, being sure to set dataType=json:

$.ajax({

url: ‘/foo/profileInfo.jsp’,

dataType: ‘json’,

success: function(data) {

var firstName = data.firstName;

var lastName = data.lastName;

var regDate = data.registrationDate;

// do stuff with data…

}

});

Using this method, you can effortlessly pull data from the backend for your frontend needs.

Form Submissions

Form submissions are the tricky part with ATG to do over AJAX. If you want to submit a form using jQuery, simply use:

$(‘#submit-btn’).click(); // a click-by-proxy

and look no further. If, however, you need to submit a form and keep the entire page from reloading, more steps need to be taken. First, a clean way to exchange data with the FormHandler must be established, followed by invoking the handleXXX method and finally juggling the response without triggering a page reload.

1. Exchanging data with the FormHandler

In non-ajax ATG, when a form is submitted, you get an HTML response back from ATG corresponding to an error or success page. When pulling AJAX into the picture, an html response isn’t going to (easily) help the calling JavaScript know the status of the form submission. Instead, returning a json response is the preferred method for communication. The seamless support provided by jQuery makes it an obvious winner.

To return json, one way to structure your form handler is like this:

public boolean handleSampleFormSubmit(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {

JSONObject responseObj = new JSONObject();

JSONArray errors = new JSONArray();

//

// do stuff

//

// errors.put(“Example error 1”); –> use this for adding errors

responseObj.put(“errors”, errors);

responseObj.put(“status”, errors.isEmpty() ? “success” : “error”);

pResponse.getWriter().write(responseObj.toString());

pResponse.flushBuffer();

return false;

}

Notes:

  • We use the JSON library provided by ATG to cleanly create the json response.
  • Instead of using addFormException(), we create an array of errors to display to the user. Sometimes if I am retrofitting old code, I’ll keep the addFormException calls, and loop through the getFormExceptions() values at the end of the method, adding each one into the json array.
  • You must return false to prevent the page reload.

2. Submitting the form via ajax

With the FormHandler method created, you can now add it to the jsp:

<dsp:form id=”sample-form”>

<%– Your other form fields here –%>

<dsp:input type=”hidden” bean=”/atg/userprofiling/ProfileFormHandler.sampleFormSubmit” value=”true”/>

<dsp:input type=”submit” id=”submit-sample” bean=”/atg/userprofiling/ProfileFormHandler.sampleFormSubmit” value=”Submit!”/>

</dsp:form>

Then call it using:

$(‘#submit-sample’).click(function(e){

e.preventDefault();

$.ajax({

type: ‘post’,

url: ‘/foo/bar.jsp’,

dataType: ‘json’,

data: $(‘#sample-form’).serialize(),

success: function(data) {

// see below

}

});

});

Notes:

  • Basic idea is to listen in on the submit button click and intercept the form submission before the browser’s default behavior can take over.
  • The URL is irrelevant because the form handler takes over before that page is even loaded.
  • This is not the only way to submit a form to ATG via AJAX, just my suggestion.

After a lot of fidgeting on my part, I’ve come to the conclusion that adding a hidden form field pointing to the handleXXX method is the easiest way to get the handleXXX method to invoke and take over form submission. When submitting via AJAX, the bean reference attached to the submit field does not matter. You have to add the hidden attribute to get the handleXXX method invoked. Maybe someone reading this can comment if this is a defect on Oracle’s part, or intended behavior, or another workaround.

3. Handling the response

The only thing left is to parse the response and determine how to handle it. Because we specified the dataType=json in the AJAX form call, the data we get in the success function is already parsed as json. Also, because we used a standard json library, the parsing is never going to fail (don’t try to hard-wire your json responses without using a library). Within the success function, we can use something like this to pick apart the response:

if(data.status == ‘success’) {

// do something

} else if(data.status == ‘error’ && data.errors.length) {

var errorStr =””;

for(var i=0; i<data.errors.length; i++) {

errorStr +='<span class=”error”>’+ data.errors

[i]+'</span><br/>’;

}

errorStr ='<div class=”errors”>’+ errorStr +'</div>’;

// displays errors above the form

$(‘#sample-form’).before(errorStr);

}

Note:

  • This is one way to handle errors, but there are certainly more options.

Conclusion

I’ve shown a few ways to implement AJAX into ATG applications. There are certainly more ways to do most of the things I’ve mentioned. Before making the jump, I’d recommend having an expert in JavaScript, AJAX and ATG look things over. When AJAX is heavily implemented without an underpinning organization, there tends to be a loss of design patterns. AJAX can really make a frontend unmanageable if done haphazardly.