IllegalStateException In Servlet - java

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.

Related

how to append getRequestDispatcher with extra data in java?

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.

response.sendRedirect() does not running - Servlet

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).

Java servlet : request.getParameter() returns a parameter from the query string in a POST request

I'm currently developing a Servlet that runs under Glassfish 4.
I implemented the doPost() method and I need to ensure that the parameters are passed using the POST body, and not in the query string.
I wrote a test implementation to check it:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
response.getOutputStream().print(name);
}
If I call my page with POST with this url:
http://localhost:8080/myservlet/testservlet
and pass name=Nico into the post body, the value Nico is returned, and it's okay.
Now if I call it this way:
http://localhost:8080/myservlet/testservlet?name=Robert
and I still pass name=Nico in the POST body, Robert is returned, and the name=Nico is ignored.
I just would like to avoid parameters to be passed in the URL.
Is there a way to explicitly retrieve parameters from the POST body instead of body + query string?
Check the javadoc for the getParameter method:
https://tomcat.apache.org/tomcat-7.0-doc/servletapi/javax/servlet/ServletRequest.html#getParameter%28java.lang.String%29
Like it is stated, you are sending 2 parameters on the request with the same name, one from the query string and another on the body.
Now it is up to you to either validate that no parameter is coming from the query string or read directly values from the request body.
In most cases, you can read both of them using getParameterValues, the first one is query string and the second one is post body. Now you can decide which one to use.
String[] lines = request.getParameterValues("name");
Did you check what request.getAttribute() returns?
Anyway you can't avoid that people will try to send you evil data, either in the url or by tinkering with the post-request.
So when you work with input from a website, always imagine a hacker sitting on the other side and sending you evil content in your parameters, like sql-injections. So you need a good validation to only let good content through to your database.
Because it's not your problem if a user enters his username as a parameter in the url. Let him have the fun, if he prefers this way over the input-field. The hackers are the problem.
I think it is a problem of front end code, instead of servlet. Any post request submission from UI should strip query string.

Servlet that receives a XML based request and then make a new XML file to send back as the response

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.

request dispatcher forward is not forwarding after include of any servlet

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.

Categories