|
Using a tag file to produce JavaScript code
The MonitorPage.jsp file, which was presented in the first section of this article, uses the <js:rpc> tag (see Listing 15) to generate the JavaScript routines that call the server-side functions.
Listing 15. Using <js:rpc> in MonitorPage.jsp
<js:rpc function="getInfo()" script="MonitorScript.jss"
method="GET" async="true" jsonVar="json">
showInfo(json, "info");
</js:rpc>
<js:rpc function="allocMem(size, seconds)" script="MonitorScript.jss"
validator="valid('Size', size) && valid('Seconds', seconds)"
method="POST" async="true"/>
<js:rpc function="gc()" script="MonitorScript.jss"
method="POST" async="false">
alert("Garbage Collected");
</js:rpc>
Listing 16 contains the rpc.tag file, which implements the custom tag. The tag file declares its attributes and the used JSP libraries, invokes the authorize.tag file with <js:authorize>, sets two JSP variables named xhrVar and paramList, and generates the client-side JavaScript function with the given name and parameters.
The xhrVar variable is used on the server side to maintain the name of a JavaScript variable that is used throughout the generated JavaScript code, which will be executed in the Web browser. The value of the xhrVar variable is composed of the function's name and the XHR string. For example, if function is getInfo(), the value of the JSP variable (and the name of the JavaScript variable) will be getInfoXHR.
The other JSP variable named paramList will keep the list of parameters that are provided through the function attribute between ( and ). For example, if function is allocMem(size, seconds), the paramList variable will store the size, seconds list.
Listing 16. The rpc.tag file
<%@ attribute name="function" required="true" rtexprvalue="true" %>
<%@ attribute name="script" required="true" rtexprvalue="true" %>
<%@ attribute name="validator" required="false" rtexprvalue="true" %>
<%@ attribute name="jsonVar" required="false" rtexprvalue="true" %>
<%@ attribute name="method" required="false" rtexprvalue="true" %>
<%@ attribute name="async" required="true" rtexprvalue="true"
type="java.lang.Boolean" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="js" tagdir="/WEB-INF/tags/js" %>
<js:authorize script="${script}" function="${function}"/>
<c:set var="xhrVar" value="${fn:trim(fn:substringBefore(function, '('))}XHR"/>
<c:set var="paramList"
value="${fn:substringBefore(fn:substringAfter(function, '('), ')')}"/>
var ${xhrVar} = new XHR("${method}", "${script}", ${async});
function ${function} {
<c:if test="${!empty validator}">
if (!(${validator}))
return;
</c:if>
var request = ${xhrVar}.newRequest();
${xhrVar}.addHeader("Ajax-Call", "${function}");
<c:forEach var="paramName" items="${paramList}">
<c:set var="paramName" value="${fn:trim(paramName)}"/>
${xhrVar}.addParam("${paramName}", ${paramName});
</c:forEach>
function processResponse() {
if (${xhrVar}.isCompleted()) {
<c:if test="${!empty jsonVar}">
var ${jsonVar} = eval(request.responseText);
</c:if>
<jsp:doBody/>
}
}
${xhrVar}.sendRequest(processResponse);
}
The first line of JavaScript code generated by rpc.tag creates the XHR object. Then, the tag file produces the JavaScript function that can be used in the Web browser to invoke its server-side counterpart. If the validator attribute has a non-empty value, the JavaScript expression is included in the generated code to decide whether the remote call can be made or not.
Next, the newRequest() function is used to initialize a new XMLHttpRequest object, which is stored in a local JavaScript variable named request. The generated code will add the Ajax-Call header, whose value is the function's signature. Then, the parameters are added to the XHR object. Listing 17 contains the code generated for the allocMem() function.
Listing 17. The allocMem() generated function
var allocMemXHR = new XHR("POST", "MonitorScript.jss", true);
function allocMem(size, seconds) {
if (!(valid('Size', size) && valid('Seconds', seconds)))
return;
var request = allocMemXHR.newRequest();
allocMemXHR.addHeader("Ajax-Call", "allocMem(size, seconds)");
allocMemXHR.addParam("size", size);
allocMemXHR.addParam("seconds", seconds);
function processResponse() {
if (allocMemXHR.isCompleted()) {
}
}
allocMemXHR.sendRequest(processResponse);
}
After the initialization of the XHR object, the rpc.tag file generates an Ajax callback named processResponse(). This function verifies if the Ajax request is completed and evaluates the response if the jsonVar attribute is present. |
|