I want someone to explain some points in BlausC's amazing answer in this question.
He said that scriptlets had some disadvantages, which are:
Reusability: you can't reuse scriptlets. My question : how could I reuse JSTL code?
Replaceability: you can't make scriptlets abstract. What does abstract mean and how could JST become abstract?
OO: you can't make use of inheritance/composition. How could I use OO paradigms in JSTL?
Debugging: if a scriptlet throws an exception halfway, all you get is a blank page.
Testability: scriptlets can't be unit tested. What does that mean, and how can JSTL be unit tested?
Maintainability: per saldo, more time is needed to maintain mingled/cluttered/duplicated code logic. What does this mean?
The last thing is what he quoted form Oracle's recommendation:
JSP scriptlets should not be used for writing business logic.
In the MVC pattern, I use scriptlets only in the presentation layer. What does he mean here?
You seem to concentrate on only the presentation and flow-control part of the scriptlets as in using if, for and switch statements and out.print() things. You seem to compare scriptlets 1:1 with JSTL. This is wrong. I was not talking about the flow control part only (which is indeed to be replaced by JSTL), but about writing raw Java code in JSP files in general. I.e. gathering request parameters, validating and converting values, interacting with database and other Java classes/methods, etc. All things you normally (indirectly) do in a Servlet or Filter.
You should not have scriptlet code in JSPs. I'd recommend 100% JSTL and zero scriplet code.
JSPs should be purely presentation. That's the hidden benefit of writing JSPs using only JSTL, because they get all their dynamic data elsewhere. Let the service layer have the business logic and determine what data the JSP needs.
This answers your unit testing question, too. You should not have to unit test JSPs; those would be Selenium-like UI tests. If the logic is in the service tier, it's obvious how you test it.
JSPs should not be inherited. You can certainly compose them together using something like SiteMesh, but inheritance has no part in your JSPs. Once they inherit from Servlet, the chain should be ended.
Besides, it's a false alternative. Neither one should require reuse, inheritance, or unit testing. But that doesn't mean there isn't a clear winner: it's JSTL. No one should be using scriptlets in JSPs, except for very rare one-liners. Scriptlets are begging for trouble.
These days I prefer Velocity as my web UI template solution for Java, much more than JSPs. Just my opinion.
I can't speak for BalusC but in general I believe he was getting at the idea that these kinds of things should be accomplished by your ordinary Java code (in the Controller and Model layers if you're into the whole MVC thing).
You can't literally reuse JSP tags at an individual level, but you can reuse the classes they call into.
JSTL can't be abstract, but ordinary Java code (which you can perhaps invoke from JSTL) can be.
Again, you can't make objects usefully in jstl, but you can in all the classes that are called.
JSTL by itself is not unit-testable. But the classes and methods you call through it are.
It depends on the pattern you're using. By using the MVC (spring, struts, ...) you should avoid the usage of scriptlets in your JSP, because it represent the view it should contain pure XHTML tags. JSTL is a declarative language some kind of XML, while scriplet isn't.
Particularly I have used JSTL in combination with AJAX via prototype for generating RIA without needing to implement another pattern. Recently I have seen this kind of programming with ExtJS and DWR. In my case I found It was necessary to combine both JSTL and scriplets always preferring JSTL when possible.
<!-- simple controller, each action is called by means of AJAX -->
<% String signExt="jpg"; %>
<% int r=0, iMaxRows=0, iMaxCols=0;%>
<c:choose>
<c:when test="${param.action == 'get_chrequest_profile_table_by_family_and_date'}">
<sql:query var="dataset">
CALL GetProfilesView('<c:out value="${param.family_name}" />', '<c:out value="${param.reg_date}" />')
</sql:query>
<c:set var="strElements"><c:out value="${dataset.rowCount}" /></c:set>
<%
String strElements = pageContext.getAttribute("strElements").toString();
int iElements = (int)Integer.valueOf(strElements).intValue();
String to = "";
%>
<table class="tb_profiles" id="tb_profiles" iElements="<%=iElements%>"
width="100%" frame=void border="0" cellPadding="0" cellSpacing="0" style="border-top: 3px solid gray; border-left: 1px solid gray">
<%for(int i=1, j=0, col=0; i<100; i++){%>
<tr>
<%for(j=0; j<4; j++, col++){%>
<c:set var="c" scope="page"><%=col%></c:set>
<td name='<c:out value="${dataset.rows[c].chreqprofile_id}" />' >
<table width="100%" frame="below" cellPadding="0" cellSpacing="0"style="border-right: 1px solid gray;">
<%if( col < iElements){%>
<tr style="height:10mm">
<td class="td_function" style="cursor:default;">
<c:out value="${dataset.rows[c].description}" />
</td>
</tr>
.................
<tr style="height:14mm">
<td class="td_signature" align="center" vAlign="middle">
<img class="img_signature"
src='../xdata/signatures/<c:out value="${dataset.rows[c].responsible_name}"/>.<%=signExt%>'
alt='<c:out value="${dataset.rows[c].email}" />'
/>
</td>
</tr>
.................
<c:set var="sMail"><c:out value="${dataset.rows[c].email}"/></c:set>
<% if( col < iElements-1){
to = to + pageContext.getAttribute("sMail").toString() + ",";
}else{
to = to + pageContext.getAttribute("sMail").toString();
}
%>
<%}else{%>
<tr style="height:10mm">
<td class="td_function" style="cursor:default;">x</td>
.............
</tr>
<%}%>
</table>
</td>
<%}%>
</tr>
<%
if( col >= iElements){break;}
}%>
</table>
<span id="span_mail_to" style="display:none;"><%=to%></span>
</c:when>
<c:when test="${param.action == 'functions_form_insert'}">
.............
</c:when>
</c:choose>
I dont see that scriplets is too bad specially if you follows design pattern in it, I work a lot on spring mvc, in my jsp i just get the model data in scriplits, and i show it to the user using simple java code in html, i feel it give me more freedom than JSTL.
Here is a table comparing JSP and Facelets that may possibly be helpful to someone, somewhere:
Source
Related
I'm a newbie to the CheckMarx and preventing XSS attacks. I've got this error:
Method %> at line 1 of \app\src\web\searchresults.jsp gets user input for the getSearchResults element. This element’s value then flows through the code without being properly sanitized or validated and is eventually displayed to the user in method %> at line 1 of \app\src\web\searchresults.jsp. This may enable a Cross-Site-Scripting attack.
This is the line that it complaining about in the code snip below:
<c:forEach var="combo" items="${searchForm.searchResults}">
Code snip from a searchresults.jsp (code modified to protect the innocent)
<% int i = 0;%>
<c:forEach var="combo" items="${searchForm.searchResults}">
<tr <%=i++%2==0?"":"class='odd'"%>>
<td align="center" style="width: 40px;"><c:out value="${combo.stay.status}"/></td>
<c:choose>
<c:when test="${hasDetailAccess}">
<c:url var="detailLink" value="/detail.do">
<c:param name="code" value="${searchForm.code}"/>
<c:param name="brandCode" value="${searchForm.brandCode}"/>
<c:param name="smUni" value="${combo.object1.smUni}"/>
<c:param name="shUni" value="${combo.object1.shUni}"/>
<c:param name="searchType" value="${searchForm.searchType}"/>
</c:choose>
<td style="width: 80px;"><fmt:formatDate pattern="MMM dd yyyy" value="${combo.object1.dateMade.date}"/></td>
<td style="width: 80px;"><c:out value="${combo.object1.lastName}"/></td>
<td style="width: 80px;"><c:out value="${combo.object1.firstName}"/></td>
</c:forEach>
The part that I'm not for sure of how to fix is that the "searchForm.searchResults" is an queueCombo that can refer to multiple objects, for this instance, "object1".
My thought is to do the clean-up on the object. My method of doing this would be to add the needed attributes the page is using (as the "object1" is HUGE number of attributes) and put as single values and populate them when the object is constructed.
I don't have a specific solution for sanitizing your "queueCombo" after that it has been built, but generally the best-practices for securing the user inputs are:
as soon as the value is received from the user (early control): here before building your object. Most sanitizations made early intend to remove forbidden characters and control values formats. Eg: here the first and last names should not contain anything else than alphabetical characters.
You should not perform a transformation of variables early if the transformation aims to encode the data in a specific format (eg HTML output) because it could made the use of the objects in other contexts (eg: DB queries) harder to do.
just before using the variable (late control). Eg: SQL sanitization prior making a SQL query, or HTML encoding prior printing the values.
I think, in regards of your code snippet, that the latter should do.
Checkmarx is alerting on the loop line, but the issue is not really there. It lies in the value= statements that follow, the sanitization should be made here.
Tip for other readers: do not forget that any sanitization process should be made server side. If made client-side, it is mostly cosmetical.
I am developing an MVC web app using spring framework.
At some point I have a jsp that is listing study case objects as sown below
<tbody>
<c:forEach items="${studycases}" var="studycase">
<tr>
<td>
<a href='<spring:url value="/studycase/${studycase.study_case_number}.html"/>'>
${studycase.study_case_number}
</a>
</td>
<td>
${studycase.dateOFHospitalAdmission}
</td>
<td>
${studycase.dateOfWardAdmission}
</td>
<td>
${studycase.dateOfWardDischarge}
</td>
</tr>
</c:forEach>
</tbody>
as you can see there is a spring:url that is directing to a jsp with details about the spesific study case, that is being handled by the below controller :
#RequestMapping("/studycase/{studyCaseNumber}")
public String detail(Model model, #PathVariable String studyCaseNumber)
{
model.addAttribute("studyCase", studyCaseService.findOne(studyCaseNumber)) ;
model.addAttribute("measurements", measurementService.findAllOfThem(studyCaseNumber)) ;
return "study-case-detail" ;
}
The problem is that as the study cases listed in the first jsp could be thousands I will need to make it possible for the user to enter the study_case_number of a study case in a input field and get the details of the study case having the study case number inputed . So what I am doing is this:
<form action="<spring:url value="/studycase/study-case-detail2"/>" method="GET">
Study Case Number : <input type="text" name="studyCaseNumber">
<br/>
<input type="submit" value="Submit" />
</form>
That is being handled by an other controller and directs to an other jsp with more or less the same structure and data :
#RequestMapping("/studycase/study-case-detail2")
public String detail2(Model model, #RequestParam("studyCaseNumber") String std)
{
model.addAttribute("measurements", measurementService.findAllOfThem(std)) ;
return "study-case-detail2" ;
}
My question is this : Is this a good way to go having different controllers and different views even if they are presenting more or less the same thing ? What are other alternatives ??
Is there any source that you can direct me to containing best practices catalogue or guide on how to handle similar situations ??
Looking at your code, your controllers are not doing exactly the same thing (e.g. different model attributes, and they return different views).
Other than that, in general, it's not the best practice to do what you're doing as it somewhat in conflict with "Do Not Repeat Yourself" principle (also known as DRY principle).
One suggestion would be to use javascript to do redirect on id from input box rather than a form.
It seems you're using Spring Data too. If that's the case then one additional (not exactly related) suggestion to DRY up your code would be to use Spring Data's domain class converters to avoid calls studyCaseService.findOne(studyCaseNumber) in your StudyCase related controllers.
With domain class converters in place, you could then write controller method like this:
public String detail(Model model, #PathVariable("studyCaseNumber") StudyCase studyCase)
and avoid call to repository's findOne method as the converters would automatically convert ID to entity.
Take a look at DomainClassConverter in "Basic Web Support" section of Spring Data manual:
http://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
I have a JSTL loop where I'm trying to check to see if a given variable is empty or not with a dynamic variable name. When I use c:set with page scope, the variable is not accessible to the if statement. However, when I set it using <% pageCotnext.setAttribute(...); %>, the variable is available.
<%
pageContext.setAttribute("alphaParA", "test");
pageContext.setAttribute("alphaParF", "test");
int i = 0;
%>
<ul class="alphadex_links">
<c:forEach var="i" begin="0" end="25" step="1" varStatus="status">
<c:set var="currentLetter" scope="page">&#${i+65}</c:set>
<c:set var="currentPar" scope="page">alphaPar${currentLetter}</c:set>
<% pageContext.setAttribute("currentPar", "alphaPar" + (char)('A' + i++)); %>
<li>
<c:choose>
<c:when test="${not empty pageScope[currentPar]}">
The test is always fails when I remove the pageContext.setAttribute block, however it succeeds for A and F as it should when the block is in. I'm very confused and can't find help anywhere.
It fails because HTML doesn't run at the moment JSTL runs. You're effectively passing a Java String A to it instead of the desired character A which would be represented as such based on the HTML entity A when the HTML is retrieved and parsed by the webbrowser after Java/JSP/JSTL has done its job. Please note that your HTML entity is missing the closing semicolon, but this isn't the cause of your concrete problem.
As to the concrete functional requirement, sorry, you're out of luck with EL. It doesn't support char. Your best bet is to deal with strings like this:
<c:forEach items="${fn:split('A,B,C,D,E,F,G,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z', ',')}" var="currentLetter">
<c:set var="currentPar" value="alphaPar${currentLetter}" />
${pageScope[currentPar]}
</c:forEach>
If necessary, just autogenerate the letters as String[] in Java end and set it as application attribute.
I have a couple of ArrayLists with variable length and sometimes null. This ArrayList contains a bunch of objects.
The table should have columns based on (some) attributes of the object. And the table should be displayed on a jsp.
I have two ideas, one is to use a JSTL tag the other is to use JavaScript. And library suggestions are welcome.
JSTL is the standard, preferred way (unless you need to load it via ajax, for example)
<table>
<tr><td>Foo header</td><td>Bar header</td></tr>
<c:forEach items="${yourRequestScopedArrayList}" var="obj">
<tr>
<td>${obj.foo}</td>
<td>${obj.bar}</td>
</tr>
</c:forEach>
</table>
JSTL is better,
Javascript you should avoid as much as possible ,
I am not sure how you are going to render datatable using java script and Collection
How to use jstl with collection that has been demonstrated by Bozho in the same thread.
Javascript doesn't have access to the Java objects that live (I presume) on the server. The server code can make the ArrayLists available to the JSP which can then loop over them with a JSTL forEach tag.
How you make the ArrayLists "available" depends on the framework you're using, but the plain servlet way is just setting an attribute from the doPost method.
request.setAttribute("list1", arrayList1);
The loop would be something like
<table>
<tr><th>Column 1</th> <th>Column 2</th> <th>Column 3</th></tr>
<c:forEach var="row" items="${list1}">
<tr><td>${row.col1data}</td> <td>${row.col2data}</td> <td>${row.col3data}</td></tr>
</c:forEach>
</table>
I've been told that the use of scriptlets (<%= ... %>) in my JSP pages isn't such a great idea.
Can someone with a bit more java/jsp experience please give me some pointers as to how to change this code so its more 'best practice', whatever that may be?
This JSP is actually my sitemesh main decorator page. Basically my web design has a tab strip and a submenu, and i wish to somehow highlight the current tab and show the correct submenu by looking at the current request URI.
<%# taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<html>
<head>
<title>My Events - <decorator:title /></title>
<link href="<%= request.getContextPath() %>/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="tabs">
<a
<%= request.getRequestURI().contains("/events/") ? "class='selected'" : "" %>
href='<%= request.getContextPath() %>/events/Listing.action'>Events</a>
<a
<%= request.getRequestURI().contains("/people/") ? "class='selected'" : "" %>
href='<%= request.getContextPath() %>/people/Listing.action'>People</a>
</div>
<div class="submenu">
<% if(request.getRequestURI().contains("/events/")) { %>
List of Events
|New Event
<% } %>
<% if(request.getRequestURI().contains("/people/")) { %>
List of People
|New Person
<% } %>
</div>
<div class="body">
<decorator:body />
</div>
</body>
</html>
Thanks all
I think it helps more if you see with your own eyes that it can actually be done entirely without scriptlets.
Here's a 1 on 1 rewrite with help of among others JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) core and functions taglib:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<html>
<head>
<title>My Events - <decorator:title /></title>
<link href="${pageContext.request.contextPath}/assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="tabs">
<a
${fn:contains(pageContext.request.requestURI, '/events/') ? 'class="selected"' : ''}
href="${pageContext.request.contextPath}/events/Listing.action">Events</a>
<a
${fn:contains(pageContext.request.requestURI, '/people/') ? 'class="selected"' : ''}
href="${pageContext.request.contextPath}/people/Listing.action">People</a>
</div>
<div class="submenu">
<c:if test="${fn:contains(pageContext.request.requestURI, '/events/')}">
List of Events
|New Event
</c:if>
<c:if test="${fn:contains(pageContext.request.requestURI, '/people/')}">
List of People
|New Person
</c:if>
</div>
Here's a more optimized rewrite, note that I used c:set to "cache" expression results for reuse and that I use HTML <base> tag to avoid putting the context path in every link (just make all relative URL's in your webpage relative to it --without the leading slash!):
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<c:set var="isEvents" value="${fn:contains(pageContext.request.requestURI, '/events/')}" />
<c:set var="isPeople" value="${fn:contains(pageContext.request.requestURI, '/people/')}" />
<html>
<head>
<title>My Events - <decorator:title /></title>
<base href="${pageContext.request.contextPath}">
<link href="assets/styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="tabs">
<a ${isEvents ? 'class="selected"' : ''} href="events/Listing.action">Events</a>
<a ${isPeople ? 'class="selected"' : ''} href="people/Listing.action">People</a>
</div>
<div class="submenu">
<c:if test="${isEvents}">
List of Events|New Event
</c:if>
<c:if test="${isPeople}">
List of People|New Person
</c:if>
</div>
It can actually be optimized more if you collect all those "hardcoded" values like events and people and link texts in a Map in the application scope and use under each the JSTL <c:forEach> to display the tabs.
As to your actual question, you can disable scriptlets (and get runtime errors about using it) by adding the following entry in webapp's web.xml. It may help to spot overseen scriptlets.
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
To learn more about EL, check the Java EE tutorial part II chapter 5. Implicit EL objects, such as ${pageContext} are described here. To learn more about JSTL, check the Java EE tutorial part II chapter 7. Note that JSTL and EL are two separate things. JSTL is a standard taglib and EL just enables to access backend data programmatically. Although it is normally used in taglibs like JSTL, it can also be used standalone in template text.
As an aside, is <%= request.getContextPath() %> an acceptable use of scriptlets that isn't frowned on so much?
This may be an unpopular opinion, but if all you do are simple conditionals and text insertions, I cannot find much fault in the use of scriptlets. (Note the if)
I'd probably use JSTL and the expression language, but mostly because it can be less typing, and IDE support may be better (but a good JSP IDE can also find missing closing brackets and stuff like that).
But fundamentally (as in "keep logic out of templates") I fail to see any difference between
<% if(request.getRequestURI().contains("/events/")) { %>
and
${fn:contains(pageContext.request.requestURI, '/events/')
Scriptlets aren't the worst thing in the world. An important consideration is to think about who is going to be maintaining the code. If its web designers who don't have much Java experience, you are probably better off going with tag libraries. However, if Java developers are doing the maintainance, it may be easier on them to go with scriptlets.
If you end up using a tag library and JSTL, you are expecting the maintainer to also learn the tag library and know JSTL. Some developers will be fine with this as it is a skill they want or already have, but for some developers who only have to deal with JSPs every few months or so, it can be lot less painful to work with clearly written scriptlets written in nice, familiar Java.
This isn't a direct answer to your question (and there are already several good ones, so I won't try to add to it), but you did mention:
Can someone with a bit more java/jsp
experience please give me some
pointers as to how to change this code
so its more 'best practice', whatever
that may be?
In my opinion, best practice, with regards to JSP, is that it should be used strictly as a templating engine, and no more (i.e., no business logic in there). Using JSTL, as many pointed out, definitely helps you get there, but even with JSTL, it's easy to do to much in a JSP.
I personally like to follow the rules laid out in Enforcing Strict Model-View Separation in Templating Engines by the Terence Parr when developing in JSP. The paper mentions the purpose of templating engines (separating model and view), and characteristics of a good templating engine. It takes a good look at JSP and points out ways it's not a good templating engine. Not surprisingly, JSP is basically too powerful and allows developers to do too much. I strongly recommend reading this paper, and it'll help you restrict yourself to the "good" parts of JSP.
If you read only one section in that paper, read chapter 7, which includes the following rules:
the view cannot modify the model either by directly altering model
data objects or by invoking methods on
the model that cause side-effects.
That is, a template can access data
from the model and invoke methods, but
such references must be side-effect
free. This rule arises partially
because data references must be
order-insensitive. See Section 7.1.
the view cannot perform computations upon dependent data
values because the computations may
change in the future and they should
be neatly encapsulated in the model in
any case. For example, the view cannot
compute book sale prices as
“$price*.90”. To be independent of the
model, the view cannot make
assumptions about the meaning of data.
the view cannot compare dependent data values, but can test the
properties of data such as
presence/absence or length of a
multi-valued data value. Tests like
$bloodPressure<120 must be moved to
the model as doctors like to keep
reduc- ing the max systolic pressure
on us. Expressions in the view must be
replaced with a test for presence of a
value simulat- ing a boolean such as
$bloodPressureOk!=null Template output
can be conditional on model data and
com- putations, the conditional just
has to be computed in the model. Even
simple tests that make negative values
red should be computed in the model;
the right level of abstraction is usu-
ally something higher level such as
“department x is losing money.”
the view cannot make data type assumptions. Some type assumptions are
obvious when the view assumes a data
value is a date, for example, but more
subtle type assumptions ap- pear: If a
template assumes $userID is an
integer, the pro- grammer cannot
change this value to be a non-numeric
in the model without breaking the
template. This rule forbids array
indexing such as colorCode[$topic] and
$name[$ID] The view further cannot
call methods with arguments be- cause
(statically or dynamically) there is
an assumed argu- ment type, unless one
could guarantee the model method
merely treated them as objects.
Besides graphics designers are not
programmers; expecting them to invoke
methods and know what to pass is
unrealistic.
data from the model must not contain display or layout information.
The model cannot pass any display
informa- tion to the view disguised as
data values. This includes not passing
the name of a template to apply to
other data values.
Incidentally, Terence has created his own templating engine called String Template which supposedly does a really good job of enforcing these rules. I have no personal experience with it, but would love to check it out on my next project.
You may want to start by using tag libraries. You can use the standard tag library JSTL to do most of the common things that you need scriplets for. There are many other richer tag libraries that are used like in the struts2 framework or from apache.
e.g.
<c:if test="${your condition}">
Your Content
</c:if>
would replace your if statements.
The preferred alternative to scriptlets is the JSTL expression language; here's a good overview. You'll need to add the taglib like so:
<%# taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c' %>
As an example, JSTL provides a bunch of implicit objects that give you the stuff you need; the one you want is pageContext.request.
So you can replace <%request.getRequestURI%> with ${pageContext.request.requestURI}.
You can do conditionals using <c:if> tags.
You'll need to use some web framework. Or at least some convenient taglib. Or a templating enginge like FreeMarker.
Ad frameworks:
If you like JSP way of coding, then I'd suggest Struts 2.
<s:if test="%{false}">
<div>Will Not Be Executed</div>
</s:if>
<s:elseif test="%{true}">
<div>Will Be Executed</div>
</s:elseif>
<s:else>
<div>Will Not Be Executed</div>
</s:else>
Then there's component-oriented JSF.
If you like OOP and coding everything in Java, try Apache Wicket (my favorite) or Google Web Toolkit.