Servlet mapping with multiple matches - servlets

I have a question according the mapping behaviour.
If there are these mappings given:
<servlet-mapping>
<servlet-name> ServletA </servlet-name>
<url-pattern> *.xml </url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name> ServletB </servlet-name>
<url-pattern> /result/* </url-pattern>
</servlet-mapping>
And there is this HTTP-Request:
/result/example.xml
Which servlet would be mapped and why?

Given your <servlet-mapping> configuration, the request for /result/example.xml would be handled by ServletB because a path match always trumps an extension match.
This is so because an extension match is considered to be a looser (not loser, though that works too :) constraint as it works site-wide when compared to a path match which targets a specific directory and its descendents and is hence more specific in nature.
The matching priority goes like this:
Exact path match
Wildcard path match (a longer match will trump a shorter one)
Extension match
Default servlet (configured with just / to handle all 404s)

Related

Invoke servlet Filters from another servlet

I'm working on a CMS.
My code is inside the doGet() function of a servlet invoked at url "/market". I want a HttpServletRequestWrapper that would pass through all filters set for url "/page".
I expect these filters would update the request, so that an annotation processor could later inject dependencies with correct values.
I'm in a Tomcat server, so I should be able to cast to the right special object, and I don't have to be compliant to other servers.
An associated question is that using req.getRequestDispatcher(path).forward(requestWrapper, responseWrapper);, I was expecting the filters to be invoked. Should they ?
The javadoc says:
This method allows one servlet to do preliminary processing of a
request
Filters are by default mapped on the REQUEST dispatcher only. The below example of a filter mapping
<filter-mapping>
<filter-name>yourFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
is implicitly equivalent to
<filter-mapping>
<filter-name>yourFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
This means, the filter is only triggered on the "raw" incoming request, not on a forwarded request.
There are three more dispatchers: FORWARD, INCLUDE and ERROR. The RequestDispatcher#forward() triggers the FORWARD dispatcher. If you'd like to let your filter hook on that as well, then just add it:
<filter-mapping>
<filter-name>yourFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Note that you need to explicitly specify the REQUEST dispatcher here, otherwise it would assume that you're overriding it altogether and are only interested in FORWARD dispatcher.
Inside the filter, if you'd like to distinguish between a REQUEST and FORWARD, then you can then check that by determining the presence of a request attribute keyed with RequestDispatcher#FORWARD_REQUEST_URI
String forwardRequestURI = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
if (forwardRequestURI != null) {
// Forward was triggered on the given URI.
}

web.xml localhost servlet mapping [duplicate]

I have manually configured web.xml for my application. Now, I'm facing issues while running my application. I'm trying to access my servlet from my jsp page. But, it is throwing error as page not found.
The servlets are placed under below folder location
<application folder>/WEB-INF/classes/<package>
So, what should be the entries for servlets in url-pattern and servlet-mapping. So that, servlet can be accessible through URL.
url-pattern is used in web.xml to map your servlet to specific URL. Please see below xml code, similar code you may find in your web.xml configuration file.
<servlet>
<servlet-name>AddPhotoServlet</servlet-name> //servlet name
<servlet-class>upload.AddPhotoServlet</servlet-class> //servlet class
</servlet>
<servlet-mapping>
<servlet-name>AddPhotoServlet</servlet-name> //servlet name
<url-pattern>/AddPhotoServlet</url-pattern> //how it should appear
</servlet-mapping>
If you change url-pattern of AddPhotoServlet from /AddPhotoServlet to /MyUrl. Then, AddPhotoServlet servlet can be accessible by using /MyUrl. Good for the security reason, where you want to hide your actual page URL.
Java Servlet url-pattern Specification:
A string beginning with a '/' character and ending with a '/*'
suffix is used for path mapping.
A string beginning with a '*.'
prefix is used as an extension mapping.
A string containing only the '/' character indicates the "default" servlet of the application. In this case the servlet path
is the request URI minus the context path and the path info is
null.
All other strings are used for exact matches only.
Reference : Java Servlet Specification
You may also read this Basics of Java Servlet
Servlet-mapping has two child tags, url-pattern and servlet-name. url-pattern specifies the type of urls for which, the servlet given in servlet-name should be called. Be aware that, the container will use case-sensitive for string comparisons for servlet matching.
First specification of url-pattern a web.xml file for the server context on the servlet container at server .com matches the pattern in <url-pattern>/status/*</url-pattern> as follows:
http://server.com/server/status/synopsis = Matches
http://server.com/server/status/complete?date=today = Matches
http://server.com/server/status = Matches
http://server.com/server/server1/status = Does not match
Second specification of url-pattern A context located at the path /examples on the Agent at example.com matches the pattern in <url-pattern>*.map</url-pattern> as follows:
http://server.com/server/US/Oregon/Portland.map = Matches
http://server.com/server/US/server/Seattle.map = Matches
http://server.com/server/Paris.France.map = Matches
http://server.com/server/US/Oregon/Portland.MAP = Does not match, the extension is uppercase
http://example.com/examples/interface/description/mail.mapi =Does not match, the extension is mapi rather than map`
Third specification of url-mapping,A mapping that contains the pattern <url-pattern>/</url-pattern> matches a request if no other pattern matches. This is the default mapping. The servlet mapped to this pattern is called the default servlet.
The default mapping is often directed to the first page of an application. Explicitly providing a default mapping also ensures that malformed URL requests into the application return are handled by the application rather than returning an error.
The servlet-mapping element below maps the server servlet instance to the default mapping.
<servlet-mapping>
<servlet-name>server</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
For the context that contains this element, any request that is not handled by another mapping is forwarded to the server servlet.
And Most importantly we should Know about Rule for URL path mapping
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.
Reference URL Pattern

Filter Liferay HttpRequest

I would like to filter (modify) HttpRequest, which is coming to target Liferay Servlet, intercept it and add some attributes. (for example User) and then redirect (forward) the request to the target servlet. I create new servlet that should work like interceptor, add the attribute (request.setAttribute("user", User)) and then either dispatcher.forward or response.redirect... This is only for testing purposes to be able to call some liferay functionality from tests.
The problem is that Liferay is filtering the request and add there its 7 attributes. I tried also create SimpleFilter, but its not called when target servlet is called, only when I create my own Servlet which extends HttpServlet.
So the question is, is it possible to tell liferay not to filter the requests or more important not to remove the attributes from the request? I have debugged the Liferay source code, catch the Filter Chain and on the 1. filter I see there original request, and at the end the requests contains those Liferay attributes.
Many thanks.
The target servlet is defined like this:
<servlet>
<servlet-name>targetServlet</servlet-name>
<servlet-class>com.liferay.portal.kernel.servlet.PortalDelegateServlet</servlet-class>
<init-param>
<param-name>servlet-class</param-name>
<param-value>org.springframework.web.context.support.HttpRequestHandlerServlet</param-value>
</init-param>
<init-param>
<param-name>sub-context</param-name>
<param-value>targetServlet</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Handler method mappings with Spring 3.2.6

I'm trying to learn web app development with Spring MVC framework and I'm not completely clear about how controller mappings work. It will be better if I show my config and code first and then explain what I don't understand.
Here's mapping in my web.xml:
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
mapping in my controller class:
#Controller
#RequestMapping("/main/courses")
public class CourseController {
...
and mapping of the method in question in this controller:
#RequestMapping(value="", method = RequestMethod.GET)
public String getCourses(Model model) {
...
As you can see, value attribute is set to empty quotes and this is the only way this mapping works. If I change value attribute to "/", I get 404 error. I have other mappings in this controller that work fine, for example value="/add". The only problem is when I try to map to the root of this controller.
Is value="" a valid value? Why value="/" doesn't work?
The #RequestMapping used at the class level sets the base path mapping that all the handlers methods will resolved against.
In your example, that's
#RequestMapping("/main/courses")
When you specify another #RequestMapping on a method like
#RequestMapping("/add")
that is added as a path element. So the request would need to be to
/main/courses/add
If you have another like so
#RequestMapping("/")
then you add a new path element but the element itself is empty. So the request needs to be to
/main/courses/
With a mapping like
#RequestMapping("")
there is no new path element, it's just the empty String. So the request would need to be to
/main/courses

Servlet Mapping URL pattern

webapps
|
|----helloworld
|
|----WEB-INF
|
|-----classes-HelloWorldServlet.class
|-----lib----servlet-api.jar
|-----web.xml
The above is my directory structure. Now in web.xml i don't know what to give in url-pattern for servlet mapping. What should i give there? Which is the url pattern?
The mechanism for mapping servlets is not relevant to the directory structure, as skaffman noted.
Basically, you have two things in web.xml (regarding servlets):
the <servlet> tag, which defines the alias for the servlet, and its fully-qualified name (for example com.foo.pkg.YourServlet)
the <servlet-mapping> which specifies a url-pattern for a given alias (taken from the <servlet> definitions).
As the name suggest, the url-pattern denotes what URL portion should make the servlet be called. So if you map a given servlet to the url-pattern /myfirstserlet, it will be accessible when the user opens http://localhost:8080/helloword/myfirstservlet, where the first part is the host name and the port, followed by the context name (the name of your webapp), and then the url-pattern
Note: you are currently using the default package (i.e. no package) for your servlet. This is discouraged, so give it some package name. (and put it in WEB-INF/classes/com/foo/pkg/). This is done via specifying package com.foo.pkg;

Resources