Taglib para referencias constantes en archivos jsp

20/02/2015

taglibs
Una de las limitaciones que tiene el estándar EL (Expression Language) de JSP (al menos hasta la versión 2.2), es que no permite acceder a las constantes de una clase Java.

Para suplir esta carencia podemos crearnos nuestra propia tagLib. A continuación incluyo el código completo de una sencilla etiqueta que yo mismo he creado. La idea es muy sencilla, guardar un Map en una variable definida a nivel de Contexto de Aplicación Web (por defecto, pero configurable) y reutilizar dicha variable si ya ha sido definida en algún momento (por defecto, pero configurable) para evitar estar continuamente analizando la clase de la que queremos “extraer” las constantes.


ConstantsTag.java

package org.eu.rubensa.web.taglib.constants;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.TagSupport;

import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;

/**
* Get all class constants (statics) and place into Map so they can be accessed
* from EL.
*
* @author rubensa
*/
public class ConstantsTag extends TagSupport {
public static final long serialVersionUID = 1L;

private String className = "";
private String var = "";
private int scope = PageContext.APPLICATION_SCOPE;
private boolean override = false;

public void setClassName(String className) throws JspException {
this.className = (String) ExpressionUtil.evalNotNull("constants",
"className", className, String.class, this, pageContext);
}

public void setVar(String var) throws JspException {
this.var = (String) ExpressionUtil.evalNotNull("constants", "var", var,
String.class, this, pageContext);
}

public void setScope(String scope) {
if (scope.equalsIgnoreCase("page")) {
this.scope = PageContext.PAGE_SCOPE;
} else if (scope.equalsIgnoreCase("request")) {
this.scope = PageContext.REQUEST_SCOPE;
} else if (scope.equalsIgnoreCase("session")) {
this.scope = PageContext.SESSION_SCOPE;
} else if (scope.equalsIgnoreCase("application")) {
this.scope = PageContext.APPLICATION_SCOPE;
}
}

public void setOverride(boolean override) {
this.override = override;
}

public int doStartTag() throws JspException {
if (override == false && pageContext.getAttribute(var, scope) != null) {
return SKIP_BODY;
}
// Use Reflection to look up the desired field.
try {
Class clazz = null;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new JspException("Class " + className + " not found.");
}
Field[] flds = clazz.getDeclaredFields();
// Go through all the fields, and put static ones in a Map.
Map constMap = new TreeMap();
for (int i = 0; i < flds.length; i++) {
// Check to see if this is public static final. If not, it's not
// a constant.
int mods = flds[i].getModifiers();
if (!Modifier.isFinal(mods) || !Modifier.isStatic(mods)
|| !Modifier.isPublic(mods)) {
continue;
}
Object val = null;
try {
val = flds[i].get(null); // null for static fields.
} catch (Exception ex) {
System.out.println("Problem getting value of "
+ flds[i].getName());
continue;
}
// flds [i].get () automatically wraps primitives.
// Place the constant into the Map.
constMap.put(flds[i].getName(), val);
}
// Export the Map as an scoped variable.
pageContext.setAttribute(var, constMap, scope);
} catch (Exception ex) {
if (!(ex instanceof JspException)) {
throw new JspException(
"Could not process constants from class " + className);
} else {
throw (JspException) ex;
}
}
return SKIP_BODY;
}
}

constants.tld

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
version="2.1">

<description>Constants library</description>
<display-name>Constants</display-name>
<tlib-version>1.1</tlib-version>
<short-name>constants</short-name>
<uri>http://rubensa.eu.org/jsp/jstl/constants/tags</uri&gt;
<tag>
<description>Simple tag, which gets all class constants (statics) and place into Map so they can be accessed from EL.</description>
<name>constants</name>
<tag-class>org.eu.rubensa.web.taglib.constants.ConstantsTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>The path (full class name) to the constants Class.</description>
<name>className</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>Name of the exported scoped variable for the resulting indexed Map by all public static final variables java names. The type of the scoped variable is Map.</description>
<name>var</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>Scope for var (default "application").</description>
<name>scope</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<description>If variable exist in context should It be overrided (default "true").</description>
<name>override</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
<type>boolean</type>
</attribute>
</tag>
</taglib>

Luego, en nuestra jsp podríamos hacer uso de la etiqueta del siguiente modo:


<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="const" uri="http://rubensa.eu.org/jsp/jstl/constants/tags" %>

<const:constants className="java.lang.Boolean" var="Boolean" />

<c:if test="${ Boolean.TRUE.booleanValue() }">TRUE</c:if>

vía

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: