Skip to content

Fix #20 - add support for <welcome-servlet> #881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
<xsd:annotation>
<xsd:documentation>

Copyright (c) 2009, 2024 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2009, 2025 Oracle and/or its affiliates and others.
All rights reserved.

This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -1337,9 +1338,11 @@
<xsd:annotation>
<xsd:documentation>

The welcome-file element contains a file name to use
as a default welcome file, such as index.html

The welcome-file element contains a file name to use as a
welcome file, such as index.html, that must match an
actual file or be an exact or prefix match to a servlet
URL pattern.

</xsd:documentation>
</xsd:annotation>
</xsd:element>
Expand All @@ -1348,9 +1351,10 @@
<xsd:annotation>
<xsd:documentation>

The welcome-servlet element contains servlet name to use
as a default welcome servlet, such as index.do

The welcome-servlet element contains a file name to use as
a welcome file, such as index.do, that must match a
servlet mapping other than that for the default servlet.

</xsd:documentation>
</xsd:annotation>
</xsd:element>
Expand Down
70 changes: 49 additions & 21 deletions spec/src/main/asciidoc/servlet-spec-body.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -3726,9 +3726,15 @@ In addition to these annotations all the
annotations defined in <<Annotations and Resource Injection>> will continue
to work in the context of these new annotations.

By default all applications will have
`index.htm[l]` and `index.jsp` in the `welcome-file-list`. The
descriptor may to be used to override these default settings.
By default all applications will have a `welcome-file-list` of:
```
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
```
The descriptor may to be used to override these default settings.

The order in which the listeners, servlets
are loaded from the various framework jars / classes in the
Expand Down Expand Up @@ -4323,7 +4329,7 @@ but with different `<load-on-startup>` elements, and the same servlet is
also declared in the main `web.xml`, but without any
`<load-on-startup>`, then an error must be reported.

... `<welcome-file>` declarations are additive.
... `<welcome-file>` and `<welcome-servlet>` declarations are additive.

... `<servlet-mapping>` elements with the same
`<servlet-name>` are additive across `web-fragments`.
Expand Down Expand Up @@ -5442,7 +5448,7 @@ the following types of configuration and deployment information:

* MIME Type Mappings

* Welcome File list
* Welcome Resources List

* Error Pages

Expand Down Expand Up @@ -5653,10 +5659,10 @@ the container. The mechanism described in
may be used to specify filters that are applied before an error response
is generated.

=== Welcome Files
=== Welcome Resources

Application Developers can define an
ordered list of partial URIs called welcome files in the web application
ordered list of partial URIs called welcome resources in the web application
deployment descriptor. The deployment descriptor syntax for the list is
described in the web application deployment descriptor schema.

Expand All @@ -5673,26 +5679,40 @@ where `directory` is an entry in the WAR that is not mapped to a
servlet or JSP page, is returned to the client as
`host:port/webapp/directory/index.html`.

If a web container receives a valid partial
request, the web container must examine the welcome file list defined in
the deployment descriptor. The welcome file list is an ordered list of
partial URLs with no trailing or leading `"/"`. The web server must append
each welcome file in the order specified in the deployment descriptor to
the partial request and check whether a static resource in the WAR is
mapped to that request URI. If no match is found, the web server MUST
again append each welcome file in the order specified in the deployment
descriptor to the partial request and check if a servlet is mapped to
that request URI. The web container must send the request to the first
resource in the WAR that matches.

If a matching welcome file is found in the manner described, the container may
Deployment descriptors that declare a version of 6.2 or later, may define
welcome files or welcome servlets. Deployment descriptors that declare an
earlier version than 6.2 define legacy welcome files.

The web container identifies the servlet to serve the request using the process
described in the following paragraphs. The process stops when the first match is
found.

For each welcome resource in the order it appears in the deployment descriptor:
- append the partial URI to the request URI to create a welcome URI
- if the welcome URI has an exact match to a servlet mapping, send the request
to that servlet
- if the welcome URI has a prefix match to a servlet mapping, send the request
to that servlet
Comment on lines +5692 to +5695
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we mapping welcome-file elements in 6.2 descriptors to servlets? Surely these mappings should only be for welcome-servlet resources and perhaps legacy welcome files?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second bullet (exact matching) is to handle pre-compiled JSPs.
The third bullet (prefix mapping) is probably unnecessary. There might be some backwards compatibility edge cases but I don't have a concrete argument for keeping it.

I see the point re *.jsp. I think that is a wording issue. How about this instead of the last bullet for the first iteration:

  • if a static file exists in the web application for the welcome URI, map the URI to a servlet using the standard mapping rules (including the default servlet)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think that for all welcome-file resources, then the file must exist. This would work for precompiled JSPs because the index.jsp file should still be there. Then only for welcome-servlet resources do we look for a match regardless of the files existence?

I'm AFK until Monday, so can this wait until then for some more considered discussion?

- if the welcome resource is a welcome file or legacy welcome file and a static
file exists in the web application for the welcome URI, send the request to
that static resource
- if the welcome resource is a welcome servlet and a servlet mapping (other than
the default servlet) matches the welcome URI, send the request to that servlet

If no match is found then for each legacy welcome file in the order they appear
in the deployment descriptor:
- append the partial URI to the request URI to create a welcome URI
- if a servlet mapping (other than the default servlet) matches the welcome URI,
send the request to that servlet

