Friday, 25 March 2011

Struts2 - Jquery AJAX tutorial3

The AJAX with JSON example required more if not much to understand.
Let's begin from the easiest point.

The div named "result" is targeted by the AJAX call to put the
output. It is located in the body part of the AjaxTest6.JSP .
...

<div id="result" class="result ui-widget-content ui-corner-all">Click on the link below.</div>
...



The AJAX call is located in the body part of the AjaxTest6.jsp .
...
<sj:a id="ajaxjsonlink"
href="%{jsonurl}"
dataType="json"
onSuccessTopics="handleJsonResult"
indicator="indicator"
button="true"
buttonIcon="ui-icon-gear"
>
Run AJAX Action with JSON Rsult
</sj:a>
...

It uses the jsonurl which is set to
...
<s:url id="jsonurl" action="jsonlanguages"/>
...
So the action trigged by the AJAX call lies at the struts.xml with the label "jsonlanguages":

...
<action name="jsonlanguages" class="ARS.Jsonlanguages" method="execute">
<result type="json"><param name="root">languages</param></result>

</action>
...

The struts entry fro jsonlanguages at the struts.xml points to the class address as
jsonlanguages.java at the ARS library. IMPORTANT: It also gives a hint about how the result should be returned. The result should be based on the parameter "languages" not the default result definition. I will further elaborate on this below.

jsonlanguages.java uses a static string array of:
...
private static String[] staticLanguages =
{
"Actionscript (Flash)",
"ABAP Objects",
"Ada",
"Aleph",
"AppleScript",
"Beta",
"BlitzMax",
//...
"Zonnon"
};

and later on it copies this string into languages array:
in the execute method (the method that works as action default).
...
private String[] languages = Jsonlanguages.staticLanguages;

public String execute() throws Exception
{
ArrayList<String> tmp = new ArrayList<String>();
for (int i = 0; i < staticLanguages.length; i++)
{
tmp.add(staticLanguages[i]);
}
languages = tmp.toArray(new String[ tmp.size()]);

return SUCCESS;
}
...

The execute method returns SUCCESS. The difficulty is: By default, the jsonlanguages action returns the staticLanguages if we say:
...
<action name="jsonlanguages" class="ARS.Jsonlanguages" method="execute">
<result type="json"/>

</action>
...

In order to return the languages we must indicate it as base to the parameter:
...
<action name="jsonlanguages" class="ARS.Jsonlanguages" method="execute">
<result type="json"><param name="root">languages</param></result>

</action>
...


This is done somewhat different by Herr GEPPERT as he has chosen to do things in the
convention fashion globally.

Here is the full working code.

AjaxTest6.jsp
-------------
<%--
Document : testAJAX
Created on : 15.Mar.2011, 20:08:02
Author : Ali Riza SARAL
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib prefix="s" uri="/struts-tags"%>
<%@ taglib prefix="sj" uri="/struts-jquery-tags"%>
<html>
<head>
<sj:head/>
<script>
$.subscribe('handleJsonResult', function(event,data) {
$('#result').html("<ul id='languagesList'></ul>");
var list = $('#languagesList');
$.each(event.originalEvent.data, function(index, value) {
list.append('<li>'+value+'</li>\n');
});
});
</script>
</head>
<body>

<div id="result" class="result ui-widget-content ui-corner-all">Click on the link below.</div>
<s:url id="jsonurl" action="jsonlanguages"/>

<sj:a id="ajaxjsonlink"
href="%{jsonurl}"
dataType="json"
onSuccessTopics="handleJsonResult"
indicator="indicator"
button="true"
buttonIcon="ui-icon-gear"
>
Run AJAX Action with JSON Rsult
</sj:a>
<img id="indicator" src="./images/indicator.gif" alt="Loading..." style="display:none"/>
</body>
</html>

struts.xml
-----------
...
<action name="jsonlanguages" class="ARS.Jsonlanguages" method="execute">
<result type="json"><param name="root">languages</param></result>

</action>
...


jsonlanguages.java
------------------
package ARS;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import com.opensymphony.xwork2.ActionSupport;

public class Jsonlanguages extends ActionSupport {

private static final long serialVersionUID = -3066791113091431706L;
private static String[] staticLanguages =
{
"Actionscript (Flash)",
"ABAP Objects",
"Ada",
"Aleph",
"AppleScript",
"Beta",
"BlitzMax",
// ...
// "XOTcl",
// ...
"Zonnon"
};
private String[] languages = Jsonlanguages.staticLanguages;

public String execute() throws Exception
{
ArrayList<String> tmp = new ArrayList<String>();
for (int i = 0; i < staticLanguages.length; i++)
{
tmp.add(staticLanguages[i]);
}
languages = tmp.toArray(new String[ tmp.size()]);

return SUCCESS;
}

public String[] getLanguages()
{
return languages;
}
}

The AJAX call trigs "handleJsonResult" via:
...
onSuccessTopics="handleJsonResult"
...

HandleJsonResult simply buids up a list;
first creates the ist named "languagesList" and then
adds each value in the "event.originalEvent.data" using the
each iterator.

$.subscribe('handleJsonResult', function(event,data) {
$('#result').html("<ul id='languagesList'></ul>");
var list = $('#languagesList');
$.each(event.originalEvent.data, function(index, value) {
list.append('<li>'+value+'</li>\n');
});
});
</script>

This list is placed into the "targets" area of tha AJAX call, namely the div named "result".

Kind regards. Enjoy!

Ali R+