|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 6
The TestMethodTag.jsp page uses the <tm:testMethod2> tag to call the bean method. Within <tm:testMethod2>'s body, the JSP page uses the ${ret} construct to get the value returned by the bean method.
The tag handler uses getJspBody() to obtain a JspFragment object that represents the body of the <tm:testMethod2> action. The JspFragment's invoke() method executes the Java code generated from the <tm:testMethod2>'s JSP body. In this example, the resulting HTML output goes to the JSP's writer, but the output could have been redirected
to another writer by passing to invoke() a java.io.Writer object instead of null:
public void doTag() throws JspException, IOException {
String ret = object.testMethod(text, number, logic);
JspContext context = getJspContext();
context.setAttribute("ret", ret);
JspFragment body = getJspBody();
body.invoke(null);
}
}
If you want a better understanding of the way in which the tag handler methods are invoked, look at the Java servlet generated
by your application server to execute the JSP page. Tomcat 5.0 places the generated Java servlets in TOMCAT_HOME/work/Catalina/localhost/calltag/org/apache/jsp.
The TestMethodTag.jsp page uses the <%@taglib%> directive to specify the prefix of the tags and the library's URI:
<%@ taglib prefix="tm" uri="http://devsphere.com/articles/calltag/TestMethodTag.tld"%>
The <jsp:useBean> tag creates an instance of the TestBean class stored as a JSP page attribute named obj:
<jsp:useBean id="obj" class="com.devsphere.articles.calltag.TestBean"/>
The bean method is called twice with the help of the two custom tags handled by TestMethodTag and TestMethodTag2. The first call gets some constant parameters, while the second call gets the values of the bean properties as parameters.
Both calls output the value returned by testMethod():
<HTML>
<BODY>
<tm:testMethod object="${obj}" text="abc" number="123" logic="true"/>
<HR>
<tm:testMethod2 object="${obj}"
text="${obj.text}" number="${obj.number}" logic="${obj.logic}">
-- ${ret} --
</tm:testMethod2>
</BODY>
</HTML>
The TestMethodTag.jsp page produces the following HTML output:
<HTML> <BODY> abc 123 true <HR> -- abcabc 246 true -- </BODY> </HTML>
The TestMethodTag.tld file describes the <tm:testMethod> and <tm:testMethod2> tags. Both have the same list of attributes: object, text, number, and logic. All attributes are required (none are optional). Any attribute's value can be either a constant or an expression (because
rtexprvalue is true). The first tag's body must always be empty, while the second tag's body may contain scriptless JSP code:
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>tm</short-name>
<uri>http://devsphere.com/articles/calltag/TestMethodTag.tld</uri>
<tag>
<name>testMethod</name>
<tag-class>com.devsphere.articles.calltag.TestMethodTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>object</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>text</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>number</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>logic</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
<tag>
<name>testMethod2</name>
<tag-class>com.devsphere.articles.calltag.TestMethodTag2</tag-class>
<body-content>scriptless</body-content>
<attribute>
<name>object</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>text</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>number</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>logic</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
The tag library is declared in the web.xml application descriptor:
<taglib>
<taglib-uri>
http://devsphere.com/articles/calltag/TestMethodTag.tld
</taglib-uri>
<taglib-location>
/WEB-INF/TestMethodTag.tld
</taglib-location>
</taglib>
So far, this article has presented two ways for calling JavaBean methods from scriptless JSP pages. Both ways require some work that may be worthwhile for frequently called methods. In the case of JSP functions, you must provide static wrappers for nonstatic methods, and you must declare the functions in a TLD file. If you prefer to use custom tags, you have to code the tag handler classes and describe the custom tags in a TLD file. A third way for calling JavaBean methods doesn't require extra work. You may use a generic tag based on the Java Reflection API and the new JSP 2.0 dynamic attributes.
The generic tag has the following syntax:
<ct:call object="..." method="..."
return="..." scope="..." debug="..."
param1="..." param2="..." ... />
The CallTag class extends SimpleTagSupport and overrides the doTag() method like the tag handlers from the earlier sections. In addition, the CallTag class implements the DynamicAttributes interface, whose setDynamicAttribute() method lets you handle attributes not described in the TLD file:
package com.devsphere.articles.calltag;
import javax.servlet.jsp.JspContext;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.DynamicAttributes;
import javax.servlet.jsp.tagext.SimpleTagSupport;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class CallTag extends SimpleTagSupport implements DynamicAttributes {
The CallTag class declares a field for each tag attribute. The paramValues list will maintain the dynamic attributes' values, which are actually the values that will be passed as parameters to the
JavaBean method:
private Object object;
private String methodName;
private String returnVar;
private int returnScope;
private boolean debugFlag;
private List paramValues;
Some of the fields are initialized with default values within the CallTag() constructor. The other fields don't need initialization because their corresponding attributes are required or because the
default Java values such as null and false are suitable for them. Here is the CallTag() constructor:
public CallTag() {
returnScope = PageContext.PAGE_SCOPE;
paramValues = new LinkedList();
}
The object attribute specifies the bean instance whose method must be called. Usually, you create or find an object with <jsp:useBean id="someID" ... > and then call its methods using <ct:call object="${someID}" ... >:
public void setObject(Object object) throws JspException {
if (object == null)
throw new JspException("Null 'object' attribute in 'call' tag");
this.object = object;
}
The method attribute specifies the JavaBean method name that must be called:
public void setMethod(String methodName) throws JspException {
if (methodName == null)
throw new JspException("Null 'method' attribute in 'call' tag");
if (methodName.length() == 0)
throw new JspException("Empty 'method' attribute in 'call' tag");
this.methodName = methodName;
}
The return attribute is optional and specifies the JSP variable name that will hold the value returned by the JavaBean method: