Good day!
I encountered the following error upon running my JSP program.
java.lang.IllegalStateException: PWC3991: getOutputStream() has already been called for this response
It seems like the html file inside my JSP doesn't work.
My code is as follows:
<%#page import = "java.util.*"%>
<%#page import = "javax.servlet.*"%>
<%#page import = "javax.servlet.http.*"%>
<%#page import= "session.*" %>
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<%
Item item = (Item) request.getAttribute("invenItem");
if (item != null) {
out.println("<html><title>Inventory Item</title>");
out.println("<body><h1>Inventory Item Details:</h1>");
out.println("Stock ID : " + item.getStockID() + "<br/>");
out.println("Name : " + item.getItemName() + "<br/>");
out.println("Unit Price: " + item.getUnitPrice() + "<br/>");
out.println("On Stock : " + item.getOnStock() + "<br/>");
out.println("</body>");
out.println("</html>");
} else {
RequestDispatcher rd = request.getRequestDispatcher("DataForm.html"); //NOT WORKING
rd.include(request, response);
out.println("<br>Item not found...<br>");
rd = request.getRequestDispatcher("ItemEntry.html"); //NOT WORKING
rd.include(request, response);
}
%>
</body>
</html>
My html Files are located inside the folder WEB-INF. How can I make it work? DO i need to import it also? Thank you.
Don't use scriptlets (those <% %> things). JSP is a template technology for HTML. You don't need all those nasty out.println() things for HTML. Just write HTML plain in JSP.
So, instead of
<%
out.println("<html><title>Inventory Item</title>");
%>
just do
<html><title>Inventory Item</title>
(note that this results in invalid HTML, there should be only one <html> tag in a HTML page and only one <title> in the <head>, but that's a different problem, the w3 HTML validator should give a lot of hints and answers, also get yourself through some HTML tutorials)
JSP offers EL (Expression Language, those ${ } things) to access backend data, i.e. the data which is present as attribute in page, request, session and application scopes. It can be accessed using the attribute name.
So, instead of
<%
Item item = (Item) request.getAttribute("invenItem");
%>
use
${invenItem}
and instead of
<%
out.println("Stock ID : " + item.getStockID() + "<br/>");
%>
use
Stock ID: ${invenItem.stockID}<br/>
JSP also offers taglibs like JSTL to control the page flow and output.
So, instead of
<%
if (item != null) {
} else {
}
%>
use
<c:choose>
<c:when test="${invenItem != null}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
JSP also offers <jsp:include> tag to include page fragments.
So, instead of
<%
RequestDispatcher rd = request.getRequestDispatcher("DataForm.html"); //NOT WORKING
rd.include(request, response);
%>
use
<jsp:include page="/WEB-INF/DataForm.jsp" />
(and rename it to .jsp)
And the exception will disappear.
See also:
JSP tag info page
How to avoid Java code in JSP files?
Java web development, what skills do I need?
Unrelated to the concrete problem, almost all of the links in this answer was already (in)directly given to you in your previous questions. Take them serious. To become a great programmer (as you ever stated in a question/comment), take some time to get yourself through those links (and the links in the links).
Firstly, try to avoid putting code onto your JSP page - it violates the MVC/separation of concerns paradigm that is a central part of JSP.
Second, plain old JSP's getting a bit old - using JSF/facelets/etc is recommended these days.
As for your actual problem, I'm not totally familiar with the technique you're employing, but the exception basically means that you've tried to send content after the latest point at which your able to (generally, after sending headers). In this case, I think what's happening is that you've already started sending the current page when you ask it to send a different page.
Simplest fix I can think of: rather than trying a conditional include based on results, just redirect to a different page.
The error indicates that the error lines of code cannot be called once something has been printed out to the output stream in jsp (including even the doctype declaration)
So you can try to put those pieces of code at the top of your page.
You can not use
out.print() and Requestdispatcher simultaneously....
It means after execution of out.print() there should not be any execution of statement with requestdispatcher.forward()....
So remove out.println() form else block.
Related
This question already has answers here:
Difference between JspWriter and PrintWriter in Java EE?
(2 answers)
Closed 6 years ago.
I am getting split output from my JSP page, with writer.write() output first and second the JSP with tags omittted.
I have the following simple JSP page
<%# page import="com.AAA.SiteTemplate.RenderPageInterface" %>
<%# page import="java.io.Writer" %>
<%# page import="java.io.IOException" %>
<%# page import="com.NatureRelaxation.SiteTemplate.RenderPageInterfaceNull" %><%--
Created by IntelliJ IDEA.
User:
--%>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<%
RenderPageInterface obj = (RenderPageInterface) request.getAttribute("renderPageInterface");
if (obj == null){
obj = new RenderPageInterfaceNull();
}
%>
<title><% response.getWriter().write(obj.getTitle()); %></title>
<style type="text/css">
</style>
</head>
<body>
<%
obj.renderHTML(response.getWriter());
%>
</body>
</html>
and I include it via this small function:
public static void doRequest(HttpServletRequest req, HttpServletResponse res, RenderPageInterface renderPageInterface) throws ServletException, IOException{
req.setAttribute("renderPageInterface", renderPageInterface);
RequestDispatcher rd = req.getRequestDispatcher("/WEB-INF/templates/header.jsp");
rd.include(req, res);
}
The response that I am getting now is
My page titleMypagebody....
<html>
<head>
<title></title>
etc. There are 4 newlines in the middle. I'm thinking it must be a compiler error, but clearing caches (IntelliJ) and restarting, redeploying to Tomcat 8 doesn't fix it. All worked as normal until server was restarted, but nothing fixes it now. I even run the debugger on the JSP and all goes in order.
Update:
It runs fine without this tag "<% response.getWriter().write(obj.getTitle()); %>", but when the tag is there, both the body and the title get written at the top and the template at the bottom. getTitle() returns a String.
I figured it out fast enough, but it was quite tricky. "response.getWriter()" and JSP's "out" variable (which I did not know about), are not the same thing.
It is by coincidence that my code previously worked.
I also had to include jsp.api.jar before I could use the "out" (JSPWriter) variable.
Relevant info here:
Difference between JspWriter and PrintWriter in Java EE?
what is difference between JspWriter and PrintWriter?
In my JSP page,I use <%=TITLE %> to show the page title, sometimes it is ok.But sometimes the page show that can not cpmplie the code <%=TITLE %>.
So I change the code to ${TITLE},and it is OK.What is different between <%=TITLE %> and ${TITLE} in jsp?
Here is my page code:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<base href="<%=basePath%>">
<title><%=TITLE %></title>
<meta name="description" content="${DESCRIPTION}">
<meta name="keyword" content="${KEYWORD}">
</head>
I define them in the controller:
ModelAndView mv = this.getModelAndView();
mv.addObject("DESCRIPTION","MYDESCRIPTION"));
mv.addObject("KEYWORD","MYKEYWORD");
mv.addObject("TITLE","MYTITLE");
return mv;
Answer according to context of your Question
What is different between “<%=TITLE %> ” and “${TITLE} ” in jsp?
Since most of the times we print dynamic data in JSP page using out.print() method, there is a shortcut to do this through JSP Expressions. JSP Expression starts with <%= and ends with %>.
<% out.print(TITLE); %>
above statement is called scriptlet can be written using JSP Expression as
<%= TITLE %>
We can use scriptlets and JSP expressions to retrieve attributes and parameters in JSP with java code and use it for view purpose. But for web designers, java code is hard to understand and that’s why JSP Specs 2.0 introduced Expression Language (EL) through which we can get attributes and parameters easily using HTML like tags.
Expression language syntax is
${TITLE}
and we can use EL implicit objects and EL operators to retrieve the attributes from different scopes and use them in JSP page.
UPDATE
According to your controller related query
I say to write like this
<title><%=request.getAttribute("TITLE"); %></title>
because it's stored as a request attribute.
NOTE
Scriptlets are discouraged since JSP 2.0 which was released almost a decade(!) ago. So Please use Expression Language (EL).
I've read most of the online resources for building a simple "Hello World" app using Java and Struts 2. I understand the simple stuff. My problem is that I'm trying to expand that learning and build a large scale app, and I just don't see how to connect the dots.
Scenario:
I've got three views to begin with: Home.jsp, MyAccount.jsp, Contact.jsp. Each has the following HTML:
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<%#taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="js/common.js"></script>
...
</head>
<body>
<!-- If logged in, says "hello <s:property name="username">"
Else displays link to .show() #loginPane -->
<div id="accountHeader">...</div>
<!-- Displays <s:textfield> tags and <s:submit> tag to accept username and password -->
<div id="loginPane" style="display: none">...</div>
<header>...</header>
<nav>...</nav>
<!-- Displays view-specific content that includes Struts 2 tags -->
<div id="content">...</div>
<footer>...</footer>
</body>
</html>
So, obviously there is a lot of code common to each view (anything not in #content div).
How do I architect these views for code reuse?
What I've tried:
Placing common code in common.js and using jQuery .html() calls to populate <div>s. [Doesn't work because jQuery cannot generate code with <s:> tags.]
Using only one .jsp view file and placing view-specific code in common.js to be generated with jQuery .html() calls. [Doesn't work for the same reason -- jQuery cannot generate code with <s:> tags.]
Placing all view components in .jspf files and loading each with jQuery .load() calls from common.js. [Doesn't work -- I'm guessing the .jspf files need the Struts 2 <%taglib ...%> included in each, but jQuery .load() treats the <%taglib ...%> as text to be displayed in the <div>... and also fails to properly generate the <s:> tags.]
What is the proper way to do this? How do I architect my view(s) for code reuse?
My apologies if this isn't the proper forum to ask for architecture help, but I'm really struggling here... Perhaps point me to a more appropriate forum or an online tutorial that addresses this type of architecture?
Thanks in advance!
I've used several methods to accomplish this type of re-use of code including Tiles and tooling around with Sitemesh and other template frameworks. What I've found is that, much as Steven Benitez, in the end I preferred to use JSP taglibs, native Struts2 taglibs, and JSTL to essentially build out my own templating routines. The main reason I prefer this is that there tends to be less overhead and it's been a lot easier to maintain and extend in the long run.
Generally What I do is define my base template, index.jsp for example, and then in each independent Struts controller class I will define what page fragment is used. I try to split my controllers up in such a way that each page or function is handled by a single controller and I implement the Preparable interface. This way I can set a parameter for the page to reference. Sometimes I set it as a variable in the controller class, sometimes a sessions variable depending on what type of stating I need for the application.
Once I have a variable with the page to reference, I can just use a JSTL import or Struts include tag to load the page fragment.
The controller class would look something like this:
#Results({
#Result(name = "success", location = "/WEB-INF/content/index.jsp")
})
public class IndexController extends RestActionSupport implements Preparable{
private String page;
private String pageTitle;
#Override
public void prepare() throws Exception {
page = "home";
pageTitle= "My Home Page";
}
...
}
And then the JSP would look something like this:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title> ${pageTitle}</title>
</head>
<body>
<c:import url="${page}.jsp" />
</body>
</html>
EDIT: Fragment page example:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%# taglib prefix="s" uri="/struts-tags"%>
<div>
<h1>Welcome Home!</h1>
</div>
<script type='text/javascript'>
$(document).ready(function() {
// page specific scripting if needed
);
</script>
You can encapsulate common template code in JSP tag files, as explained in this answer or you can also use decorator frameworks such as Tiles or SiteMesh to do this.
Personally, I prefer JSP tag files. Do not attempt to write out HTML with jQuery or to put all of your code into a single JSP.
System: Mac OSX
I have set up nutch so that it crawls and indexes my site. It also returns search results. My problem is that I want to customise the Nutch index.jsp and search.jsp pages to fit with my site. Ive read up and on jsp and it says its just a matter of putting in the html tags and then using <% %> to enclose the Java scriplets you want. For some reason nothing changes when i edit the files (index and search)
Here is what the original file displays:
<%# page
session="false"
import="java.io.*"
import="java.util.*"
%><%
String language =
ResourceBundle.getBundle("org.nutch.jsp.search", request.getLocale())
.getLocale().getLanguage();
String requestURI = HttpUtils.getRequestURL(request).toString();
String base = requestURI.substring(0, requestURI.lastIndexOf('/'));
response.sendRedirect(language + "/");
%>
Here is my edited version with sum gibberish test added to test it:
<html>
<head>
</head>
<body>
gigigyigig
<%# page
session="false"
import="java.io.*"
import="java.util.*"
%><%
String language =
ResourceBundle.getBundle("org.nutch.jsp.search", request.getLocale())
.getLocale().getLanguage();
String requestURI = HttpUtils.getRequestURL(request).toString();
String base = requestURI.substring(0, requestURI.lastIndexOf('/'));
response.sendRedirect(language + "/");
%>
ghjgjkbkhb
hjgjvjhvj
</body>
</html>
Nothing has changed tho and the nutch homepage/index.jsp still displays the same as original. This is my first encounter with JSP so its just what ive picked up so far. Can anyone tell me why the page isnt displaying the html with gibberish typed??
I have my search totaly modified. However I have my <html>... tags after the second scriptlet ie <% %> not <%# page.
As for your index.jsp modified it has a redirection response.sendRedirect and therefore it looks normal to me that you see nothing.
Also I presume you took care of loading the jsp pages at the right place under the tomcat/webapps tree, because the standard ant make file doesn't. So I ended up adding some Ant task to patch my test website.
Beware if you are going to change the .jar files you also need to restart Tomcat.
How can I read/access a JSP variable from JavaScript?
alert("${variable}");
or
alert("<%=var%>");
or full example
<html>
<head>
<script language="javascript">
function access(){
<% String str="Hello World"; %>
var s="<%=str%>";
alert(s);
}
</script>
</head>
<body onload="access()">
</body>
</html>
Note: sanitize the input before rendering it, it may open whole lot of XSS possibilities
The cleanest way, as far as I know:
add your JSP variable to an HTML element's data-* attribute
then read this value via Javascript when required
My opinion regarding the current solutions on this SO page: reading "directly" JSP values using java scriplet inside actual javascript code is probably the most disgusting thing you could do. Makes me wanna puke. haha. Seriously, try to not do it.
The HTML part without JSP:
<body data-customvalueone="1st Interpreted Jsp Value" data-customvaluetwo="another Interpreted Jsp Value">
Here is your regular page main content
</body>
The HTML part when using JSP:
<body data-customvalueone="${beanName.attrName}" data-customvaluetwo="${beanName.scndAttrName}">
Here is your regular page main content
</body>
The javascript part (using jQuery for simplicity):
<script type="text/JavaScript" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
<script type="text/javascript">
jQuery(function(){
var valuePassedFromJSP = $("body").attr("data-customvalueone");
var anotherValuePassedFromJSP = $("body").attr("data-customvaluetwo");
alert(valuePassedFromJSP + " and " + anotherValuePassedFromJSP + " are the values passed from your JSP page");
});
</script>
And here is the jsFiddle to see this in action http://jsfiddle.net/6wEYw/2/
Resources:
HTML 5 data-* attribute: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes
Include javascript into html file Include JavaScript file in HTML won't work as <script .... />
CSS selectors (also usable when selecting via jQuery) https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors
Get an HTML element attribute via jQuery http://api.jquery.com/attr/
Assuming you are talking about JavaScript in an HTML document.
You can't do this directly since, as far as the JSP is concerned, it is outputting text, and as far as the page is concerned, it is just getting an HTML document.
You have to generate JavaScript code to instantiate the variable, taking care to escape any characters with special meaning in JS. If you just dump the data (as proposed by some other answers) you will find it falling over when the data contains new lines, quote characters and so on.
The simplest way to do this is to use a JSON library (there are a bunch listed at the bottom of http://json.org/ ) and then have the JSP output:
<script type="text/javascript">
var myObject = <%= the string output by the JSON library %>;
</script>
This will give you an object that you can access like:
myObject.someProperty
in the JS.
<% String s="Hi"; %>
var v ="<%=s%>";
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
<title>JSP Page</title>
<script>
$(document).ready(function(){
<% String name = "phuongmychi.github.io" ;%> // jsp vari
var name = "<%=name %>" // call var to js
$("#id").html(name); //output to html
});
</script>
</head>
<body>
<h1 id='id'>!</h1>
</body>
I know this is an older post, but I have a cleaner solution that I think will solve the XSS issues and keep it simple:
<script>
let myJSVariable = <%= "`" + myJavaVariable.replace("`", "\\`") + "`" %>;
</script>
This makes use of the JS template string's escape functionality and prevents the string from being executed by escaping any backticks contained within the value in Java.
You could easily abstract this out to a utility method for re-use:
public static String escapeStringToJS(String value) {
if (value == null) return "``";
return "`" + value.replace("`", "\\`") + "`";
}
and then in the JSP JS block:
<script>
let myJSVariable = <%= Util.escapeStringToJS(myJavaVariable) %>;
</script>
The result:
<script>
let myJSVariable = `~\`!##$%^&*()-_=+'"|]{[?/>.,<:;`;
</script>
Note: This doesn't take separation of concerns into consideration, but if you're just looking for a simple and quick solution, this may work.
Also, if you can think of any risks to this approach, please let me know.