0

In my application I am trying to get labels out of a message bundle. However rather then use constant key values I am using variables

<c:forEach var="emailAddress" items="${emailAddresses}">
...
<c:set var="labelKey" value="Contact_Label_${emailAddress.type}"/>
...
<h:outputText value="#{faces_translations[labelKey]}"/>
...
</c:forEach>

Most of the time this works correctly, but every so often when a page is loaded some of the label are not processed correctly and the following message is displayed:

???Contact_Label_???

It looks like the email.type does not return a value, however I added some debug code to print out the value of email.type by including

${emailAddress.type}

and saw that a value was returned.

Another thing I tried was to remove the value everytime before setting it again inside the loop using . This resulted in the following exception. I verified that I had the tag library included in the WAR file (jstl-api-1.2.jar and jstl-impl-1.2.jar as well as javax.faces-2.1.7).

<c:remove> Tag Library supports namespace: http://java.sun.com/jsp/jstl/core,
but no tag was defined for name: remove

Both these issues are really baffling. The label works most of the time, but not consistently. The tag is defined in the included library, but cannot be found.

Thanks in advance for any pointers.

1 Answers1

1

JSF UI components and tag handlers like JSTL doesn't run in sync. JSTL runs when the JSF view is to be built. The result is a JSF component tree without any tag handlers like <c:xxx> and <f:xxx>. JSF UI components runs when the JSF view needs to generate HTML for the HTTP response. That very same JSF view can be reused multiple times in subsequent HTTP requests as long as you're interacting with the same view by returning null or void on POST actions (like as you should use a @ViewScoped bean). It is not true that JSTL tags runs on every single HTTP request. That's most likely where it went wrong in your case.

Rather use JSF UI components if you want consistent render-time behaviour while reusing the same view. Your construct can be replaced as follows:

<ui:repeat var="emailAddress" value="#{emailAddresses}">
    ...
    <ui:param name="labelKey" value="Contact_Label_#{emailAddress.type}" />
    ...
    <h:outputText value="#{faces_translations[labelKey]}" />
    ...
</ui:repeat>

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555