jspjsp-tags

JSP: "object cannot be resolved to a variable" when used in nested tag


I am trying to build app pages via JSP, using nested tags within an outer tag ("page"). All of the tags need access to the same object, which is passed in from the controller. But I can't find out how to use the same object as attribute to a tag from within another tag.

page.tag (outer, simplified):

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ attribute name="var" required="true" type="java.util.Map"%>
<!DOCTYPE html>
<html>
<head>
<title>${var.title}</var>
... some shared headers ...
</head>
<body>
... some shared body elements, navigation etc. ...
<jsp:doBody></jsp:doBody>
... more shared body elements, footer etc. ...
</body>
</html>

login.tag (nested, simplified):

<%@ tag language="java" pageEncoding="UTF-8"%>
<%@ attribute name="var" required="true" type="java.util.Map"%>
<div class="login">
<form id="loginForm">
<input type="text" name="username">
<input type="password" name="password">
<input type="hidden" name="session" value="${var.session}">
...
</form>
</div>

Used in login.jsp like this:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
 import="java.util.Map"
%>
<%@ taglib prefix="t" tagdir="/WEB-INF/tags" %>
<%! @SuppressWarnings("unchecked") %>
<%
Map<String,String> var = Map.of();
if (request.getAttribute("variables") != null) {
    var = (Map<String,String>) request.getAttribute("variables");
}
%>

<t:page var="<%= var %>">
<jsp:body>
<t:login var="<%= var %>"></t:login>
</jsp:body>
</t:page>

Controller.java:

...
Map<String,String> var = Map.of("title", "Page title", "session", "1234567890");
request.setAttribute("variables", var);
...

I get the following error message:

Unable to compile class for JSP: An error occurred at line: [203] in the generated java file:
[/var/lib/tomcat9/work/Catalina/app-name/org/apache/jsp/WEB_002dINF/jsp/login_jsp.java]
var cannot be resolved to a variable

Without the <t:login>, or if I put only simple html into login.tag that doesn't need any objects, it works (i.e. var is visible in page.tag).

Is there a way to use var in both page.tag and login.tag? Or am I looking at this the wrong way? Thanks for any pointers!


Solution

  • You should use attribute in tags to pass a variable.

    In tag:

    <%@ attribute name="var" required="true" type="java.util.Map" rtexprvalue="true"%>
    
    

    In JSP:

    <t:page var="${variables}">
    <jsp:body>
    <t:login var="${variables}"></t:login>
    </jsp:body>
    </t:page>
    

    For details: Declaring Tag Attributes for Tag Handlers