Kontekst w tagach JSP 2.0

W weekend trafiłem na całkiem dobry opis użycia tagów z JSP 2.0. Tagi w tej wersji pozwalają w łatwy i przyjemny sposób upraszczać kod źródłowy widoku.

Próbowałem uruchomić jeden z pierwszych przykładów, operujący na danych zawartych wewnątrz taga:

<jsp:doBody var="theBody" />
<% String bc = (String) pageContext.getAttribute("theBody"); %>
<%= bc.toUpperCase() %>

Niestety próba kompilacji strony używającej taga się nie powiodła.

SEVERE: Servlet.service() for servlet jsp threw exception
org.apache.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 3 in the jsp file: /WEB-INF/tags/bar.tag
pageContext cannot be resolved
1: <jsp:doBody var="theBody" scope="page" />
2:
3: <% String theBody = (String) pageContext.getAttribute("theBody"); %>
4: <%= theBody %>

Szukałem pomocy w internecie jednak nie znalazlem żadnej interesującej wskazówki. Zajrzałem więc do implementacji taga wygenerowanej przez serwer aplikacji i coś przykuło moją uwagę.

public void doTag() throws JspException, IOException {
  PageContext _jspx_page_context = (PageContext) jspContext;
  // ...
  _jspx_page_context.setAttribute("theBody", _jspx_sout.toString(), PageContext.PAGE_SCOPE);
  // ...
  String theBody = (String) pageContext.getAttribute("theBody");
  // ...
}

Zgodnie z komunikatem błędu nie ma tam dostępu do zmiennej pageContext jednak istnieje jspContext, która jest rzutowana do typu PageContext. Podmiana zmiennej w kodzie źródłowym taga spowodowała, że tag się skompilował i wszystko zadziałało. Ostatecznie znalazłem potwierdzenie mojego domysłu w tym artykule jednak nadal nie wiem skąd ta różnica w nazewnictwie wynika. W związku z tym, poprawna implementacja taga powinna wyglądać następująco:

<jsp:doBody var="theBody" scope="page" />
<% String theBody = (String) jspContext.getAttribute("theBody"); %>
<%= theBody %>

Photo by Volodymyr Hryshchenko on Unsplash