When run the below code and the output I receive is "in", but the response .sendRedirect() does not run. The two java servlet files "Class1" and "Servlet1" are in the same folder.
public class Class1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html; charset=ISO-8859-7");
PrintWriter out = new PrintWriter(response.getWriter(), true);
ArrayList list2 = (ArrayList)request.getAttribute("list_lo");
if (list2 == null || list2.isEmpty() ) {
out.println("in");
response.sendRedirect("Servlet1");
return;}
}
}
Try to put the name of the file with the extension instead of the class name, sometimes happened to me, and just by doing this worked
You cannot send redirect once you start returning any output.
You need to put the logic handling any possible redirects before any output is started (e.g. out.println() in your example). Putting the redirect logic at the very beginning of the method is a sensible thing to do anyways, since it should be the first thing you decide.
The reason why redirecting after output is started lies in the HTTP protocol itself - redirect is transmitted using response headers, which are separated from response body by a blank line. Once you start writing the response body, there's no way to transmit any more headers anymore (apart from the started output being still in buffer if you're lucky).
Related
So Basically I have:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/zips/packet.html").forward(request, response);
return;
}
As you can you can see when a request is made for this servlet, It responds with packet.html file. To be precise, inside my packet.html I have a video element with src="" which I need to fill it by users requested url.
Question: How do I send a little extra data saying video source to the client, So in my client side it could change the video source from src="" to src="actual video source"
I TRIED:
String video_source = "/zips/video.mp4";
response.getWriter().append(video_source);
request.getRequestDispatcher("/zips/packet.html").forward(request, response);
With this method I can see my packet.html being received in my front-end But I can't find the video_source. FYI: don't know how to receive the video_source.
Well, To satasify your demand you can follow many apporoaches. One approach that I would suggest would put into consideration whatever you've already started
As Below
Step 1. Forward your request and response objects into packet.jsp,instead of into packet.html
Step 2. inside packet.jsp grab the input from user and send it with
the request object from packet.jsp
Step 3. Write a servlet class that process the request object from
packet.jsp and send the video as mulitpart file with the response.
Moreover, Do some research on how to use jsp's and servlets
The second approach would be to write client side javascript code that send ajax request to grab the video in a second call. For this you might even consider some client side frameworks and libraries(like jquery, angular, etc) that ease your work.
You could do the following:
Pass that additional information via request attribute (request.setAttribute())
Use some dynamic handler (like a servlet or JSP) to serve /zips/handler.html
Use request.getAttribute() in that handler.
So:
in your initial servlet, put
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("real_source", /some real source/);
request.getRequestDispatcher("/zips/packet.html").forward(request, response);
return;
}
In your /zips/packet.html you just use request.getAttribute("real_source") to generate the html attribute you need.
I have a form that is submitting a POST request to a servlet defined by #WebServlet("/SignUp").
I also have checks on the client side to make sure all of the form inputs are populated, but if they sneak by that and submit the form with an empty input I'd like the servlet to send them back /Home (i.e. index.jsp) as a fallback.
I have the following for my SignUp servlet's doPost():
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final String METHODNAME = "doGet";
logger.entering(CLASSNAME, METHODNAME);
String email = request.getParameter("email");
String pass = request.getParameter("password");
String cpass = request.getParameter("confirmPassword");
String forwardJsp = "";
if (StringUtils.isNotBlank(email) && StringUtils.isNotBlank(pass)
&& StringUtils.isNotBlank(cpass)) {
forwardJsp = "/SignUpMoreInfo.jsp";
} else {
// one of the fields was empty
request.setAttribute("signupFieldWasEmpty", true);
forwardJsp = "/Home";
}
request.getRequestDispatcher(forwardJsp).forward(request, response);
logger.exiting(CLASSNAME, METHODNAME);
}
This all works on a basic level. If they neglect to enter a value (i have yet to do any real checking, like .trim() or invalid characters), then they are send back to index.jsp (which backed by the /Home servlet).
However, I have two problems with the way my code is working and I can't figure out how to get around them.
My index.jsp is now being loaded as a POST request, rather than the usual GET. If the user refreshes the page, they get a client warning about refreshing the page on a POST request which is really ugly and cumbersome on the homepage.
The URL in the browser still has the address http://localhost:8080/SignUp, when I was expecting it to be http://localhost:8080/Home. This is also ugly and kind of confusing to the user, as the url no longer properly represents the page they associate with the "Home" page of the site.
How do I fix these issues I have with my Java backend code while maintaining as much MVC as possible?
You have to use redirect here instead to start a new request to /home :
Try this:
if (StringUtils.isNotBlank(email) && StringUtils.isNotBlank(pass) && StringUtils.isNotBlank(cpass)) {
forwardJsp = "/SignUpMoreInfo.jsp";
} else {
request.setAttribute("signupFieldWasEmpty", true);
response.sendRedirect("/Home");
}
However the problem now is that you are going to lose this information signupFieldWasEmptyso if you want to keep it you have to add as a request param to the uri :
else {
response.sendRedirect("/Home?signupFieldWasEmpty=true");
}
You can use the Post/Redirect/Get pattern to avoid this problem.
The servlet receives the Post request, processes the form, then sends a redirect to the desired page.
This is from book Professional Java For Web
The first time you call getParameter, getParameterMap,
getParameterNames, or getParameterValues on a request object, the web
container determines whether the request contains post variables, and
if it does it reads and parses those post variables by obtaining the
request’s InputStream. The InputStream of a request can be read only
once. If you call getInputStream or getReader on a request containing
post variables and then later attempt to retrieve parameters in that
request, the attempt to retrieve the parameters results in an
IllegalStateException.
And this is my test code:
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String name = req.getParameter("name");
System.out.println(name);
ServletInputStream inputStream = req.getInputStream();
int read = inputStream.read();
System.out.println(read);
}
And when I hit the Servlet with ?name=test I get:
test
-1
Is there something I am missing? How can I reproduce this Exception?
You have written a doGet. In the HTTP GET method, the data is passed through the URL (in the form of ?name1=value1&name2=value2...), not through the input stream.
To process POST variables, you have to write a doPost method and provide the data using a form (at least that's the usual way).
Note also that the book says that to get the exception, you have to open the stream first, then attempt to access the parameter. Not the other way around as you have written.
I am trying to create a Servlet that receives a XML based request and sends a XML in the response. I am new to Servlet first of all.
I have created the below Servlet in which I thought I am creating a Servlet that receives a XML based request in the doGet method and then in the doPost method, I can parse that XML file and then make a new XML file to send back the response. But I believe my understanding is wrong.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/xml");
PrintWriter writer = response.getWriter();
writer.println("<?xml version=\"1.0\"?>");
writer.println("<request uuid = \"hello\">");
writer.println("<app hash = \"abc\"/>");
writer.println("<app hash = \"def\"/>");
writer.println("</request>");
writer.flush();
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(request);
//parse the xml file if my understanding is right?
}
Can anyone provide me a simple example of this? I am just trying to create a Servlet that receives a XML based request (I am not sure of this, how can I make a servlet that can receive a XML based request), xml should be like above in my example.
And then parse the above XML file and use some content from that XML file to make a new sample XML file which I will be sending back as the response from that same Servlet.
Any help will be appreciated on this as I am slightly new to Servlet. This is the first time I am working with Servlet.
Update:-
I haven't got a proper answer on this yet. Any simple example will make me understand better. Thanks
You probably want to do everything in the doPost() method. Just one of doGet or doPost will be called, for a given HTTP request, depending on if the caller specified GET or POST in their request.
Your creation of the XML response looks basically ok. That is the general approach anyway, write the result XML to the response writer. If this is for production code, and not just a learning exercise, then you should use a library to create the XML, not just manually build it from strings. See "HOWTO Avoid Being Called a Bozo When Producing XML" http://hsivonen.iki.fi/producing-xml/
As far as parsing the incoming request:
BufferedReader reader = request.getReader()
Use that to read the characters of the incoming XML, and pass them to your XML parser.
Someone please HELP ME.
private void forward(String address,
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
getServletContext()
.getRequestDispatcher("/" + address)
.forward(request, response);
}
private void include(String address,
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException{
getServletContext()
.getRequestDispatcher("/" + address)
.include(request, response);
}
These two functions have been written in every servlet in my project and the problem is that when I have used these two functions in a servlet at first include("servlet/abc",request.response); and after it have used forward("servlet/def",request.response); so using Netbeans 7 I have step by step watched that forward is not forwarding the control of servlet but when I don't use include before the forward its forwarding the control.
So I want to know that why it is happening and what's the reason and how can I do forward after include any servlet.
Please someone HELP ME ...it's an interesting question.
include("servlet/abc",request, response);
forward("servlet/def",request, response); //HERE IS PROBLEM NOT FORWRDING AFTER INCLUDE
Regardless of exactly why you seem to observe this behavior, what you're attempting will never work. Per the contract of RequestDispatcher.forward(), "If the response already has been committed, this method throws an IllegalStateException," and "Uncommitted output in the response buffer is automatically cleared before the forward."
Therefore, whether the forward succeeds or not, you'll never be able to successfully send content back to the user both before and after a forward. This is because the purpose of a forward is to allow "one servlet to do preliminary processing of a request and another resource to generate the response", not to let two different servlets generate different parts of the response. In the Servlet model, generating a response always belongs to exactly one servlet.
If you don't know what "committed" and "uncommitted" means, it's referring to whether the response status and headers have been sent to the user yet. When you're writing a response, you're actually writing into a local buffer. Nothing will necessarily be sent immediately. As long as everything you've written is still local, you're free to do whatever, including resetting the buffer and starting over, like a forward does, but as soon as something is sent off, you're committed and can no longer change what you were going to do. A response can become committed (i.e. be all or partly sent to the user) in a few ways, including filling up the buffer so that it has to be sent to make room for more content, flushing the buffer manually, or flushing the Writer or OutputStream of a response.
Ultimately, what's probably happening in your case is that you're writing some stuff using an include, and it's causing the response to be committed, either because you've filled the buffer or because I seem to recall that an include generally causes an automatic flush (not sure about documentation on this one). Then when you try to forward, it's throwing the required IllegalStateException, which you should probably see in your logs somewhere, but won't cause the typical 500 response status since, as I've discussed, you've already committed with some other status code.
You cannot change the response status or state once response is committed. When you include some page using request dispatcher you are actually committing response and data is starting to be sent to client. After that you are not allowed to make a change of response status to 302 which is required for redirect.
You will get an error java.lang.IllegalStateException: Cannot forward after response has been committed if you try that.
RequestDispatcher has only two methods:
public interface javax.servlet.RequestDispatcher {
public abstract void forward(javax.servlet.ServletRequest, javax.servlet.ServletResponse) throws javax.servlet.ServletException, java.io.IOException;
public abstract void include(javax.servlet.ServletRequest, javax.servlet.ServletResponse) throws javax.servlet.ServletException, java.io.IOException;
}
You are giving it as
include("servlet/abc",request, response);
forward("servlet/def",request, response);
but in the API it is mentioned only servlet request object and response object as parameters, so I guess you should remove your url from there. Correct me if I'm wrong, as I'm also learning.