The problem is: I have a page1.jsp which is submitted and forwarded to page2.jsp. The problem is that the forwarded output should be only the content in page2.jsp, instead of that is showing me content from page1.jsp and immediately the content from page2.jsp
I'm using requestDispatcher.forward(String) but i don know why is this happening
PS: I'm using JE 1.4
Well it seems you have got the method signature incorrect . As per the javaee 1.4 API:
public void forward(ServletRequest request,ServletResponse response)
throws ServletException,
java.io.IOException
Hence your code should be :
RequestDispatcher dispatcher = request.getRequestDispatcher("page2.jsp);
dispatcher.forward( request, response );
Better , you can use the <jsp:forward> standard action.
The JSP that contains the action stops processing, clears its buffer, and forwards the request to the target resource. Note that the calling JSP should not write anything to the response prior to the action.
Suggested Reading:
How to avoid Java Code in JSP-Files?
Related
I am just a beginner in Java Web and I am exploring the pure Servlets and JSPs (with no frameworks). I am trying to build up a simple CRUD and I got stuck in an error that makes no sense at all (at least to me!).
Objective
I wanna build a simple CRUD with several Servlets containing the logics and database operations (controller) and JSPs to display the pages (views). I have already successfully build up a CustomerIndexServlet (route: /customers), which returns the list of records and a button to CustomerNewServlet (route: /customers/new) which SHOULD return a JSP with the form to create new records.
Issue
Calling CustomerNewServlet leads to a Page Not Found (404) and GlassFish prints the message PWC6117: File "null" not found in the console. By debugging the code, the error occurs when forwarding the request through RequestDispatcher. I don't understand! If I try to access the JSP directly (at http://localhost:8080/MyApp/customerForm.jsp), it returns OK (200). I even printed the path of JSP before forwarding to make sure it is the one expected!
#WebServlet(name = "NewCustomer", urlPatterns = {"/customers/new"})
public class NewCustomerServlet extends HttpServlet {
#Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException {
System.out.println(request.getContextPath());
if (request.getSession().getAttribute("login") == null)
/*error*/ request.getRequestDispatcher(request.getContextPath()).forward(request, response);
else
/*error*/ request.getRequestDispatcher(request.getContextPath() + "/customerForm").forward(request, response);
}
}
And in server's console it is displayed:
Info: /MyApp
Server: PWC6117: File "null" not found
What am I doing wrong? Does it have something to do with the file locations and directories?
I figured out what happen and how redirection and forward deal with URI's... I'm gonna share the knowledge I've acquired:
response.sendRedirect(URL)
When using the sendRedirect() method, you are requesting the client to submit a new request to the passed URL. When using an absolute path, you have to concatenate the request.getContextPath() prefix to your URL, if you wanna target a resource within your application.
request.getRequestDispatcher(URL).forward(...)
When dispatching the request to another URL, it already uses application context. So using request.getContextPath() + "/customerForm.jsp" as target URL will only look for a resource in /AppName/AppName/customerForm.jsp. Then, omitting the getContextPath() call is enough to make my code work as expected.
I would like to know what happens to the html codes written inside the servlet?
What is the need of writing like this?
Sample code:
public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Using GET Method to Read Form Data";
out.println("<html>"<head><title>"Welcome"</title></head>\n" +
"<body><p>Welcome to servlet</p></body></html>");
}
The HTML code written in the servlet goes to the Client through the Container (or through web server talking with the Container) which is responsible to send a response back to the Client (browser) that, in turn, will render the HTML to the user.
Here you will find a nice explanation of what is going on behind the scenes: How do servlets work? Instantiation, sessions, shared variables and multithreading
An HTML page is nothing else than plain text following HTML syntax.
Hence, anything you give as a response to a HTTP request, being plain text following HTML syntax (like your String does), IS an HTML page, provided you tell the caller what is the content type of the response :
response.setContentType("text/html");
I am having problem with redirect in jsp , the page just remains and doesn't throw any error.
I am able to do redirect when I direct write the script in my login.jsp like
<%
String redirectURL = "/client/index.jsp";
response.sendRedirect(redirectURL);
%>
<t:login title="Client Login">
..........
</t:login>
But I am unable to do redirect when I split the file into three and include it. below is my implementation.
login.jsp
<%#include file="/include/checkhandler.jsp"%>
checkhandler.jsp - this is a script that will check for file in handler folder and include it when it is exist.
......
request.getRequestDispatcher(handler).include(request, response);
......
login_handler.jsp this is the file the dispatcher will include
String redirectURL = "/client/index.jsp";
response.sendRedirect(redirectURL);
out.println("hello world");
After I execute this script , the hello world displayed but it is still stay at the same page without any error.
You need to use RequestDispatcher#forward() instead. Change your checkhandler.jsp to
request.getRequestDispatcher(handler).forward(request, response);
A server-side include is prohibited to change the response status code which is what happens when you use sendRedirect(). Any such attempt is simply ignored by the container.
From the RequestDispatcher#include() docs:
The ServletResponse object has its path elements and parameters remain
unchanged from the caller's. The included servlet cannot change the
response status code or set headers; any attempt to make a change is
ignored.
This limitation is by design. The spec treats the web component being included as a guest i.e. it cannot direct the flow and any such attempts would be rightly ignored instead of throwing an exception to possibly allow an include for any servlet that you may have.
Only the hosting web component (the one doing an include) would be in complete control of the flow as well as what response headers are sent over to the client.
You have this in your code
out.println("hello world");
String redirectURL = "/client/index.jsp";
response.sendRedirect(redirectURL);
which will not work because you cannot redirect after writing to the response stream. The redirect is sent in the response header. The response body should not contain any html.
I am currently passing some ArrayList's from my servlet to my JSP page using the below code.
RequestDispatcher rd = null;
request.setAttribute("date",al);
request.setAttribute("bau",al1);
request.setAttribute("project",al2);
rd = request.getRequestDispatcher("ResourceChart.jsp");
rd.forward(request,response);
The problem is when I click refresh on the page, the same date is passed again and I end up with odd results. Should I be forwarding to the JSP page as well to avoid the servlet regenerating the variables and passing them?
Whats the best way to implement this?
You're apparently refreshing a POST request and ignoring/confirming the browser's builtin warning that the data would be resent. In that case, the doPost() method will indeed be re-executed with the previously submitted data which would only end up in duplicate entries in the DB.
The canonical approach to avoid the double submit on a refresh of a POST request is to send a redirect after POST request. A redirect implicitly creates a new GET request. Refreshing would then result in only the GET request being re-executed which is totally harmless.
To achieve that, replace all in the question shown lines of the doPost() by the following single line
response.sendRedirect(request.getContextPath() + "/ResourceChart");
(assuming that your servlet is mapped on an URL pattern of /ResourceChart)
and create a new doGet() method wherein you put all those removed lines back, along with the necessary logic to prepare the lists. The only change which you need to make is to put the JSP file in /WEB-INF folder to avoid endusers from being able to open it directly by entering/guessing its URL without calling the servlet's doGet() first.
request.getRequestDispatcher("/WEB-INF/ResourceChart.jsp").forward(request, response);
See also:
Our Servlets wiki page
I have a simple (Servlet, JSP, and JSTL) web app whose main functionality is displaying images retrieved from a back-end server. The controller servlet forwards the user to a JSP that in turn uses another Servlet to display the resulting image on that same JSP. Further down, the JSP has a line similar to:
<img src="<c:out value='${imageURL}'/>" alt="image view" border="1">
which invokes a GET request on the image-generating servlet causing it to generate the image.
My question is: how do I handle Exceptions thrown by this image-generating servlet?
I already have an error page defined (in web.xml) to handle ServletException within my web app but this doesn't work for this image-generating Servlet, and results in the following errors showing up in my Tomcat server logs:
SEVERE: Exception Processing ErrorPage[exceptionType=javax.servlet.ServletException, location=/WEB-INF/ExceptionPage.jsp]
java.lang.IllegalStateException: Cannot reset buffer after response has been committed
What's my recourse in this situation?
I'd like to be able to handle Exceptions thrown from this image-generating Servlet, and display some error on the main UI or forward the user to another error page.
You can't change the response to redirect to an error page while sending the response. It's already too late to change the entire response then. You can't ask those already sent bytes back from the client side. That's what the IllegalStateException stands for here. It's a point of no return.
Best what you can do is to just log the exception, or to rewrite the code so that it doesn't write any bit to the response (also not setting the response headers) while the business logic hasn't finished its task yet. Once you've determined that the business logic didn't throw any exception, then start writing (and thus indirectly also committing) the response. If the business logic has thrown an exception while the response isn't touched yet, then you can just safely throw it through so that it ends up in an error page. Although in case of an image servlet, you may also want to stream some standard 404.gif to the response instead. This because you can't display another HTML (error) page in an <img> element and you also can't change the URL of the parent JSP/HTML page as well since that concerns a different request.
According to the servlet API no servlet should call the getWriter() and getOutputStream() on the same response object as it causes the IllegalStateException. Usually this is the source of this exception. If you're outputing binary data like and image file you should use getOutputStream().
Looks like the problem you have is within your ExceptionPage.jsp, not your servlet code.
And this
java.lang.IllegalStateException:
Cannot reset buffer after response has
been committed
Means that you've already have tried to send a response.
Probably you've opened an output stream directly and wrote some data to it. Once you've done it you cannot try to set headers and such on a response ( they are already on their way to the client ).
You need to do a better state management. Best way to do this is to separate request preprocessing from the response generation. Once you are writing response, you can only do or die. For this, check that you are not catching IOExceptions from the response output, wrapping them to ServletException and redirect them to your error page. You really cannot handle them in the context of the current request.
First, identify why the Illegal State exception is being thrown. Rather than dealing with a thrown exception, you probably just want to fix your code so that it goes away.
You should catch the exception and forward the request using RequestDispatcher to the required page:
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// The following piece of code results in NumberFormatException which will
// be detected by the container. The RequestDispatcher object will forward
// the same request to the other resource, here the file: forwardedJSP.jsp
try {
int test = Integer.parseInt("abc");
} catch (NumberFormatException nfe) {
RequestDispatcher rd = request.getRequestDispatcher("/forwardedJSP.jsp");
rd.forward(request, response);
}}