Setting parent jsp variables in child jsp - java

I have a parent jsp a.jsp which includes another jsp b.jsp. I am calculating some values in b.jsp which needs to be used in parent jsp a.jsp , which will pass this calculated value to another jsp say c.jsp. How can I evaluate value in child jsp and pass it to parent jsp before that page completely loads?

How are you including the "child" jar inside the parent? static or dynamic import?
if you have
<%# include file="myFile.jsp" %>
change it by
<jsp:include file="myFile.jsp" />
then in the parent set a property in the request (not in the session, that would be "dirtier"):
<% request.setAttribute("attrName", myValue) %>
finally, in the "child" jsp:
<% myValue = (MyValueType)request.getAttribute("attrName") %>

If you need to pass an attribute between including and included jsp (and viceversa)you should use the page context, which is the more short context (from lifecycle perspective)

You can set variables in the request in b.jsp, and use them in parent.jsp. But you can only use them in the parent jsp after the <jsp:include> tag. Remember that this is all evaluated on the server side, so when you say "before that page completely loads," you can be guaranteed that the server has evaluated it before the browser has loaded it. If you mean that you want to delay evaluation on the server until some code below it is evaluated, that's not going to be possible. At least not like this.
b.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="myVar" scope="request" value="Hello"/>
parent.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<jsp:include page="b.jsp"></jsp:include>
<span>
The value is ${requestScope.myVar}.
</span>

You could you session scope to accomplish this.
(b.jsp)
session.setAttribute("value",value);
(c.jsp)
session.getAttribute("value");
However, I would recommend doing some major restructuring instead. In your example, the value of your data depends on the order of the elements on the page. If you ever need to re-arrange things (for instance, moving the b.jsp include after the c.jsp include), you risk breaking the business logic.
A good pattern for web development is a model-view-controller pattern. The "controller" determines what page should be displayed, the "model" calculates all the data and makes it available, and the "view" does the display and formatting.
I would recommend reviewing this article, which is helpful for understanding why MVC is a valuable approach:
http://www.javaranch.com/journal/200603/Journal200603.jsp#a5
Edit: As other users have mentioned, request scope would be cleaner than session scope. However, I still recommend determining the value first before writing any display content.

Related

Hybris: How to pass class as a parameter to cms:component?

I've started to learn Hybris and I want to find out how to pass the class as a parameter to a custom CMS Component (for the component's root element).
Let's suppose that in a jsp file named customNavigationComponent.jsp I have this piece of code:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="cms" uri="http://hybris.com/tld/cmstags"%>
<c:forEach items="${navigation.entries}" var="navigationLink">
<div class="custom-component-wrapper">
<cms:component component="${navigationLink.item}"/>
</div>
</c:forEach>
And the custom component looks like this:
<a href="${component.url}">
<div>${component.linkText}</div>
</a>
I would like to understand what I need to do to pass the class navigation-link as a parameter, like this:
<cms:component component="${navigationLink.item}" class="navigation-link"/>
so that the rendered result will be similar to:
<a href="stackoverflow.com" class="navigation-link">
<div>Lorem Ipsum</div>
</a>
There is no attribute called, class in cms:component and therefore the following statement will not work:
<cms:component component="${navigationLink.item}" class="navigation-link"/>
Please check https://help.sap.com/doc/a4265d5ea8314eb2929e6cf6fb8e35a5/1811/en-US/de/hybris/platform/cms2lib/cmstags/CMSComponentTag.html
In order to understand it better, you can compare it with c:forEach. At https://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/c/forEach.html, you will find a list of attributes available with c:forEach and if you want to dig deeper, you can further check https://tomcat.apache.org/taglibs/standard/apidocs/javax/servlet/jsp/jstl/core/LoopTagSupport.html
If you want to use your statement, you will need to create a custom tag.

Printing an array/collection of javabeans in JSP

Is there a standard way of printing an array/collection elements of javabeans in JSP? All I know is the <jsp:getProperty> tag which can't do this. I know it can be done using custom tags, but it being such an essential requirement should be provided by JSP.
Also, I have read that using setAttribute() method of PageContext, ServletContext etc we can in a Servlet get the bean and work on it, but it's giving me null value.
pageContext.getAttribute("beanPropertyVariable") //set in page scope
application.getAttribute("beanPropertyVariable") //set in application scope
How can I achieve this?
The standard way is using JSTL <c:forEach>.
Assuming that ${beans} represents the collection of javabeans, here's an example:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<c:forEach items="${beans}" var="bean">
${bean.property1}<br/>
${bean.property2}<br/>
${bean.property3}<br/>
</c:forEach>
That's also the simplest way you can get.
See also:
Our JSTL wiki page
Our Javabeans wiki page
you can use JSTL c:foreach tag like below
<c:forEach items="${list}" var="var">
${var}<br/>
</c:forEach>

How to write content before and after the output of a JSP

I have JPSs that represent Components. I want to have these component JSPs write some HTML before and after the contents of the JSP is executed.
component.jsp
<#page session="false">
<%= "hello " + "world" %>
when this JSP/servlet is rendered, I want it to render:
<div class="component">
hello world
</div>
I want to be able to create various "wrappers", and depending on the JSP, include wrap the contents of the JSP with the correct content. If I want to change/augment the wrapper down the road, I want to only do it in one place (Could be 100s of components).
Can i do something with <#page extends="..."> possibly?
Thanks
What do you want is named: tag files. Introduced on JSP 2.0
With this approach you can write JSP tags using jsp, therefore you need to create a folder named WEB-INF/tags, and create a 'normal' jsp within this folder.
The tag that you want to create needs to have the following start instruction:
<%#tag description="tag description" %> in order to indicate this is a tag.
To use it you will need to reference the tags you want to use with the following instruction: <%# taglib tagdir="/WEB-INF/tags" prefix="custom"%>
So, you can do something like:
WEB-INF/tags/myTag.tag
<%#tag description="hello tag" %>
<%#attribute name="name" required="false" type="java.lang.String"%>
<html><head></head><body>
<h1>Hello <%=name%></h1>
<jsp:doBody />
</body>
index.jsp
<%# taglib tagdir="/WEB-INF/tags" prefix="custom"%>
<custom:myTag name="My Name">this is the content</custom:myTag>
The result will be a page printing
<html><head></head><body>
<h1>Hello My Name</h1>
this is the content
</body>
This is a terrible idea. JSPs with scriptlets are 1998 technology. No one writes these anymore.
If you must write JSPs, you're better off using JSTL and something like SiteMesh or Tiles to composite pages.
An even better idea would be to start moving towards something that might allow you to easily run a mobile solution alongside your web app. Services and templates would be my preference over JSPs.

JSP: Use information from one page to another

I currently have a JSP page with a Form for the user to enter their name, but what I want is to get the user forwarded to a different JSP page after form submission and to carry on their name to be used.
I don't want to use JSTL EL just simple JSP uses.
I was thinking of using a bean storing the detail in a session but how would it work.
Thanks.
You'd have JSP enter the info into a form and POST it to a servlet. The servlet would validate the form input, instantiate the bean, add it to session, and redirect the response to the second JSP to display.
You need a servlet in-between. JSPs using JSTL are for display; using the servlet this way is called MVC 2. Another way to think of it is the front controller pattern, where a single servlet handles all mapped requests and simply routes them to controllers/handlers.
duffymo you have the best idea but here is a quick solution by just passing things through the JSP.
Here is the JSP with the form
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Simple jsp page</title></head>
<body><form name="test" action="./stackTest2.jsp" method="POST">
Text Field<input type="text" name="textField">
<input type="submit">
</form> </body>
</html>
and then the second page looks like this:
<html>
<head><title>Simple jsp page</title></head>
<body><%=request.getParameter("textField")%></body>
</html>
And then put information in a hidden field, you can get information by using the request.getParameter method. This just prints out what was in the form, but using the same idea for inputting it in to the hidden field in a form. I recommend this as all my experience with sessions have ended in a failure. I STRONGLY DO NOT Recommend this method, MVC is a much better way of developing things.
Dean

How to avoid using scriptlets in my JSP page?

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.

Categories