RequestDispatcher in Java - java

What exactly the main purpose of using RequestDispatcher, for example when it's executed in Filter like the following example:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws ServletException, IOException {
HttpServletRequest aHttpServletRequest = (HttpServletRequest) request;
aHttpServletRequest.getRequestDispatcher("/init.jsp").include(request, response);
chain.doFilter(request, response);
}

In your case, the output of JSP is prepended to every page that filter is attached. This is a technique to easily add a common header to all your pages.
It's a little bit confusing when RequestDispatcher is used int his context. Normally, when you want to dispatch your request to another servlet or JSP for process, you use RequestDispatcher to forward to another resource. In this case, your request is not dispatched anywhere else, instead you include output generated by another resource to your current response.

The javadoc says is better than I can:
RequestDispatcher:
Defines an object that receives
requests from the client and sends
them to any resource (such as a
servlet, HTML file, or JSP file) on
the server. The servlet container
creates the RequestDispatcher object,
which is used as a wrapper around a
server resource located at a
particular path or given by a
particular name.
In other words, you obtain a RequestDispstcher when you want to include from, or forward to, another resource on the server.

Related

How does the Tomcat container calls service() method?

How does the Tomcat container calls service(ServletRequest req, ServletResponse res) method?
Where can I look for implementation of this call?
How can I see how this req and res objects (that passed to service() method) are created?
Although the Tomcat Architecture page is in TODO status, there is at least a link to the UML sequence diagram of the request processing. Combining with Tomcat's source code, it is a good starting point.
If you want to know it, first clone apache tomcat source code
git clone https://github.com/apache/tomcat.git
Then inside the cloned repository, launch this command to search where it is invoked service method:
grep -H -n -r "\.service(" --include=*.java
You will find a short file list:
java/javax/servlet/jsp/PageContext.java:107: * in this PageContext until the return from the current Servlet.service()
java/org/apache/catalina/connector/Request.java:3128: // that set towards the start of CoyoyeAdapter.service()
java/org/apache/catalina/core/ApplicationFilterChain.java:231: servlet.service(request, response);
java/org/apache/catalina/servlets/DefaultServlet.java:411: super.service(req, resp);
java/org/apache/catalina/servlets/WebdavServlet.java:349: super.service(req, resp);
java/org/apache/coyote/ajp/AjpProcessor.java:403: getAdapter().service(request, response);
java/org/apache/coyote/AsyncStateMachine.java:41: * been called during a single Servlet.service() method. The
java/org/apache/coyote/AsyncStateMachine.java:58: * been called during a single Servlet.service() method. The
java/org/apache/coyote/http11/Http11Processor.java:498: getAdapter().service(request, response);
java/org/apache/coyote/http2/StreamProcessor.java:257: adapter.service(request, response);
java/org/apache/jasper/Constants.java:41: * HttpJspBase.service(). This is where most of the code generated
java/org/apache/jasper/servlet/JspServlet.java:385: wrapper.service(request, response, precompile);
java/org/apache/jasper/servlet/JspServletWrapper.java:440: servlet.service(request, response);
java/org/apache/jasper/servlet/JspServletWrapper.java:443: servlet.service(request, response);
The most intresting one is java/org/apache/catalina/core/ApplicationFilterChain.java. You wil find more coincidences, but much of them are because there is another interface into Tomcat source code that has a very similar method java/org/apache/coyote/Adapter.java ignore it.
Once you get java/org/apache/catalina/core/ApplicationFilterChain.java, you can edit, got to line 231 and see where the service method is called.
However, both req and res objects are not created in that place. Finding how those are created seems to be a bit more complex and requires more time.
Servlet lifecycle is controlled by the underlying container. Once the servlet has been initialized and there is a request, Tomcat will call the servlet's service method to process the request.
Service method will delegate request to your Servlet class where you can get access to req and res objects in doGet or doPost methods.
public void doGet(HttpServletRequest req, HttpServletResponse res){
}
Update :
1. Upon request from the client, Container creates two objects : HttpServletRequest and HttpServletResponse.
2. Based on the request, Container will find correct Servlet (as per URL mapping), creates new thread for that particular request(one-to-one mapping - new thread for each request) and calls Servlet's service method, passing in created HttpServletRequest and HttpServletResponse objects as arguments.
3. Based on request method (GET or POST) service() method will call doGet() or doPost() method in Servlet, again passing the same HttpServletRequest and HttpServletResponse objects as arguments.
Those are Servlet specifications in a nutshell. How does Tomcat act exactly is implementation specific, it is not controlled by specification. If you need to know how exactly it is implemented in Tomcat, you might check it's source code.

Will the code be executed after chain.doFilter()? [duplicate]

