Search code examples
jspjstljsp-tagsvar

Export scoped var from custom JSP tag


In the JSTL fmt tag library is the tag formatDate, which has an optional attribute var. When using the formatDate tag, you can pass in a string via the var attribute that specifies the name of the variable that will be created, whose value will be the formatted date string.

Unfortunately, Java (as of Java 8) doesn't support the Tongan and Samoan locales, which I need. Therefore, a co-worker created a custom date formatting tag that basically just formats the date using fmt:formatDate but then (in the case of Tongan and Samoan) replaces the day name and month name values with the appropriate translations. However, this custom tag only outputs (using c:out) the result, and I'd like to enhance the custom tag to be able to create a variable, just like fmt:formatDate does. Unfortunately, I don't know how.

c:set doesn't allow expressions in its var attribute, and for some reason pageContext is null inside the custom tag file (date-formatter.tag).

So here's what I have for the tag definition, minus extraneous details (assume the c and fmt taglibs are included, as well as the dateFormatterLocale variable):

<%@attribute name="value" type="java.util.Date" required="true" rtexprvalue="true" description="..." @>
<%@attribute name="type" required="true" rtexprvalue="true" description="..." %>
<%@attribute name="pattern" required="true" rtexprvalue="true" description="..." %>
<%@attribute name="var" required="false" rtexprvalue="false" description="..." %>

<fmt:formatDate type="${type}" pattern="${pattern}" value="${value}" var="dfFormattedDate" />
<c:if test="${((dateFormatterLocale == 'to') || (dateFormatterLocale == 'sm'))}">
    ...
    [stuff to translate day names and month names]
    ...
</c:if>
<c:choose>
    <c:when test="${not empty var}">
        <%-- SOMEHOW SET VARIABLE WHOSE NAME IS THE VALUE OF "var" AND WHOSE VALUE IS THE VALUE OF dfFormattedDate --%>
    </c:when>
    <c:otherwise>
        <c:out value="${dfFormattedDate}" />
    </c:otherwise>
</c:choose>

Solution

  • Use <c:set> with a target on the desired scope map and property on the ${var}.

    E.g. if you need it to be request scoped:

    <c:set target="${requestScope}" property="${var}" value="${dfFormattedDate}" />
    

    Or page scoped:

    <c:set target="${pageScope}" property="${var}" value="${dfFormattedDate}" />