Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapping a specific servlet to be the default servlet in Tomcat

I am trying to implement a servlet that gets raw requests, and decide either to process them, or forward them to another backend server. It is similar to a load-balancer, where a received request is forwarded to one of the (in my case 2) destinations. One of the destination is remote (on another host). Furthermore, the requests could come to the root (http://mycompany.com/).

Since I want to get raw requests, I implemented my own servlet (subclassing HttpServlet), and that works great. My servlet looks like:

public class MyProxyServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        processOrForward(req, resp);
    }
    // also doGet(), doHead(), ...
}

Since the service I want to process may send requests to the root, I would like to map my servlet to be the default servlet, thereby receiving any request that does not have an explicit servlet mapping. Assume my servlet's name is "myservlet", and is running along side of another servlet "foo", I expect all requests in the form of http://mycompany.com/foo/... to be delivered to foo, and everything else (e.g., /, /bar/..., /myservlet/...) to "myservlet". Looking at earlier posts (eg., root mapping here and here, or url rewriting here), I thought I figured it out, but it does not work.

Here is my web.xml:

<web-app>
  <servlet>
    <servlet-name>ProxyServlet</servlet-name>
    <servlet-class>com.mycompany.MyProxyServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>ProxyServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

In the above web.xml, for url-pattern I tried

"/" and "/*" and empty (i.e., <url-pattern></url-pattern>), all behave the same -->
    Requests to root (/)goes to tomcat's default servlet
    Requests to /myservlet/... are handled by "myservlet"
    Requests to /fubar/... are always 404

Is there a way of turning my servlet to be the default. I.e., any request that does not map specifically to a servlet comes to mine (it is even acceptable to receive all requests, since I can deploy this servlet in its own container). In case it matters, I am using Tomcat 7.0.30 on Ubuntu 12.10.

like image 699
Virtually Real Avatar asked Jan 08 '13 20:01

Virtually Real


2 Answers

This should be useful to you.

From the Java™ Servlet Specification Version 3.1 (JSR 340)

Chapter 12. Mapping Requests to Servlets

12.2 Specification of Mappings

In the Web application deployment descriptor, the following syntax is used to define mappings:

  • 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.

  • The empty string ("") is a special URL pattern that exactly maps to the application's context root, i.e., requests of the form http://host:port/<contextroot>/. In this case the path info is / and the servlet path and context path is empty string ("").

  • 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.


As an addition, read this nice explanation with short examples from the book Head First Servlets & JSP: Passing the Sun Certified Web Component Developer Exam (2nd edition) (quote):

The THREE types of <url-pattern> elements

1) EXACT match

Example:
<url-pattern>/Beer/SelectBeer.do</url-pattern>

  • MUST begin with a slash (/).
  • Can have an extension (like .do), but it’s not required.

2) DIRECTORY match

Example:
<url-pattern>/Beer/*</url-pattern>

  • MUST begin with a slash (/).
  • Always ends with a slash/asterisk (/*).

3) EXTENSION match

Example:
<url-pattern>*.do</url-pattern>

  • MUST begin with an asterisk (*) (NEVER with a slash).
  • After the asterisk, it MUST have a dot extension (.do, .jsp, etc.).


IMPORTANT NOTE:
The URL patterns represent logical / virtual structure, i.e. the patterns (paths) specified does not need to exist physically.


UPDATE

If you want, as you say in your comment,

I want host:port to hit my servlet, not the default tomcat servlet

then see the solution here:
How do I make my web application be the Tomcat default application

In other words, what you want is a path without application context, which implies the application context of the Tomcat default application.

Quote from the above link:

In a standard Tomcat installation, you will notice that under the same directory (CATALINA_BASE)/webapps/, there is a directory called ROOT (the capitals are important, even under Windows). That is the residence of the current Tomcat default application, the one that is called right now when a user calls up http://myhost.company.com[:port]. The trick is to put your application in its place.

like image 126
informatik01 Avatar answered Oct 19 '22 23:10

informatik01


I am not sure did I understood what you want but probably intercept 404 is what you want to do, then redirect where you want.

I've came here to forum because I have strange problem with tomcat 7, mine is doing just what you want ;)

This is only one way how I can have root, EMPTY

<servlet-mapping>
    <servlet-name>Default</servlet-name>
    <url-pattern></url-pattern>
</servlet-mapping>

That way : anything is redirected to this servlet, including images, etc, for example, I open another page, this show this one, root, then I can see in log 4 more request to same page, 3 for css and one for image.

<servlet-mapping>
    <servlet-name>Default</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
like image 34
Dejan Avatar answered Oct 19 '22 23:10

Dejan