Sending response after chain.doFilter in filters - servlets

I am new to Servlets. In the book i am reading now it is written, that we need wrappers, because it is late to do anything with response after finishing chain.doFilter() method as response is sent already.
I wrote the following Servlet and Filter:
public class MyServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
PrintWriter writer = response.getWriter();
writer.println("In Servlet");
}
}
public class MyFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException{
PrintWriter writer = response.getWriter();
chain.doFilter(request, response);
writer.println("After chain");
}
}
And i see both strings in the browser.
My question is: Why do we need wrappers? I still can write to response even after chain.doFilter and i still see result?
Is it because response is sent in two pieces(first in the end of chain.doFilter and second in the end of Filter.doFilter)? So if i had to compress response it would work incorrectly(because first uncompressed part would be sent)?

The book is talking about response headers.
You misunderstood it as response body.
Here are some real world use cases of response wrappers so you can see why we may need them:
How to add response headers based on Content-type; getting Content-type before the response is committed
How do delete a HTTP response header?
How to read and copy the HTTP servlet response output stream content for logging
How to insert JSF page rendering time and response size into the page itself, at least partially?
How to configure Tomcat to not encode the session id into the URL when HttpServletResponse.encodeURL() is invoked
For more examples, see this search.

Related

Apache Sling - passing request object as part of doPost

Can someone explain and provide code snippet for passing request body (maybe it can accept value Object) as part of apache sling doPost method -
request :
{ "XDPCont" : "XDP sample string"}
Response :
I have tried with below code but it did't work.
#Override
protected void doPost(final SlingHttpServletRequest req,
final SlingHttpServletResponse resp) throws ServletException, IOException {
final Resource resource = req.getResource();
resp.getOutputStream().println(resource.toString());
resp.getOutputStream().println(
"This content is generated by the HelloServlet POST"+req.getRequestParameter("XDPCont"));
}
Can you please explain with an working code.

does returning from doGet() or doPost() automatically send a resonse

I have looked around and previously asked this question but did not get a full answer. When you explicity return from doGet() or doPost() does a response get sent regardless of if you have encoded anything or not. If so what is the default code ? Is it enough to simply response.setStatus() and return ? If not: so I have always manually send back a response ? What is the default way to just respond not using forward or redirect ?
If you do nothing, just return (or not even return) from a servlet, it will send back a status code 200(OK) empty response. Tested it in both tomcat and glassfish servers, using the servlet below:
#WebServlet("/a")
public class a extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return;
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return;
}
}
Using the network profiler tool of Chrome you can see what I said:

Setting character encodiing using ServletRequest and ServletResponse

I have seen a web application which deals with file processing (reciving applications from
a third party application and storing them in database for further usage).
That particular web application is also having a servlet filter configured whose only basic purpose is to set the character encoding to UTF-8.
For example :
public class ResponseFilterExample implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) throws IOException, ServletException {
filterchain.doFilter(request, response);
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
}
}
Now my question is, what is the difference between
request.setCharacterEncoding("UTF-8");
and
response.setCharacterEncoding("UTF-8");
?
Well, the difference is that one sets the encoding on the request, the other sets the encoding on the response.
The above doc links explain in more detail.
ServletRequest.setCharacterEncoding():
Overrides the name of the character encoding used in the body of this request. This method must be called prior to reading request parameters or reading input using getReader(). Otherwise, it has no effect.
ServletResponse.setCharacterEncoding():
Sets the character encoding (MIME charset) of the response being sent to the client, for example, to UTF-8.

How to get a Servlet Request attribute in Struts 2.2.1?

I'm reading some tutorial where before invocating any action there is a filter that sets an attribute in the ServletRequest as Connection.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Connection connection = new ConnectionFactory().getConnection();
request.setAttribute("connection", connection);
chain.doFilter(request, response);
connection.close();
}
However I still didn't find a way to get the attribute in my Action. How can I get it?
Map parameters = ActionContext.getContext().getParameters();
Another option is that your action class implements ServletRequestAware. In the implementation of the method you simply assign the request to an instance field.

How do I execute multiple servlets in sequence?

I am just beginning with Servlets and managed to have some servlets that act as individual URLs for populating a database for some dummy testing. Something of the form:
public class Populate_ServletName extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
//Insert records
//Print confirmation
}
}
I have about 6 such servlets which I want to execute in a sequence. I was thinking of using setLocation to set the next page to be redirected but was not sure if this is the right approach because the redirects should happen after the records have been inserted. Specifically, I am looking for something like this:
public class Populate_ALL extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
//Call Populate_1
//Call Populate_2
//Call Populate_3
//...
}
}
Any suggestions?
Use RequestDispatcher#include() on an URL matching the url-pattern of the Servlet.
public class Populate_ALL extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
request.getRequestDispatcher("/populateServlet1").include(request, response);
request.getRequestDispatcher("/populateServlet2").include(request, response);
request.getRequestDispatcher("/populateServlet3").include(request, response);
//...
}
}
Note: if those servlets cannot be used independently, then this is the wrong approach and you should be using standalone Java classes for this which does not extend HttpServlet. In your specific case, I think the Builder Pattern may be of interest.
The RequestDispatcher#forward() is not suitable here since it throws IllegalStateException when the response headers are already committed. This will be undoubtely the case when you pass the request/response through multiple servlets which each writes to the response.
The HttpServletResponse#sendRedirect() is absolutely not suitable here since it implicitly creates a brand new request and response, hereby trashing the original ones.
See also:
How do I call a second JSP servlet while in the first JSP servlet?
RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()
communication between remote servlets
It looks like what you may need is a service that each of the servlets can use to perform some work. Then the servlets are not depending one and another, but rather all using the service.
However, here is an explanation of forwarding or redirecting requests.

Resources