If a matching welcome resource is found in the manner described, the container may
send the request to the welcome resource with a forward, a redirect, or a
container specific mechanism that is indistinguishable from a direct request. In
later case, the request information (e.g. `getRequestURI()`) presented to the
filter chain and the servlet will include the welcome file since filter mapping
occurs after welcome file mapping.

If no matching welcome file is found in the
If no matching welcome resource is found in the
manner described, the container may handle the request in a manner it
finds suitable. For some configurations this may mean returning a
directory listing or for others returning a `404` response.
Expand Down Expand Up @@ -8560,6 +8580,14 @@ can be mapped to a physical path but the physical path does not exist.
link:https://github.com/jakartaee/servlet/issues/18[Issue 18]::
Clarify the behaviour of `HttpServletRequest.getContextPath()`.

link:https://github.com/jakartaee/servlet/issues/20[Issue 20]::
Introduce a new element, `<welcome-servlet>` to the web.xml schema that can be
used to specify a welcome resource that is not backed by a file but is backed by
a servlet. With the introduction of this new element, the rules for mapping
welcome resources have been updated to differentiate welcome resources that are
expected to be backed by files and those that are only expected to be backed by
a servlet.

link:https://github.com/jakartaee/servlet/issues/25[Issue 25]::
Document the risks created by a filter modifying the `ServletResponse`. Add a
recommendation that filters that modify the `ServletResponse` should endeavour
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package servlet.tck.spec.welcomefiles;

import java.io.IOException;
import java.io.PrintWriter;

import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

/**
* Simple servlet used for the welcome servlet tests.
*/
public class IndexServletDo extends GenericServlet {

private static final long serialVersionUID = 1L;

@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
PrintWriter pw = response.getWriter();
// Test looks for this string to confirm the welcome servlet was used.
pw.println("INDEX from *.do");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package servlet.tck.spec.welcomefiles;

import servlet.tck.common.client.AbstractTckTest;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

public class WelcomeFilesFileTests extends AbstractTckTest {

/**
* Deployment for the test.
*
* @return The web archive to test.
*
* @throws Exception If an error occurs creating the archive.
*/
@Deployment(testable = false)
public static WebArchive getTestArchive() throws Exception {
WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "servlet_spec_welcomefiles_file_web.war")
.addClasses(IndexServletDo.class)
.setWebXML(WelcomeFilesFileTests.class.getResource("servlet_spec_welcomefiles_file_web.xml"));
Arrays.asList("legacy/index.html")
.forEach(s -> webArchive.addAsWebResource("spec/welcomefiles/" +s, s));
return webArchive;
}


/*
* Test should trigger a 404 since index.do is configured as a welcome file and no such file exists.
*/
@Test
public void partialfoundLegacy() throws Exception {
TEST_PROPS.get().setProperty(FOLLOW_REDIRECT, "follow_redirect");
TEST_PROPS.get().setProperty(STATUS_CODE, NOT_FOUND);
TEST_PROPS.get().setProperty(SEARCH_STRING, "<html");
TEST_PROPS.get().setProperty(APITEST, "legacy");
invoke();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package servlet.tck.spec.welcomefiles;

import servlet.tck.common.client.AbstractTckTest;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

public class WelcomeFilesLegacyTests extends AbstractTckTest {

/**
* Deployment for the test.
*
* @return The web archive to test.
*
* @throws Exception If an error occurs creating the archive.
*/
@Deployment(testable = false)
public static WebArchive getTestArchive() throws Exception {
WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "servlet_spec_welcomefiles_legacy_web.war")
.addClasses(IndexServletDo.class)
.setWebXML(WelcomeFilesLegacyTests.class.getResource("servlet_spec_welcomefiles_legacy_web.xml"));
Arrays.asList("legacy/index.html")
.forEach(s -> webArchive.addAsWebResource("spec/welcomefiles/" +s, s));
return webArchive;
}


/*
* Test should trigger a 404 since default.jsp is a valid welcome file but does not exist.
*/
@Test
public void partialfoundLegacy() throws Exception {
TEST_PROPS.get().setProperty(FOLLOW_REDIRECT, "follow_redirect");
TEST_PROPS.get().setProperty(STATUS_CODE, NOT_FOUND);
TEST_PROPS.get().setProperty(SEARCH_STRING, "<html");
TEST_PROPS.get().setProperty(APITEST, "legacy");
invoke();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package servlet.tck.spec.welcomefiles;

import servlet.tck.common.client.AbstractTckTest;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

public class WelcomeFilesServletTests extends AbstractTckTest {

/**
* Deployment for the test.
*
* @return The web archive to test.
*
* @throws Exception If an error occurs creating the archive.
*/
@Deployment(testable = false)
public static WebArchive getTestArchive() throws Exception {
WebArchive webArchive = ShrinkWrap.create(WebArchive.class, "servlet_spec_welcomefiles_servlet_web.war")
.addClasses(IndexServletDo.class)
.setWebXML(WelcomeFilesServletTests.class.getResource("servlet_spec_welcomefiles_servlet_web.xml"));
Arrays.asList("legacy/index.html")
.forEach(s -> webArchive.addAsWebResource("spec/welcomefiles/" +s, s));
return webArchive;
}


/*
* Test should use the index.do mapping since it is configured as a welcome-servlet.
*/
@Test
public void partialfoundServlet() throws Exception {
TEST_PROPS.get().setProperty(FOLLOW_REDIRECT, "follow_redirect");
TEST_PROPS.get().setProperty(SEARCH_STRING, "INDEX from *.do");
TEST_PROPS.get().setProperty(APITEST, "legacy");
invoke();
}
}
Loading