Setting character encodiing using ServletRequest and ServletResponse - servlets

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.

Related

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.

How HttpServletRequest works

i'm trying to understand how HttpServletRequest works:
in a demo application I have this code in a .class file:
HttpServletRequest req = (HttpServletRequest)
FacesContext.getCurrentInstance().getExternalContext().getRequest();
String parameter = req.getHeader("PARAMETER");
is this a JSF implementation? Does it read a parameter from the session right?
How can I retrieve the same parameter without using JSF?
Yes, this snippet is part of a JSF application.
No it doesn't read a parameter from the session, since it calls getHeader() on a HttpServletRequest object. So it reads a request header (as the javadoc of HttpServletRequest.getHeader() explains).
To retrieve the same header in a simple servlet-based application, you would use the HttpServletRequest argument passed to every servlet method:
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String header = request.getHeader("PARAMETER");
...
}
It looks like you're not familiar at all with servlets. Read an introductory tutorial to grasp the basics before dving into code.

Servlet doFilter setAttributes not available in Servlet

I'm trying to add an Attribute to the request via doFilter before passing it to the Servlet, so that a value in JSTL will be set. I simply do req.setAttribute("b", "blah") in the filter, but it doesn't seem to get set in the JSTL file. How would I do this?
It's hard to pinpoint the root cause without seeing the code. There are several possible causes.
You're sending a redirect after setting the attribute instead of continuing with the same request.
You're accessing the attribute with the wrong name (case sensitive!).
You're accessing the attribute the wrong way.
The attribute is been overridden somewhere further down in the request processing.
There's a page scoped attribute with the same name which has no value.
You're misinterpreting the results.
Etc.
By the way, there's no such thing as a "JSTL file". Perhaps you meant "JSP file".
The problem is that the doFilter method uses ServletRequest instead of HttpServletRequest which is the one that has the setAttribute method. Most of my filters are something like this:
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// do what you must...
chain.doFilter(servletRequest, servletResponse);
}

How do delete a HTTP response header?

I have a situation where one of the response headers Content-Disposition has to be removed. So I thought of writing a servlet filter to do this. But I realized that the HttpServletResponse has only a setHeader() method but no method to remove it.
How can I do this?
You can't delete headers afterwards by the standard Servlet API. Your best bet is to just prevent the header from being set. You can do this by creating a Filter which replaces the ServletResponse with a custom HttpServletResponseWrapper implementation which skips the setHeader()'s job whenever the header name is Content-Disposition.
Basically:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
public void setHeader(String name, String value) {
if (!name.equalsIgnoreCase("Content-Disposition")) {
super.setHeader(name, value);
}
}
});
}
Just map that filter on the URL-pattern of interest to get it to run.
This may not be Servlet API compliant, but setting the value to null works on GlassFish 4 and probably on Tomcat too as that is what is underneath GlassFish.
We really need to update the Servlet API specification to either add a method to allow removing headers or to officially support using setHeader with a null value.
An example where this is important is if you use a security constraint (SSL/TLS) on your web application then static resource caching is complicated by the fact that the container will automatically add headers to prevent caching (you can try to disable with disableProxyCaching and securePagesWithPragma on Tomcat/GlassFish). I've already got a servlet filter for cache control that works great for non-secure content so I would like to keep cache control all in one place and simply set Prama and Cache-Control to null to clear any container added headers.
As the other responses. There is no way to remove a header after being set, at least not standard (glassfish lets clear a header setting it's value to null). So at the end of the day you would have two choices:
Reset the response with response.reset() - This effectively removes ALL headers AND ALSO ANY BUFFERED DATA, depending on you case can be a good alternative (in my case was after authentication validation errors). If the response is already committed you'll get an IllegalStateException.
Set header to empty string, clearly this doesn't remove the header. But the http specification only has some definitions for and empty value in the Accept-Encoding, TE (transfer encoding) and HOST headers, so depending in your needs you can control that in your application layer.
This does not work for me using Spring 4. I'm trying to strip out the Expires response header. For every page. Like so:
public class CachingFilter implements Filter {
private final Log logger = LogFactory.getLog(getClass());
public CachingFilter() {}
public void destroy() {}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.debug("doFilter()");
chain.doFilter(request, new HttpServletResponseWrapper((HttpServletResponse) response) {
public void setHeader(String name, String value) {
logger.debug("setHeader(" + name + ","+value+")");
if (!name.equalsIgnoreCase("Expires")) {
super.setHeader(name, value);
}
}
});
}
public void init(FilterConfig fConfig) throws ServletException {}
}
And here is how I add the filter:
public class AppConfig implements WebApplicationInitializer {
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
private static final String DISPATCHER_SERVLET_MAPPING = "/";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppContext.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
FilterRegistration.Dynamic noCache = servletContext.addFilter("noCacheFilter", new CachingFilter());
noCache.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
servletContext.addListener(new ContextLoaderListener(rootContext));
}
}
setHeader() being called for Expires and Cache-Control, but I can't override the Expires filter value, or the Cache-Control value. I can add to the Cache-Control value. It turns into an array of values if I call setHeader on Cache-Control. But I need to delete the header.

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