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

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)

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.

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.

Related

script inside scriptlet - bad practice how to avoid

i am working on a legacy project where i have seen below piece of code.
I know it is a bad practice to use script inside scriptlet.
Regarding this , i have few confusion in mind.
what i believe is scriptlet is executed before page loads, so if below if condition is true then ShowBookReference() function call is a part of an Html page, but my question is when page is rendered should this function call happens or not ?
<% if (refLinkTerm != null) { %>
<script Language="javascript">
ShowBookReference('<%=sub2ndNavMenu%>', '<%=refLinkTerm%>', <%=String.valueOf(searchType)%>, <%=String.valueOf(codeType)%>)
</script>
<%}%>
How to avoid this kind of practice ?
Please share your thoughts.
Use an MVC framework such as Spring MVC. In these frameworks, you fill in a Java object (or map of objects) with the values for the page to display, and then the page just fills in placeholders with those values.
In terms of JSP, Its usual to use scriptlets to assign value to JS.
But as you've mentioned that it runs before the page load, so it's good to run the function on window.onload.
<script type="text/javascript">
window.onload = function() {
ShowBookReference('<%=sub2ndNavMenu%>', '<%=refLinkTerm%>', <%=String.valueOf(searchType)%>, <%=String.valueOf(codeType)%>)
}
</script>
In case you're referring some DOM elements inside ShowBookReference function, it may not be available so run it on page load.
Else you can use UI frameworks like JSF which provides you tags to bind java values to UI easily.

How to use variable defined in a scriptlet in the same jsp page

I have a jsp page namely User_Ref.jsp whcih has a datepicker .When I click on submit on that page ,it is redirected to another jsp page namely ref_time_current.jsp.In this jsp page I have used a scriptlet to hold the value which was selected by user from the calendar i.e datepicker. The scriptlet is
<%
Ref_log_current obj = new Ref_log_current();
String str= request.getParameter("datepicker");
ref.refarray_vac1(str);
%>
Now I want to use this str variable defined in scriptlet in this way in same jsp page-<c:out value="${ref.refarray_vac1(str)}"></c:out>
But When I execute this,refarray_vac1(String Date) method which return list is showing an empty list.I think I'm using the str variable in wrong way.Please correct me.
JSTL has only access to scoped variable, not directly to scriplet ones. But you can easily create a page variable that way :
<%
Ref_log_current obj = new Ref_log_current();
String str= request.getParameter("datepicker");
pageContext.setAttribute("str", str); // store str in page scope under name str
%>
You can then safely access ${str} in the JSP file.
In JSTL is not possible to use scriptlet variable in expression. Also you don't need to use scriptlet.
You need to import the bean class you create in JSP
<%# page import="com.beans.Ref_log_current" %>
You can access parameters like this
<jsp:useBean id="ref" class="com.beans.Ref_log_current" scope="page"/>
<c:out value="${ref.refarray_vac1(param.datepicker)}"/>

is it possible to set page content type on a condition in jsp or to set different content type for a single jsp

I want to display JSON & XML using a single jsp page.
at a time only one attribute will come from the java class.
My code something look like this.
<%
String json = (String) request.getAttribute("userRequestedJsonById");
if (!StringUtility.isNullOrEmpty(json)) {%>
<%=json%>
<% } else { %>
<%
String xml = (String) request.getAttribute("searcherRespondedXmlById");
if(!StringUtility.isNullOrEmpty(xml)) {%>
<%#page contentType="text/xml"%>
<%=xml%>
<%}%>
<%}%>
I am having a plugin called JSONVIEW to display the json properly.which doesn't work if it finds content type xml.
Content type is set only on the condition,jsp is including this content type even condition is not satisfied.
I don't know much how jsp set content type works,is there any other way to do this or to restrict to set content type xml on a particular condition.
Thanks.
Setting the content type needs to be done before printing anything out, so you need to get rid of the pointless opening and closing of tags that causes whitespace to be printed. Then you will use response.setContentType():
<%
String json = (String) request.getAttribute("userRequestedJsonById");
if (!StringUtility.isNullOrEmpty(json))
{
response.setContentType("application/json");
out.print(json);
}
else
{
String xml = (String) request.getAttribute("searcherRespondedXmlById");
if(!StringUtility.isNullOrEmpty(xml))
{
response.setContentType("text/xml");
out.print(xml);
}
}
%>
Its also just cleaner if you're going to use Scriptlets to just keep your code block open and use out.print() rather than opening, closing, and then <%=var%>, and opening again. That's just so unreadable.

How do I pass a New line character to JavaScript from my Servlet?

I'm setting the following in the request attribute:
confirmMsg = "REf No: \n 112";
req.setAttribute("confirmMsg", confirmMsg);
I need the above to be displayed like(in alert box) :
Ref No:
112
I'm using the following onload function in my JavaScript to show the message on loading the page.
function onLoad() {
var msg = "${confirmMsg}";
if(msg != null && msg != "") {
alert(msg);
}
}
The above throws a script error? How do I pass the newline character?
The \n needs to be JavaScript-escaped to be put in a JavaScript string literal.
Use commons-lang StringEscapeUtils.escapeECMAScript() to eascape the message, and pass this escaped message to your JSP.
As I mentioned, do not confuse JSP with JavaScript.
What you want to do is output a string message from your JSP/Servlet (JSP is a Servlet) to be used in a JavaScript code block.
To do this your message needs to be encoded for JavaScript, such as using the StringEscapeUtils.escapeECMAScript method described by JB Nizet.
Then you need, in your jsp or servlet creating the response, to output the variable where you want it for the javascript to act upon, for this you do
<%= confirmMsg %>
and not ${} as that is an expression language which is not always available in every jsp.
In short, change from "${confirmMsg}" to <%= confirmMsg %> or <%= (String)request.getParameter("confirmMsg") %> // or request.getAttribute and so on

java if statement to check if object is empty

hi I am new to java and I am creating a jsp and I am using scriplet code. I would like to be able to have my object to not display on the screen when it is empty.
<% if (webApp.getInfo != null) { %> <h6><%=webApp.getInfo()%> <% } %>
Currently it is checking if the object is null but it is still displaying a line on the page when I run the JSP. How can I check to see if webApp.getInfo is empty and not have a line display or test display for those headers?
<c:if test="${!empty str}">
<h6>...</h6>
</c:if>
Note that:
this is meaningful only for strings, not for any object
this is JSTL, which is preferred to scriptlets (from your example)
your objects needs to be set as request attribute.
you only need this if you have additional tags inside the if-clause. If it is only the string that you want to output, there is no need to check - as BalusC noted this is not displayed.
you can trim whitepsaces from the jsp output using configurations provided by your servlet container, or if using servlet 3.0 - via <trim-directive-whitespaces> in web.xml

Categories