Useless Tag Library?
Inspired by this post, I wrote a tag library to expose the fields of my Contants.java class to my JSPs. It allows a user to specify a single variable using:
<appfuse:constants var="USER_KEY"/>
Or all variables:
<appfuse:constants/>
By default, it exposes the values from the Contants class imported into the tag library, but also allows a className variable to specify a different class. The main reason I wrote this was to prove it was possible. The second reason was to get around importing my Contants class (and using <%=Contants.VARNAME%>). With this tag, both of the following work:
Scriptlet: <%=VARNAME%>, JSTL: <c:out value="${VARNAME}"/>
The only thing it gives you over the import/scriptlet way is to expose the attribute to different scopes - i.e. page for JSTL. After writing it, I think it's a fairly useless tag library - I don't know if I'll ever use it, but maybe someone else will find it useful.
- BTW, you need to use it on the JSP you plan to use it in a scriptlet and you can't wrap it with oscache's <cache> tags.
Files Needed for Tag Library
- ConstantsTag.java
- ConstantsTei.java - exposes variables as attributes
ConstantsTag.java
package org.appfuse.webapp.taglib;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.taglib.TagUtils;
import org.appfuse.common.Constants;
/**
* <p>This class is designed to put all the public variables in a class to a
* specified scope - designed for exposing a Constants class to Tag
* Libraries.</p>
*
* <p>It is designed to be used as follows:
* <pre><tag:constants /></pre>
* </p>
*
* <p>Optional values are "className" (fully qualified) and "scope".</p>
*
* <p>
* <a href="BaseAction.java.html"><i>View Source</i></a>
* </p>
*
* @author <a href="mailto:[email protected]">Matt Raible</a>
* @version $Revision: 1.1 $ $Date: 2003/12/31 13:59:32 $
*
* @jsp.tag name="constants" bodycontent="empty"
* tei-class="us.co.adams.apptracker.webapp.taglib.ConstantsTei"
*/
public class ConstantsTag extends TagSupport {
private Log log = LogFactory.getLog(ConstantsTag.class);
/**
* The class to expose the variables from.
*/
public String clazz = Constants.class.getName();
/**
* The scope to be put the variable in.
*/
protected String scope = null;
/**
* The single variable to expose.
*/
protected String var = null;
public int doStartTag() throws JspException {
// Using reflection, get the available field names in the class
Class c = null;
int toScope = PageContext.PAGE_SCOPE;
if (scope != null) {
// default to pageScope
toScope = TagUtils.getInstance().getScope(scope);
}
try {
c = Class.forName(clazz);
} catch (ClassNotFoundException cnf) {
log.error("ClassNotFound - maybe a typo?");
throw new JspException(cnf.getMessage());
}
try {
// if var is null, expose all variables
if (var == null) {
Field[] fields = c.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (int i = 0; i < fields.length; i++) {
/*if (log.isDebugEnabled()) {
log.debug("putting '" + fields[i].getName() + "=" +
fields[i].get(this) + "' into " + scope +
" scope");
}*/
pageContext.setAttribute(fields[i].getName(),
fields[i].get(this), toScope);
}
} else {
try {
String value = (String) c.getField(var).get(this);
pageContext.setAttribute(c.getField(var).getName(), value,
toScope);
} catch (NoSuchFieldException nsf) {
log.error(nsf.getMessage());
throw new JspException(nsf);
}
}
} catch (IllegalAccessException iae) {
log.error("Illegal Access Exception - maybe a classloader issue?");
throw new JspException(iae);
}
// Continue processing this page
return (SKIP_BODY);
}
/**
* @jsp.attribute
*/
public void setClassName(String clazz) {
this.clazz = clazz;
}
public String getClassName() {
return this.clazz;
}
/**
* @jsp.attribute
*/
public void setScope(String scope) {
this.scope = scope;
}
public String getScope() {
return (this.scope);
}
/**
* @jsp.attribute
*/
public void setVar(String var) {
this.var = var;
}
public String getVar() {
return (this.var);
}
/**
* Release all allocated resources.
*/
public void release() {
super.release();
clazz = null;
scope = Constants.class.getName();
}
}
|
ConstantsTei.java
package org.appfuse.webapp.taglib;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.VariableInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.appfuse.common.Constants;
/**
* Implementation of <code>TagExtraInfo</code> for the <b>constants</b>
* tag, identifying the scripting object(s) to be made visible.
*
* @author Matt Raible
* @version $Revision: 1.1 $ $Date: 2003/12/31 13:59:32 $
*/
public class ConstantsTei extends TagExtraInfo {
private Log log = LogFactory.getLog(ConstantsTei.class);
/**
* Return information about the scripting variables to be created.
*/
public VariableInfo[] getVariableInfo(TagData data) {
// loop through and expose all attributes
List vars = new ArrayList();
try {
String clazz = data.getAttributeString("className");
if (clazz == null) {
clazz = Constants.class.getName();
}
Class c = Class.forName(clazz);
// if no var specified, get all
if (data.getAttributeString("var") == null) {
Field[] fields = c.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (int i = 0; i < fields.length; i++) {
vars.add(new VariableInfo(fields[i].getName(),
"java.lang.String", true,
VariableInfo.AT_END));
}
} else {
String var = data.getAttributeString("var");
vars.add(new VariableInfo(c.getField(var).getName(),
"java.lang.String", true,
VariableInfo.AT_END));
}
} catch (Exception cnf) {
log.error(cnf.getMessage());
cnf.printStackTrace();
}
return (VariableInfo[]) vars.toArray(new VariableInfo[] { });
}
}
|
Also see my blog post.
|