HI
I like to know there is a single method called getRequestDispatcher() in ServletRequest and ServletContext interfaces. What is the difference?
As stated in the Servlet API Javadocs,
The difference between this method [the ServletRequest one] and ServletContext.getRequestDispatcher(java.lang.String) is that this method can take a relative path.
You can pass a relative path to getRequestDispatcher() of ServletRequest but not to getRequestDispatcher() of ServletContext.
Example:
My current request is served from page - webapp/view/core/bar.jsp
and requested page - webapp/view/util/foo.jsp
request.getRequestDispatcher("../util/foo.jsp") is valid and will be evaluated to the path relative to current request.
servletContext.getRequestDispatcher("/view/util/foo.jsp") is valid and will evaluate from context root.
This is because ServletContext will not be aware of current request path.
If you decide to use '/' root to access your resources, then both ways are same.
Related
Does the method getParameterMap of the HandshakeRequest include path parameters? I can't seem to find a detailed documentation regarding this.
HandShakeRequest#getParameterMap() javadoc says following:
Return the request parameters associated with the request.
It says request parameters, not path parameters.
Let's check how an URL is composed:
http://example.com/context/foo/bar?foo=bar&bar=foo
----------------
Request URI
http://example.com/context/foo/bar?foo=bar&bar=foo
--------
Context path
http://example.com/context/foo/bar?foo=bar&bar=foo
--- ---
Path parameters
http://example.com/context/foo/bar?foo=bar&bar=foo
------- -------
Request parameters
When having only HandShakeRequest at hands, which doesn't have any method directly returning path parameters, your best bet is to use getRequestURI() and perform string manipulation (split, substring, etc) in order to extract path parameters.
The alternative is to move the task into Endpoint#onOpen() or #OnOpen, there path parameters are just directly available via Session#getPathParameters().
suppose that I want to accept the following urls:
http://myserver/myapplication/posts
http://myserver/myapplication/posts/<id>
http://myserver/myapplication/posts/<id>/delete
how can I use the servlet decorator #WebServlet to do so? I'm investigating value and urlPatterns but I don't get how to do so. For example,
#WebServlet(urlPatterns={"/posts", "/posts/*"})
[..]
String param = request.getPathInfo();
gives me some result, but how to use it? Also, request.getPathInfo() seems to return the value of the wildcard, but what if I want more parameters like in http://http://myserver/myapplication/posts/<id>/delete/<force>?
In servlet specification, you have no notion of path variables. Some MVC frameworks do support them, for example Struts or Spring MVC.
For a servlet point of view, an URL is :
scheme://host.domain/context_path/servlet_path/path_info?parameters
where any of the parts (starting from context path may be null)
Spec for servlet 3.0 states :
Context Path: The path prefix associated with the ServletContext that this
servlet is a part of. If this context is the “default” context rooted at the base of the
Web server’s URL name space, this path will be an empty string. Otherwise, if the
context is not rooted at the root of the server’s name space, the path starts with a
/ character but does not end with a / character.
Servlet Path: The path section that directly corresponds to the mapping which
activated this request. This path starts with a ’/’ character except in the case
where the request is matched with the ‘/*’ or ““ pattern, in which case it is an
empty string.
PathInfo: The part of the request path that is not part of the Context Path or the
Servlet Path. It is either null if there is no extra path, or is a string with a leading
‘/’.
The following methods exist in the HttpServletRequest interface to access this
information:
getContextPath
getServletPath
getPathInfo
It is important to note that, except for URL encoding differences between the request
URI and the path parts, the following equation is always true:
requestURI = contextPath + servletPath + pathInfo
That means that you just have to use #WebServlet(urlPatterns={"/posts"}), and then decode by hands the pathInfo part to extract commands and parameters
I think you cannot do so using only the #WebServlet annotation. The urlPatterns only acts as a directive to the Servlet to indicate which url patterns should attend.
And as you can see by this docs https://docs.oracle.com/javaee/6/api/javax/servlet/annotation/WebServlet.html the value is just the case when urlPatterns is one string instead of an array of them.
As brso05 stated, you will need to parse from the request your parameters.
Using embedded tomcat, this code:
System.out.println("getServletPath: " + request.getServletPath());
System.out.println("getServletContext: " + request.getServletContext().getContextPath());
System.out.println("getServerName: " + request.getServerName());
System.out.println("getServerPort: " + request.getServerPort());
Prints out:
getServletPath: /example
getServletContext:
getServerName: localhost
getServerPort: 9090
Does that mean that:
request.getRequestDispatcher("/example/read.jsp").forward(request, response);
Will look at this URL to forward(request, response) to the JSP:
http://localhost:9090/example/read.jsp?
Is there a way to print out what absolute URL getRequestDispatcher("relativePath") is addressing?
The Servlet Specification explains this
The getRequestDispatcher method takes a String argument describing a
path within the scope of the ServletContext. This path must be
relative to the root of the ServletContext and begin with a ‘/’, or
be empty. The method uses the path to look up a servlet, using the
servlet path matching rules in Chapter 12, “Mapping Requests to
Servlets”, wraps it with a RequestDispatcher object, and returns the
resulting object. If no servlet can be resolved based on the given
path, a RequestDispatcher is provided that returns the content for
that path.
Those rules are the following
The container will try to find an exact match of the path of the request to the path of the servlet. A successful match selects the
servlet.
The container will recursively try to match the longest path-prefix. This is done by stepping down the path tree a directory
at a time, using the ’/’ character as a path separator. The longest
match determines the servlet selected.
If the last segment in the URL path contains an extension (e.g. .jsp), the servlet container will try to match a servlet that handles
requests for the extension. An extension is defined as the part of
the last segment after the last ’.’ character.
If neither of the previous three rules result in a servlet match, the container will attempt to serve content appropriate for the
resource requested. If a "default" servlet is defined for the
application, it will be used. Many containers provide an implicit
default servlet for serving content.
You ask
Does that mean that:
request.getRequestDispatcher("/example/display.jsp").forward(request,
response); Will look at this URL to forward(request, response) to the
JSP:
http://localhost:9090/example/display.jsp?
No, it doesn't send an HTTP request, so the path has nothing to do with a URI. It's more of an internal path that the Servlet container will try to match with its various url-mappings for Servlets.
You also ask
Is there a way to print out what absolute URL getRequestDispatcher("relativePath") is addressing?
No. And it isn't exactly an absolute URL. It's a path that can be handled by some resource in the web application context.
After your edit, you addWebapp to your Tomcat instance.
tomcat.addWebapp(null, "/view2/example2", new File("src/com/example/view/example").getAbsolutePath());
You then send a request to
/view2/example2/read.jsp
I'm going to assume that read.jsp is in
src/com/example/view/example/
I believe it's in the publicly accessible part of the web application and therefore the Servlet container can render it and respond with it.
You've also added a webapp with addContext which seems to be similar to addWebapp
context = tomcat.addContext("", base.getAbsolutePath());
and added servlet mappings to this context.
Tomcat.addServlet(context, "example", new ExampleController());
context.addServletMapping("/example/*", "example");
I was wrong about the /example/* not being able to handle /example.
When you send a request to
/example
since the context path is "", the Context above will be used and the mapping will match the ExampleController registered above. Your Servlet code will execute and reach
request.getRequestDispatcher("/view2/example2/read.jsp").forward(request, response);
Note the javadoc of ServletRequest#getRequestDispatcher(String)
The pathname specified may be relative, although it cannot extend
outside the current servlet context.
In other words, this Servlet, ExampleController was registered in the ServletContext mapped to the context path "", ie. root. The path /view2/example2/read.jsp is referring to another context. Since this context doesn't have a mapping for it, it responds with 404.
You can get a reference to another web applications in a different context. You have to use ServletContext#getContext(String). For example
ServletContext otherContext = request.getServletContext().getContext("/view2/example2");
Now that you have the ServletContext, you can get a RequestDispatcher for a resource in that context.
otherContext.getRequestDispatcher("/read.jsp").forward(request, response);
since ServletContext#getRequestDispatcher(String) states
The pathname must begin with a / and is interpreted as relative to the current context root.
Final Answer:
getRequestDispatcher("path") will look at the directory set in the addWebapp method when referencing a JSP file. If a blank page or NullPointerException is displayed, ensure that you have done the following:
Remove all the addWebapp definitions.
Run addContext then addWebApp like this so they both point to ROOT:
File base = new File("src/com/example/view");
context = tomcat.addContext("", base.getAbsolutePath());
tomcat.addWebapp(null, "/", base.getAbsolutePath());
In the servlet point to the jsp using request.getRequestDispatcher("/example/read.jsp").forward(request, response); provided that the directory /example exists in "src/com/example/view".
I can map a single servlet to various url patterns in the web.xml file. When programming the servlet, I can then get which of those url patterns the request is matching, by getting the servlet path through request.getServletPath().
How can I achieve this with filters? When mapping a filter to various url patterns, is there a way to get what path the current request is matching?
Because my filter is currently working on content that is mapped to the DefaultServlet, the request.getServletPath() returns the whole path, and PathInfo is always null.
I am a newbie on servlet and filters, so I hope my question is clear and makes sense at all.
No, there isn't. You have to determine it yourself based on the request URI and a predefinied set/list/map of all known/supported paths. You can if necessary set those paths as <init-param> of the filter and process it during the init() method so that you can reuse it in the doFilter() method.
why
getRequestDispatcher(String path) of
the ServletRequest interface cannot
extend outside the current servlet
context
where as
getRequestDispatcher(String path) of
the ServletContext can use the
getContext(String uripath) method to
obtain RequestDispatcher for resources
in foreign contexts.
and how??
Please help
If you use an absolute path such as ("/index.jsp"), there is no difference.
If you use relative path, you must use HttpServletRequest.getRequestDispatcher(). ServletContext.getRequestDispatcher() doesn't allow it.
For example, if you receive your request on http://example.com/myapp/subdir,
RequestDispatcher dispatcher =
request.getRequestDispatcher("index.jsp");
dispatcher.forward( request, response );
Will forward the request to the page http://example.com/myapp/subdir/index.jsp.
In any case, you can't forward request to a resource outside of the context.
The request method getRequestDispatcher() can be used for referring to local servlets within single webapp.
Servlet context based getRequestDispatcher() method can used of referring servlets from other web applications deployed on SAME server.
request.getRequestDispatcher(“url”) means the dispatch is relative to the current HTTP request.Means this is for chaining two servlets with in the same web application
Example
RequestDispatcher reqDispObj = request.getRequestDispatcher("/home.jsp");
getServletContext().getRequestDispatcher(“url”) means the dispatch is relative to the root of the ServletContext.Means this is for chaining two web applications with in the same server/two different servers
Example
RequestDispatcher reqDispObj = getServletContext().getRequestDispatcher("/ContextRoot/home.jsp");
I would think that your first question is simply a matter of scope. The ServletContext is a much more broad scoped object (the whole servlet context) than a ServletRequest, which is simply a single request. You might look to the Servlet specification itself for more detailed information.
As to how, I am sorry but I will have to leave that for others to answer at this time.
Context is stored at the application level scope where as request is stored at page level i.e to say
Web Container brings up the applications one by one and run them inside its JVM. It stores a singleton object in its jvm where it registers anyobject that is put inside it.This singleton is shared across all applications running inside it as it is stored inside the JVM of the container itself.
However for requests, the container creates a request object that is filled with data from request and is passed along from one thread to the other (each thread is a new request that is coming to the server), also request is passed to the threads of same application.
I think you will understand it through these examples below.
Source code structure:
/src/main/webapp/subdir/sample.jsp
/src/main/webapp/sample.jsp
Context is: TestApp So the entry point: http://yourhostname-and-port/TestApp
Forward to RELATIVE path:
Using servletRequest.getRequestDispatcher("sample.jsp"):
http://yourhostname-and-port/TestApp/subdir/fwdServlet ==> \subdir\sample.jsp
http://yourhostname-and-port/TestApp/fwdServlet ==> /sample.jsp
Using servletContext.getRequestDispatcher("sample.jsp"):
http://yourhostname-and-port/TestApp/subdir/fwdServlet ==> java.lang.IllegalArgumentException: Path sample.jsp does not start with a "/" character
http://yourhostname-and-port/TestApp/fwdServlet ==> java.lang.IllegalArgumentException: Path sample.jsp does not start with a "/" character
Forward to ABSOLUTE path:
Using servletRequest.getRequestDispatcher("/sample.jsp"):
http://yourhostname-and-port/TestApp/subdir/fwdServlet ==> /sample.jsp
http://yourhostname-and-port/TestApp/fwdServlet ==> /sample.jsp
Using servletContext.getRequestDispatcher("/sample.jsp"):
http://yourhostname-and-port/TestApp/subdir/fwdServlet ==> /sample.jsp
http://yourhostname-and-port/TestApp/fwdServlet ==> /sample.jsp