Understanding JSP line of code with getRequestDispatcher - java

req.getRequestDispatcher("jsp/viewArticles.jsp").forward(req, resp);
So we get the Dispatcher of the Request, and provide the path. Ok so far. Now we forward to it the req and resp.
Now I am lost: We get RequestDispatcher from this req so RequestDispatcher is member method of req. Then why do we need to forward req itself to this RequestDispatcher anyway? Can't this method just use this to access req?
I found a question identical to mine but it do not understand the explanation, this is why I am asking again as an absolute servlet beginner.
How do the getRequestDispatcher() and forward() methods work?
Just for clarification, req and resp are of type HttpServletRequest and HttpServletResponse respectively.

From th API deginition, the RequestDispatcher 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 (aka Tomcatt) 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
The getRequestDispatcher() method is available from the current Request Object or from the current Servlet Context Object . Use req.getRequestDispatcher(path) for a relative path in the same context, and prefer ServletContext.getRequestDispatcher(path) for an absolute path.
Before forwarding you can add parameters Object as attribute with req.setAttribute("key", valueObject ) method to foward parameters server-side . The Request handle the data from the client, you can complete it, and the Response will handle the page, the headers , cookies and so on to the client.
Hope this can help

There's a hint in the JavaDoc of RequestDispatcher:
The difference between this method and ServletContext.getRequestDispatcher(java.lang.String) is that this method can take a relative path.
So essentially, you can ask for the RequestDispatcher via the ServletContext, in which case you can only use absolute paths, or you can request it via the ServletRequest, in which case you can use paths relative to that request path.

Related

At what point container creates request and response object?

When the client request comes, the container finds the correct servlet based on the URL and creates a pair of request and response objects.
According to me, the request and response objects only get created if the container finds valid servlet. That is, if there is no valid servlet found for the requested URL, then request and response objects don't get created.
However, I am not sure of this. Can anyone please confirm.
In chapter 12.1 Use of URL paths, the Servlet Specification states
The path used for mapping to a servlet is the request URL from the
request object minus the context path and the path parameters.
We can therefore assume that the request object (and possibly the response object) are created before any mapping logic is executed.
Note also that
Containers commonly recycle request objects in order to avoid the
performance overhead of request object creation.

How to pass on parameters from pretty URL to JSP pages?