The javax.servlet.Filter object can be used both for authentication (where the Filter needs to catch the request before any servlet work needs to be done) and for XSLT translation (where the servlet needs to be completely finished generating content). When does it actually get executed?
I know this is implementation dependent (on the web container), but this seems to be problem that needs to be solved by all of them.
Maybe there is a configuration option set somewhere for each Filter registration with the web container?
Additional:
Also, what governs the order of Filter execution? Why would FooFilter get executed before BarFilter?
The filter chain in essence wraps the servlet invocation. The chain will process all links until it hits the "bottom", then allow the servlet to run, and then return up the chain in reverse. For example, if you have a new "example filter", your doFilter() method may look like this:
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// do pre-servlet work here
chain.doFilter(request, response);
// do post servlet work here
}
According to the servlet2.3 specification filter is performed according to web.xml configuration of filter- mapping sequence Ref-http://www.programering.com/a/MTMyADOwATI.html

Change ServletRequest server name programmatically

I need to change the serverName of the ServletRequest object in my Grails controller. I'm having trouble figuring out how to do this since the serverName is a read-only property.
The most correct thing to do is probably to set up a clever filter or redirect which "fixes" your request URL before your servlet even gets involved. I know nothing about how to do that; you should ask on serverfault.com if you want to do that.
In java, you can fake it by creating your own subclass of HttpServletRequestWrapper which provides setServerName() and overrides getServerName() while delegating all other methods to the superclass. You can then provide a filter which creates an instance of your request and sends that one down the chain.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
YourHttpServletRequest yourRequest =
new YourHttpServletRequest(request, newServerName);
chain.doFilter(yourRequest, response);
}
If I understand this correctly, CORS filter might help
I've used http://software.dzhuvinov.com/cors-filter.html in my previous project.
But you can also lookup on github for example https://github.com/eBay/cors-filter

Accessing a HashMap of custom objects in request scope after a redirect

I have a HashMap of custom objects being passed to a JSP using RequestDispatcher and I am able to access the object and its properties using JSTL.
However the code fails in case the parameter is sent using response.sendRedirect() .
I am not sure what the reason is and how to make it work?
The response.sendRedirect() basically instructs the client (the webbrowser) to send a new request on the given URL. You'll also see this being reflected by a change in the browser address bar.
A new request does of course not contain the attribtues of the previous (or any other) request. That would otherwise have broken the whole concept of "request scope".
To preprocess a GET request, you need to do the job in doGet() method of a servlet and then redirect to the URL of that servlet instead.
E.g.
response.sendRedirect(request.getContextPath() + "/foo");
and
#WebServlet("/foo")
public class FooServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, Foo> foos = fooService.map();
request.setAttribute("foos", foos);
request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response);
}
}
Note that this problem is in no way related to having a hashmap of custom objects in the request scope.
See also:
Our servlets wiki page
You can not share a request attribute in response.sendRedirect as it creates a new request.
But, if you want that HashMap, in response.sendRedirect, you can put that in session like
request.getSession().setAttribute("myMap", [HashMap object]);
and can share between the servlet and JSP. This works in both RequestDispatcher and sendRedirect.

Forward request from a filter

I need to forward my request (to a jsp but I don't think it's matter) from an http.Filter
if the URI of the original request pass some validation that my filter runs.
I found this page that faced similar task
Still I need to figure the following:
How can I get ServletContext in doFilter() method (in order to call forward API) getServletContext() is not recignized
Do I have to call chain.doFilter() before the forward, after the forward or not at all?
In addition do I have to call chain.doFilter() if my validation passed or only if it fails (because in this case I won't continue to forward my page)?
This question actually continue this thread,
to be more obvious, the code could be something like:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = ((HttpServletRequest)request);
String requestURI = httpServletRequest.getRequestURI();
String contextPath = httpServletRequest.getContextPath();
if (<this is my implementation of the validation of this filter>){
getServletContext().getRequestDispatcher(
"MySpecific.jsp").forward(request,response);
}
}
chain.doFilter(request,response);
}
How can I get ServletContext in doFilter() method?
httpServletRequest.getSession().getServletContext();
Do I have to call chain.doFilter() before the forward, after the forward or not at all? In addition do I have to call chain.doFilter() if my validation passed or only if it fails (because in this case I won't continue to forward my page)?
I would say that if you forwarded the request, you should not call chain.doFilter() - the forwarded request will get filtered according to its own filter configuration. If your validation failed though, it depends on what the semantics of your web app are - if the original page is some sort of general error/login/welcome screen, you may want to continue to that when the validation failed. It is hard to say without knowing more of the context.
To get the ServletContext, you've got 2 options:
Store off the FilterConfig during the initialization and call FilterConfig.getServletContext()
call HttpServletRequest.getSession().getServletContext()
I don't think you necessarily need the ServletContext to get the RequestDispatcher as you could just call HttpServletRequest.getRequestDispatcher().
In relation to FilterChain.doFilter() call, if you're forwarding, I would think you wouldn't make the call, as once you forward, I assume you don't want any of the standard behavior to take place.
If you don't forward (you don't fall into your if block), then I'd call the FilterChain.doFilter() method, however that assumes there is a target on the other end to be invoked.

Categories

Resources