Evaluating EL Expressions in Request Attributes

We store HTML markup inside XML and unmarshall documents using JiBX. We also use Spring, and when one of these objects is added to the model, we can access it in the JSP through EL.

${model.bookshelf.columnList[0].linkList[0].htmlMarkup} 

Nothing revolutionary. But what if we want to store EL expressions in HTML markup? For example, what if we want to keep the following link?

 <a href="/${localePath}/important">Locale-specific link</a> 

... and map it to JSP, where LocalePath is a request attribute.

Or even more interestingly, what if we want to keep the following?

 The link ${link.href} is in column ${column.name}. 

... and display it inside the nested JSP forEach ...

 <c:forEach var="column" items="${bookshelf.columnList}"> <c:forEach var="link" items="${column.linkList}"> ${link.htmlMarkup} </c:forEach> </c:forEach> 

These EL expressions in query attributes are never evaluated. Is there a way to get them to rate? Something like the "eval" tag? Replacing the token works in the first example, but not in the second and is not very reliable.

+4
source share
2 answers

If I understand correctly: you are looking for a way to evaluate the EL expression at run time, which is stored inside another value provided by the EL expression, something like a recursive evaluation of EL.

Since I could not find any existing tag for this, I quickly put together a proof of concept for such an EvalTag:

 import javax.el.ELContext; import javax.el.ValueExpression; import javax.servlet.ServletContext; import javax.servlet.jsp.*; import javax.servlet.jsp.tagext.SimpleTagSupport; public class SimpleEvalTag extends SimpleTagSupport { private Object value; @Override public void doTag() throws JspException { try { ServletContext servletContext = ((PageContext)this.getJspContext()).getServletContext(); JspApplicationContext jspAppContext = JspFactory.getDefaultFactory().getJspApplicationContext(servletContext); String expressionStr = String.valueOf(this.value); ELContext elContext = this.getJspContext().getELContext(); ValueExpression valueExpression = jspAppContext.getExpressionFactory().createValueExpression(elContext, expressionStr, Object.class); Object evaluatedValue = valueExpression.getValue(elContext); JspWriter out = getJspContext().getOut(); out.print(evaluatedValue); out.flush(); } catch (Exception ex) { throw new JspException("Error in SimpleEvalTag tag", ex); } } public void setValue(Object value) { this.value = value; } } 

Associated TLD:

 <?xml version="1.0" encoding="UTF-8"?> <taglib version="2.1" 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"> <tlib-version>1.0</tlib-version> <short-name>custom</short-name> <uri>/WEB-INF/tlds/custom</uri> <tag> <name>SimpleEval</name> <tag-class>SimpleEvalTag</tag-class> <body-content>empty</body-content> <attribute> <name>value</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.Object</type> </attribute> </tag> </taglib> 

Using:

 <custom:SimpleEval value="${someELexpression}" /> 

Note:

I tested it with Tomcat 7.0.x / JSP 2.1, but as you can see in the source code, there is no special error handling, etc., because it is just a proof of concept.

In my tests, it worked for session variables using ${sessionScope.attrName.prop1} , as well as query parameters using ${param.urlPar1} , but since it uses the current evaluator of the JSP expression, I believe that it should work and for all other "normal" EL expressions.

+2
source

You do not need to programmatically parse the el expression yourself, your tag must be provided with the result of the evaluation, including <rtexprvalue>true</rtexprvalue> in the taglib, for example.

  <tag> <name>mytag</name> <attribute> <name>myattribute</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> 
0
source

All Articles