I trying to do two things at once and I don't seem to find answers that can do both.
I'm trying this:
I want URLs ending in /user/{parameter} to be mapped to a JSP page user.jsp where I can access the parameter.
I find ways to pass parameters from the web.xml file to the JSP using this method
<init-param>
<param-name>someParam</param-name>
<param-value>itsValue</param-value>
</init-param>
And I find ways to create URL filters and map them to Java Servlets.
What I need is a combination. Also, what I found on passing URL parameters to Servlets wasn't too detailed either, so a good reference on that would also be more than welcome!
I want URLs ending in /user/{parameter} to be mapped to a JSP page user.jsp where I can access the parameter.
Map a servlet on /user/* and use HttpServletRequest#getPathInfo() to extract the path info.
E.g.
#WebServlet("/user/*")
public class UserServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String pathInfo = request.getPathInfo(); // "/{parameter}"
// ...
request.getRequestDispatcher("/WEB-INF/user.jsp").forward(request, response);
}
}
That's basically all. Use the usual String methods like substring() and/or split() to break down the path info in usable parts.
Use a base-url servlet to parse the URL and perform a conditional servlet forwarding to the appropriate JSP.
request.getRequestDispatcher().forward(JSPurl)
Let us say you have a URL branch /sales/. Under this URL branch, you would allow the following URLs to to be serviced by /implemented/usersales.jsp :
/sales/liquour/users/{region}
/sales/liquour/soft/users/{region}
/sales/toiletries/users/{type}
and the following URLs to be serviced by /implemented/products.jsp
- /sales/groceries/products/{section}
- /sales/groceries/meat/products/{region}
- /sales/groceries/vegetables/beans/products/{region}
You would have a web.xml servlet mapping for servlet class org.myorg.SalesHandler to be mapped to /sales/.
In the service method override in org.myorg.SalesHandler servlet class,
analyse the URL pattern (using regexp or otherwise) and then conditionally forward the request using
request.getRequestDispatcher().forward(JSPurl)
JAX-RS
But why would you do that when we have jax-rs?
How to forward from a JAX-RS service to JSP?.
JAX-RS may seem daunting at first, but it is actually very simple and intuitive to implement.

How to redirect a HTTPRequest from one controller class to other controller class?

I have two controller. One is main controller and other is intermediate controller. In intermediate controller I should add header to HTTPRequest. After Adding I should redirect it to main controller where I should check the header I added. How can I do this? Can anyone help me for this?pls........
Seems like a good place to use Servlet Filter . If you want to pre-process an incoming request you could do this with servlet filters and then simply chain it to the appropriate servlet .
Refer BalusC Answer for details .
If this is not the case your can merely forward the request like :
request.getRequestDispatcher("/yourServlet").forward(request, response); // forward to the main servlet
Forward Dispatching
getServletContext().getRequestDispatcher().forward("second page");
The request forwarding is done internally by the JSF Controller Servlet to another resource. The browser is unaware of what has happened in the server side at the web container. So it still thinks it is tending to the original request and displays the original URL in its address bar. However, the page content displayed is from the second page.
Redirect Dispatching
response.sendRedirect("second page");
In this case, the JSF Controller Servlet instructs the client browser (via HTTP response header) to fetch another URL. So the browser fetches entirely a new URL and displays the second URL in its address bar. This could cause slight performance delay
from here
I think you need to forward the request rather than redirecting.
RequestDispatcher dispatcher= request.getRequestDispatcher("servlet-mapped-url");
dispatcher.forward(request, response);

Sending redirect to another servlet/JSP without loosing the request parameters.

How do i specify a redirection to another servlet, in the doPost() method of a servlet.
at the moment I'm using
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response);
which is wrong since, my parameters in the doGet() method of products are not being called and initialized.
So I'm left with an empty products page after logging in :/
You need to use HttpServletResponse#sendRedirect() to send a redirect. Assuming that the servlet is mapped on an URL pattern of /products:
response.sendRedirect("/products");
This way the webbrowser will be instructed to fire a new HTTP GET request on the given URL and thus the doGet() method of the servlet instance will be called where you can in turn load the products and forward to a JSP which displays them the usual way.
In your doPost you can always call:
return doGet(request, response);

Servlet include swallows HTTP headers in Tomcat

I have a servlet that does a request dispatcher include of another servlet.
The included servlet sets headers that I would like to read in the including servlet. So I pass in a custom HTTPResponse object in the include() method which captures all feedback activity from the servlet.
The problem is that the headers are not being set in my custom response. I've run in debug and examined what looks like Tomcat wrapping my custom response object with its own response object. The setHeader calls go to this wrapping class and never propagate to my custom response object.
I imagine Tomcat does this to protect the client from headers being set in the wrong place. The funny thing is that the same approach works the way I'd expect in Jetty.
It's been a while since I've done Servlets seriously so I'm struggling a bit here. I'm trying to figure out how to read the response headers from a servlet that's invoked via dispatcher.include().
From the Servlet specifications section SRV.8.3:
The include method of the RequestDispatcher interface may be called at any time.
The target servlet of the include method has access to all aspects of the request
object, but its use of the response object is more limited.
It can only write information to the ServletOutputStream or Writer of the
response object and commit a response by writing content past the end of the
response buffer, or by explicitly calling the flushBuffer method of the
ServletResponse interface.
It cannot set headers or call any method that affects
the headers of the response. Any attempt to do so must be ignored.
How about setting your values for the calling servlet in request scope, with request.setAttribute(...) and then reading it from there once you return? Could that work?

Categories