DoubleDouble
DoubleDouble

Reputation: 1493

When do (jsp) scriptlets run their (Java) code?

I was working through a null pointer exception on code like the following:

<%
SessionData session = getSessionData(request);
Webpage webPage = null;
if (session!= null) {
    webPage = session.getWebPage();
}
%>

<script type="text/javascript"> 

//NullPointer happens here, webPage is null when the session is lost
<tags:ComboBox
    comboBox="<%=webPage.getComboBox()%>" />

</script>

I was surprised when I could move the ending of if (session!=null to after the javascript, which seems to ignore that code when the session was null.

<%
SessionData session = getSessionData(request);
Webpage webPage = null;
if (session!= null) {
    webPage = session.getWebPage();
//} move this to below
%>

<script type="text/javascript"> 

//NullPointer happens here, webPage is null when the session is lost
<tags:ComboBox
    comboBox="<%=webPage.getComboBox()%>" />

</script>
<% } %> //moved to here

Does the scriptlet for the ComboBox tag, inside the brackets, no longer run? I would think it would still try to get the combobox off the webpage, and still end up getting a null pointer. Am I incorrect in thinking that scriptlets all get their values before the code is actually ran?

(just thought I'd mention, there is an included script which redirects the page if there is no session. I get a NullPointer with the first section of code, and correctly redirect with the second section)

Upvotes: 2

Views: 3579

Answers (2)

Shotgun Ninja
Shotgun Ninja

Reputation: 2540

In short, you are incorrect as to the order in which tag libraries and scriptlets are processed; the JSP compiler first identifies JSP directives, then resolves and renders tag library output, and then converts everything not in a scriptlet into a bunch of static strings written to the page, before stitching the resulting Java file together around the existing scriptlet code, looking something like this:

// start of class and _jspService method declaration omitted for brevity

    out.write("<html>\n");
    out.write("\t<head>\n");
    out.write("\t<title>Example Static HTML</title>\n");

// comment inside a scriptlet block
int x = request.getParameter("x");
pageContext.setParameter("x", x);

    out.write("\t</head>\n");

The problem here stems from the fact that Tag Libraries are resolved first, and the code which isolates and evaluates them doesn't care about either scriptlet blocks or the DOM. In your case, the <tags:ComboBox> tag just thinks the scriptlet is a regular string.

What you should be doing instead is exposing the value in your scriptlet to the accessible scope used by the tag library; in the case of JSTL, for example, you need to add it into the page context via pageContext.setAttribute("varName", value).

Check this answer for more details.

Upvotes: 0

Andreas
Andreas

Reputation: 159127

A JSP is compiled to a servlet on-the-fly by the servlet container.

This compilation is actually simple kind of inversion:

TEXT1
<% java code %>
TEXT2
<%= java expression %>
TEXT3

That is compiled to:

out.print("TEXT1");
java code
out.print("TEXT2");
out.print(java expression);
out.print("TEXT3");

So when you say:

TEXT1
<% if (true) { %>
TEXT2
<% } %>
TEXT3

You get:

out.print("TEXT1");
if (true) {
out.print("TEXT2");
}
out.print("TEXT3");

The above examples are minified for clarity, e.g. newlines are ignored, the boilerplate servlet setup is not included, and the complexity of tag library execution is not covered.

Upvotes: 3

Related Questions