Web applications that use a servlet mapping for their welcome-file are ignored and the server returns either a directory listing or a 404 if the listing is disabled. I have JSF servlet defined and a servlet-mapping for *.jsf to go to the FacesServlet. I have "index.jsf" listed as by welcome-file and I get a 404 with directory listing disabled. I also have a custom servlet defined with its mapping and set the welcome-file to its mapping and get a 404 as well.
You'll need a physical file called index.jspf as a "placeholder" for the action to occur. The file placeholder can be 0 bytes if you want. Or you can write a filter to detect a directory is requested and forward to index.jspf. The reason for needing a physical file is the servlet container is to allow for multiple welcome file types. Imagine I had welcome files of index.jsp, then index.html, then index.htm. Imagine I have a directory that is missing index.jsp, but has an index.html. If I always tried to invoke index.jsp like the welcome file list says, then the JSP servlet will return a 404 since there is no mechanism in the servlet api to defer that decision. IIRC - there are more discussions of this in the archives, but those talks are REALLY old.
In the scenario that you described (the multiple welcome files index.jsp, index.html, etc), I would think that the container should try each in succession until it finds one that is valid. The mechanism for "defering that decision" would have to be built into the DefaultServlet. This means that if a developer wanted to forward a user to some random servlet, "/dosomething", or to a Struts action, or to a JSF page, I would have to create some dummy file in which all it did was forward the request? This has been an issue with other jsp/servlet containers in the past and the developer community fixed it. I was hoping that the Tomcat community would provide a fix for this. Instead it looks like if I want to run my apps on Tomcat, I will have to modify them all...
The "other" jsp/servlet containers that I was referring to is Jetty. Weblogic already handles this now. But since the Tomcat catalina core is used in so many other containers (Geronimo, Glassfish), this has become an issue on those containers as well.
Hi, Dear devs, Has this bug been resolved? I am instreseting in it, where can I get a snapshot build to have a try? Was that committed to 7.0 trunk or 6.0 trunk? -Rex
From my point of view, I don't like the work around to create a dummy file to help request the servlet. The logic I prefer is: 1. scan welcome list from actual files. If one is found, use it. 2. If none are found, try servlet mappings, for example: if there is a /Hello in weclome list: <welcome-file-list> <welcome-file>/Hello</welcome-file> </welcome-file-list> we should find in the wel.xml to look if there is a <servlet-mapping> hold a <url-pattern> that can match "/Hello", such as <url-pattern>/Hello</url-pattern> or <url-pattern>/*</url-pattern> Any thoughts? -Rex (In reply to comment #1) > You'll need a physical file called index.jspf as a "placeholder" for the action > to occur. The file placeholder can be 0 bytes if you want. Or you can write a > filter to detect a directory is requested and forward to index.jspf. > > The reason for needing a physical file is the servlet container is to allow for > multiple welcome file types. > > Imagine I had welcome files of index.jsp, then index.html, then index.htm. > > Imagine I have a directory that is missing index.jsp, but has an index.html. If > I always tried to invoke index.jsp like the welcome file list says, then the > JSP servlet will return a 404 since there is no mechanism in the servlet api to > defer that decision. > > IIRC - there are more discussions of this in the archives, but those talks are > REALLY old.
This wasn't fixed. SRV.9.10 makes it clear the servlet mappings in web.xml should be supported. Until this gets fixed, you can use the workaround Tim describes. Patches are always welcome.
This issue came up in jetty recently and it became clear in e.g. discussions that the spec wording interpreted literally implies a non-workable solution. The wording may be clarified in servlet 3.0, meanwhile see http://jira.codehaus.org/browse/JETTY-936 for the apparent consensus on what is intended.
This might work as a patch to org.apache.tomcat.util.http.mapper.Mapper - add it before // Rule 7 -- Default servlet and after // Rule 4 -- Welcome resources processing for servlets // DAMMIT - welcome file processing - take 2 // take first matching welcome match // its a copy of rule 4 since it needs to do less if (mappingData.wrapper == null) { boolean checkWelcomeFiles = checkJspWelcomeFiles; if (!checkWelcomeFiles) { char[] buf = path.getBuffer(); checkWelcomeFiles = (buf[pathEnd - 1] == '/'); } if (checkWelcomeFiles) { for (int i = 0; (i < context.welcomeResources.length) && (mappingData.wrapper == null); i++) { path.setOffset(pathOffset); path.setEnd(pathEnd); path.append(context.welcomeResources[i], 0, context.welcomeResources[i].length()); path.setOffset(servletPath); internalMapExtensionWrapper(extensionWrappers, path, mappingData); if (mappingData.wrapper == null && context.defaultWrapper != null) { mappingData.wrapper = context.defaultWrapper.object; mappingData.requestPath.setChars (path.getBuffer(), path.getStart(), path.getLength()); mappingData.wrapperPath.setChars (path.getBuffer(), path.getStart(), path.getLength()); mappingData.requestPath.setString(pathStr); mappingData.wrapperPath.setString(pathStr); } } path.setOffset(servletPath); path.setEnd(pathEnd); } }
hi Tim, I tried adding this, but it does not work... btw, I added one line: String pathStr = path.toString(); to pass compiling. -Rex (In reply to comment #8) > This might work as a patch to org.apache.tomcat.util.http.mapper.Mapper - add > it before // Rule 7 -- Default servlet and after // Rule 4 -- Welcome > resources processing for servlets > > // DAMMIT - welcome file processing - take 2 > // take first matching welcome match > // its a copy of rule 4 since it needs to do less > if (mappingData.wrapper == null) { > boolean checkWelcomeFiles = checkJspWelcomeFiles; > if (!checkWelcomeFiles) { > char[] buf = path.getBuffer(); > checkWelcomeFiles = (buf[pathEnd - 1] == '/'); > } > if (checkWelcomeFiles) { > for (int i = 0; (i < context.welcomeResources.length) > && (mappingData.wrapper == null); i++) { > path.setOffset(pathOffset); > path.setEnd(pathEnd); > path.append(context.welcomeResources[i], 0, > context.welcomeResources[i].length()); > path.setOffset(servletPath); > > internalMapExtensionWrapper(extensionWrappers, > path, mappingData); > if (mappingData.wrapper == null > && context.defaultWrapper != null) { > mappingData.wrapper = > context.defaultWrapper.object; > mappingData.requestPath.setChars > (path.getBuffer(), path.getStart(), > path.getLength()); > mappingData.wrapperPath.setChars > (path.getBuffer(), path.getStart(), > path.getLength()); > mappingData.requestPath.setString(pathStr); > mappingData.wrapperPath.setString(pathStr); > } > } > > path.setOffset(servletPath); > path.setEnd(pathEnd); > } > > }
Created attachment 24065 [details] Patch against tomcat 6.0 Here is a working patch. (At least in a simple test case) Previous attempt was wrong on soooo many levels.
Hi Tim, I tried again.. but still not work. I am not sure if we are on the same page, this is my web.xml: <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...> <welcome-file-list> <welcome-file>/Hello</welcome-file> </welcome-file-list> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.abc.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Hello</url-pattern> </servlet-mapping> </web-app> (In reply to comment #10) > Created an attachment (id=24065) [details] > Patch against tomcat 6.0 > > Here is a working patch. (At least in a simple test case) Previous attempt was > wrong on soooo many levels.
and I did not create a "placeholder". -Rex
Hi, Tim if I set <welcome-file-list> <welcome-file>Hello</welcome-file> ## not "/Hello" here </welcome-file-list> it seems work correctly. I tried tracking the code, and if use "Hello", the mappingData.wrapper != null But, if use "/Hello", the mappingData.wrapper = = null. Then will run into the new logic, why not don't allow "/Hello", which is actually a servlet mapping here? -Rex
Because welcome files define file names not servlet mappings. It needs to be Hello to be consistent.
Ahhh ... I see the issue. My patch was to handle the case for file extension matches. For example: index.jsf (which is what was for the original report). Comment 5 could be considered a "different bug". But in this case: - Welcome file is /Hello - Servlet exists mapped to /Hello - So when calculating welcome files - /Hello (while not existing as a file) is an exact match - so that should be used. time permitting - I'll take a look later today.
Given welcome files are defined without the leading / - ie 'index.html' rather than '/index.html' - I still think to match a servlet mapping of '/Hello' the welcome file setting should be 'Hello'. This would also be consistent with the current workaround of creating a dummy file.
Created attachment 24088 [details] War file demonstrating exact mappings Exact mappings dont need a physical file. (At least with the way the mapper works right now) Attached is example working on tomcat 6 as a timesaver ... here is the web.xml <servlet> <servlet-name>fooo</servlet-name> <jsp-file>/foo.jsp</jsp-file> </servlet> <servlet-mapping> <servlet-name>fooo</servlet-name> <url-pattern>/TIMMAY</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>TIMMAY</welcome-file> </welcome-file-list> If / is requested - then the servlet named fooo (path=/TIMMAY) will be used. All this is without the patch I supplied. For Rex Wang (comments 5,11,12) - I think you have a config issue which needs moved to the user list so they can help you.
All right, many thanks, Tim and Mark! -Rex
Applied this to trunk - so it should make its way into tomcat7 http://svn.apache.org/viewvc?rev=809596&view=rev I am not proposing this for backport to tomcat 6. But wouldn't be against it if it were proposed. So I'm moving this to enhancement.
Backporting this to 6.0.x is going to cause some nasty surprises for users such as bug 49422. Therefore, I think this should be fixed only in Tomcat 7. I am therefore moving this to Tomcat 7 and marking it as fixed.