How does ContentCachingResponseWrapper work? - spring-mvc

I understand that with ContentCachingResponseWrapper, the body of the response is cached and that can be read multiple times. But the function getContentAsByteArray() returns empty unless the chain.doFilter() method is called. I don't have another filter in my code, so I don't understand why this is the case. For example my code is -
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("In ServletFilter");
HttpServletResponse res = (HttpServletResponse) response;
ContentCachingResponseWrapper ccrw= new ContentCachingResponseWrapper(res);
chain.doFilter(request, ccrw); // If this statement is not executed then content is empty
String content=new String(ccrw.getContentAsByteArray(), "utf-8");
System.out.println(content); // This prints empty if the chain.doFilter is not executed
}

Related

Can I write code after RequestDispatcher?

public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//some code here
}
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//performTask(req, resp);
//some code here
}
private void insertRequestTemplate() {
HttpSession session = req.getSession();
responsePage = req.getParameter("ResponsePage");
ServletContext ctx = getServletConfig().getServletContext();
ctx.getRequestDispatcher(responsePage).forward(req,resp);
readMessage();
public void readMessage()
{
System.out.println("calling MessageTrigger_ABean");
MessageTrigger_ABean msg = new MessageTrigger_ABean();
msg.read();
}
msg.read() has the code to read messages from MQ. Inside insertRequestTemplate method, I am calling readMessage method after ctx.getRequestDispatcher(responsePage).forward(req,resp);is this the correct way of calling this?
But inside insertRequestTemplate method, the page is not getting forwarded to the next page untill readMessage() is executed because of which the page keeps on loading for a long time until message is read from MQ. Could you please help me on this.
Most examples I have seen of a servlet forwarding the request to another servlet have the dispatcher forward invocation at the end of the method. ie. there is no more code, other than closing braces at the end of the method.
I am guessing that the forwarding doesn't happen until the invoking method completes. So where you have your msg.read() will stop the insertRequestTemplate method from completing. This will more than likely be because the code inside msg.read is being performed synchronously. Leading to http timeouts on the http request.
How you solve this will depend on what you want to do with the messages you obtain from msg.read().

Spring Security ExceptionTranslationFilter throw "Unable to handle the Spring Security Exception because the response is already committed."

I'm using spring security web 5.0.9 and tomcat 8. ExceptionTranslationFilter throw ServletException "Unable to handle the Spring Security Exception because the response is already committed."
I dig into the source code and find the root cause. I'm not sure whether it is a bug for spring security.
I throw the UsernameNotFoundException in AuthenticationUserDetailsService.loadUserDetails
SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure catch the exception and then call
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
the sendError will set response committed to true, see ResponseFacade.java:
public void sendError(int sc, String msg)
throws IOException {
...
response.setAppCommitted(true);
...
}
Then ExceptionTranslationFilter catch it and check the response commit status, found it's true and then throw the exception
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
...
if (response.isCommitted()) {
throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", ex);
...
}
nobody catch the ServletException and the application try to find the /web_framework/error_page/405.html
I find the spring security code is changed in this bug fix https://github.com/spring-projects/spring-security/issues/5273.
How to deal with the ServletException and return the valid 401 response, but not web_framework/error_page/405.html
This sounds like it could be a misconfiguration in the code.
Typically, if the SimpleUrlAuthenticationFailureHandler is invoked, then the ExceptionTranslationFilter is not also invoked since there is no further response handling required.

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:

java.lang.NullPointerException in servlet error 500

When I run my Servlet I get this error:
java.lang.NullPointerException please i tried many solutions but it didn't work it's simple code
public LoginServlett() {
super();
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String name = request.getParameter("UserName");
String pass = request.getParameter("Password");
RequestDispatcher d=null;
if (name.contentEquals("Gestionnaire") && pass.contentEquals("1234")) {
HttpSession session;
session =request.getSession(true );
d =request.getRequestDispatcher("/EspaceGestionnaire.html");
session. setAttribute("NomSauvegardé" ,name);
}
else {
d = request.getRequestDispatcher("/Authentification.html");
d.forward(request, response);
}
}
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
}
}
A NPE will be thrown from the code if the Username and Password parameters are not set. If they are not set then the user and pass variables will be null, and when the contentEquals methods are called on them a NPE will be thrown as a result.
A way to do this would be to reverse the equality checks so the operation is called on string you want to check:
if ("Gestionnaire".contentEquals(name) && "1234".contentEquals(pass)) {
which will do what your code intends without throwing a NPE.
Although if you are sending passwords over the internet it is better to use POST than GET. For Java EE security there is also the new security API (https://javaee.github.io/security-spec/)

Sending response after chain.doFilter in filters

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.

Resources