How does the `getServletMapping()` affects the URL in Spring WebMVC? [duplicate] - spring-mvc

I have a web.xml file with content:
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>org.mycompany.test1</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>org.mycompany.test2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/path/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/path/test/*</url-pattern>
</servlet-mapping>
I tried requests
.../path/test/abc
.../path/test
Both requests are processed by Servlet2. Why?
UPDATE
Thank you guys for your help.
I realised that behaviour depends on order of servlet-mapping declaration.
I tried this web.xml
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>org.mycompany.test1</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>org.mycompany.test2</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet3</servlet-name>
<servlet-class>org.mycompany.test3</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet4</servlet-name>
<servlet-class>org.mycompany.test4</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/path/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/path/test/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet3</servlet-name>
<url-pattern>/path/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet4</servlet-name>
<url-pattern>/path</url-pattern>
</servlet-mapping>
results:
.../path/test/abc - servlet2
.../path/test/ - servlet2
.../path/test - servlet2
.../path/abc - servlet3
.../path/ - servlet4
.../path - servlet4

From Servlet 3.0 specification, this is how the web container must locate the servlet after receiving a request (emphasis mine):
The path used for mapping to a servlet is the request URL from the
request object minus the context path and the path parameters. The
URL path mapping rules below are used in order. The first successful
match is used with no further matches attempted:
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.
The container must use case-sensitive string comparisons for matching.
You should also look the specification of mappings (given below):
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
Let us look at examples now. Consider the following set of mappings:
Path Pattern Servlet
/foo/bar/* servlet1
/baz/* servlet2
/catalog servlet3
*.bop servlet4
The following behavior would result:
Incoming Path Servlet Handling Request
/foo/bar/index.html servlet1
/foo/bar/index.bop servlet1
/baz servlet2
/baz/index.html servlet2
/catalog servlet3
/catalog/index.html “default” servlet
/catalog/racecar.bop servlet4
/index.bop servlet4
Note that in the case of /catalog/index.html and /catalog/racecar.bop, the
servlet mapped to “/catalog” is not used because the match is not exact.
Now coming to your problem :)
/path/test belongs to the 5th point of specification of mappings. Which means only the paths ending in /path/test will target servlet1.
However /path/test/* qualifies for the first point of the same specification. This means that:
.../path/test will be handled by servlet1 and
.../path/test/abc will be handled by servlet2
Which was verified by me in a test application.

Your paths conflict.
Both of your paths mean the same, the '/*' doesn't make any difference.
Apparently then when you try your path, the last match (servlet2) is executed.
You usually put in a path with the Servlet name, like for example:
/path/test/servlet1
/path/test/servlet2

Related

Deploying an ear with web.xml on websphere changes the web.xml or create web_merged.xml with changed attributes for multi-part

I have an ear file built which has a war file inside.The war has web.xml which has servlet defined:
<servlet>
<servlet-name>ExcelDownload</servlet-name>
<servlet-class>web.ExcelDownload</servlet-class>
<multipart-config>
**<!--<max-file-size>1048576</max-file-size> -->**
</multipart-config>
</servlet>
The problem here is my in ear file max-file-size is commented that means there are no attributes defined for the multipart-config. But when I deploy my ear on WebSphere 8.5.5.9, it changes my web.xml to:
<servlet>
<servlet-name>ExcelDownload</servlet-name>
<servlet-class>com.ofss.infra.web.ExcelDownload</servlet-class>
<multipart-config>
<max-file-size>0</max-file-size>
**<max-request-size>0</max-request-size>**
<file-size-threshold>0</file-size-threshold>
</multipart-config>
</servlet>
Since the max-file-size attribute is defined as zero in web.xml I am not not able to use HTTP request to upload the file to server.
I need help on to understand why the attribute is being added by WAS though its not available in ear. I did my digging I tried during deployment not to use metadata-complete attribute to false then instead of changing web.xml WAS has created a new file web_merged.xml (this has max-file-size set to zero) and am still facing the issue.

Weblogic upgrade to 12c: deployment fails because url mapped to multiple servlet

I've recently setup a new Weblogic 12c environment. On deploying an application that I know works in Weblogic 11g I get the error "The url-pattern /resources/* in web application is mapped to multiple Servlets."
The mapping it's referring to is in the web.xml inside the application.ear that's being deployed, but it's only mapped once:
<servlet-mapping>
<servlet-name>velocity</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
The project doesn't contain any other references to the url pattern /resources/*, can someone explain where the duplicated mapping is coming from and how I can work around it?
The closest issue I could find is this: https://bugster.forgerock.org/jira/si/jira.issueviews:issue-html/OPENAM-7947/OPENAM-7947.html, which has been marked as unreproducible.
Full stack trace from deployment:
<Error> <Deployer> <BEA-149205> <Failed to initialize the application "<application_name>" due to error weblogic.application.ModuleException: weblogic.management.DeploymentException: [HTTP:101401]The url-pa
ttern /resources/* in web application <application_name> is mapped to multiple Servlets.
weblogic.application.ModuleException: weblogic.management.DeploymentException: [HTTP:101401]The url-pattern /resources/* in web application <application_name> is mapped to multiple Servlets.
at weblogic.application.internal.ExtensibleModuleWrapper.prepare(ExtensibleModuleWrapper.java:114)
at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:100)
at weblogic.application.internal.flow.ModuleStateDriver$1.next(ModuleStateDriver.java:192)
at weblogic.application.internal.flow.ModuleStateDriver$1.next(ModuleStateDriver.java:187)
at weblogic.application.utils.StateMachineDriver$ParallelChange.run(StateMachineDriver.java:83)
at weblogic.application.utils.StateMachineDriver.nextStateInParallel(StateMachineDriver.java:144)
at weblogic.application.internal.flow.ModuleStateDriver.parallelPrepare(ModuleStateDriver.java:46)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:75)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:55)
at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:731)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:243)
at weblogic.application.internal.EarDeployment.prepare(EarDeployment.java:66)
at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:158)
at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:65)
at weblogic.deploy.internal.targetserver.AppDeployment.prepare(AppDeployment.java:158)
at weblogic.management.deploy.internal.DeploymentAdapter$1.doPrepare(DeploymentAdapter.java:41)
at weblogic.management.deploy.internal.DeploymentAdapter.prepare(DeploymentAdapter.java:193)
at weblogic.management.deploy.internal.AppTransition$1.transitionApp(AppTransition.java:31)
at weblogic.management.deploy.internal.ConfiguredDeployments$2.doItem(ConfiguredDeployments.java:684)
at weblogic.management.deploy.internal.parallel.BucketInvoker.invoke(BucketInvoker.java:138)
at weblogic.management.deploy.internal.ConfiguredDeployments.transitionAppsParallel(ConfiguredDeployments.java:692)
at weblogic.management.deploy.internal.ConfiguredDeployments.prepare(ConfiguredDeployments.java:322)
at weblogic.management.deploy.internal.ConfiguredDeployments.deploy(ConfiguredDeployments.java:202)
at weblogic.management.deploy.internal.DeploymentServerService.resume(DeploymentServerService.java:207)
at weblogic.management.deploy.internal.DeploymentServerService.start(DeploymentServerService.java:129)
at weblogic.server.AbstractServerService.postConstruct(AbstractServerService.java:76)
at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.glassfish.hk2.utilities.reflection.ReflectionHelper.invoke(ReflectionHelper.java:1262)
at org.jvnet.hk2.internal.ClazzCreator.postConstructMe(ClazzCreator.java:332)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:374)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at org.glassfish.hk2.runlevel.internal.AsyncRunLevelContext.findOrCreate(AsyncRunLevelContext.java:232)
at org.glassfish.hk2.runlevel.RunLevelContext.findOrCreate(RunLevelContext.java:85)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2020)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:114)
at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:88)
at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.oneJob(CurrentTaskFuture.java:1213)
at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.run(CurrentTaskFuture.java:1144)
at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:666)
at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:348)
at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:333)
at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:54)
at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41)
at weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:640)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:406)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:346)
If you use web annotations in java code, you don't have to declare the servlet in the web.xml file any more.
You can try by removing the corresponding "servlet" and "servlet-mapping" tags in web.xml
It seems that WebLogic 12.1.3 can deal with double declaration (inline annotation & xml) but not anymore in WebLogic 12.2.
I had this error with #webservice annotation when I specified the "serviceName" parameter and when I declared the servlet in web.xml file with the same value.
The issue doesn't exist in version 12.1.3 (which happened to be the version we were meant to be upgrading to).
Weblogic as of version 12.2.1.3 automatically registers a JAX-RS servlet to the path /resources/* in certain scenarios (e.g. some dependency like jackson-jaxrs-json-provider "requests" it via annotation/spi/moduleinfo). But if this path is already registered by another service the mentioned error is thrown.
There are 3 possible solutions one can try:
In our case the issue was coming from classpath scanning for web services components, and finding annotated services in the webservices-rt jar. That scanning needed to be switched off.
Setting the metadata-complete attribute to true in the web.xml descriptor if your Web application does not have any annotations and if you have the version set to 2.5 or higher to avoid unnecessary scanning of the Web applications classes for annotations. E.g.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>sample</servlet-name>
<servlet-class>Sample</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>/sample</url-pattern>
</servlet-mapping>
</web-app>
Alternatively, you can turn off annotation processing and DI for all the Web applications by setting -Dweblogic.servlet.DIDisabled=true flag when starting WebLogic Server.
Registering another path for jersey in the web.xml to e.g. /jersey/*
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/jersey/*</url-pattern>
</servlet-mapping>
Try removing the FATP jars which were added after 12.2 upgrade. This worked for me.

getRequestDispatcher(.).forward(req,res) throws java.io.FileNotFoundException

I have upgraded my Servlet from 2.4 to 3.0 and deployed my application on Websphere 8.5.5.8. Application Server starts properly.
When I try to access my home.jsp page in browser it throws:
Controller Main Error OG1000SRVE0190E: File not found: /servlet/com.platform7.affina.operations.servlet.ValidateLoginUser
When I try to debug, code hits my Main Controller Servlet (which is in same package) but inside Controller servlet class I am calling:
this.getServletContext().getRequestDispatcher("Servlet/com.platform7.affina.operations.servlet.ValidateLoginUser").forward(request, response);
Which throws:
FileNotFoundException for Servlet/com.platform7.affina.operations.servlet.ValidateLoginUser.
But ValidateLoginUser is in the same package and classes folder location!
Folder structure:
\NEED4SPEEDCell02\operations_1.ear\OperationsWeb.war\WEB-INF\classes\com\platform7\affina\operations\servlet
ControllerMain.class and ValidateLoginUser.class are in same servlet package.
my Web.xml file:
<servlet>
<servlet-name>servletMain</servlet-name>
<servlet-class>com.platform7.affina.operations.servlet.ControllerMain</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>servletMain</servlet-name>
<url-pattern>/controllerMain</url-pattern>
</servlet-mapping>
So when I access my URL: it hits ControllerMain.class but inside this class I am calling another servlet which is not part of web.xml but is located in same package of ControllerMain.class.
When I print realpath: this.getServletContext().getRealPath("/"));
I get:
C:\WebSphere858\AppServer\profiles\AppSrv01\installedApps\NEED4SPEEDCell02\operations_1.ear\OperationsWeb.war
I tried using getNamedDispatcher(..) too but throws: null.
Same code works fine on Websphere 7 and even works on Websphere 8.5.5.5
Due to security reasons the default setting for com.ibm.ws.webcontainer.disallowServeServletsByClassname property has been changed.
Please Note:This APAR has changed the default value of the
WebContainer custom property
com.ibm.ws.webcontainer.disallowServeServletsByClassname from false to
true so that no security threat could occur. Prior to this change, it
was up to the developer to remember to change the custom property to
true before deploying into production.
Property Name:
com.ibm.ws.webcontainer.disallowServeServletsByClassname Description:
If set to true, disallows the use of serveServletsByClassnameEnabled
at the application server level, overriding any setting of
serveServletsByClassnameEnabled at the application level. This
property affects all applications. Values: true(default)/false
You will need to add that custom property to the Web Container and set it to false for serving servlets by class name.
But as BalusC suggested, you should add your servlet to web.xml in the form:
<servlet>
<servlet-name>servletMain</servlet-name>
<servlet-class>com.platform7.affina.operations.servlet.ValidateLoginUser</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>servletMain</servlet-name>
<url-pattern>/validateLoginUser</url-pattern>
</servlet-mapping>
and change that forward to:
this.getServletContext().getRequestDispatcher("/validateLoginUser").forward(request, response);
And do the same with your other class from the same package.
You seem to be relying on the legacy InvokerServlet which is known to have major security holes. This was deprecated in Tomcat 5 and clones (WebSphere 4) and removed in Tomcat 7 and clones (WebSphere 6).
You're not supposed to use it anymore. Just map the servlet on a normal URL pattern and invoke it. Assuming that the servlet is mapped on an URL pattern of /validateLoginUser via #WebServlet("/validateLoginUser") annotation on the servlet class, or via <url-pattern>/validateLoginUser</url-pattern> in web.xml mapping on the servlet, then you can get a request dispatcher on it as below:
request.getRequestDispatcher("/validateLoginUser");
Or, just refactor shared code to a plain Java class with a method and invoke it the usual Java way. It's these days kind of weird to have shared validation logic tight coupled in a servlet.
See also:
How to invoke a servlet without mapping in web.xml?
To make above upgrade working, I did few other changes as below for future references.
Mainly, I have to change binding files for websphere.
Previously, I had two bindings ibm-web-bnd.xmi and ibm-web-ext.xmi
ibm-web-bnd.xmi
<?xml version="1.0" encoding="UTF-8"?>
<com.ibm.ejs.models.base.bindings.webappbnd:WebAppBinding xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:com.ibm.ejs.models.base.bindings.webappbnd="webappbnd.xmi" xmi:id="WebAppBinding_1226331113121" virtualHostName="default_host">
<webapp href="WEB-INF/web.xml#WebApp"/>
<resRefBindings xmi:id="ResourceRefBinding_1226331113121" jndiName="AffinaDataSource_pma">
<bindingResourceRef href="WEB-INF/web.xml#ResourceRef_AffinaDataSource_pma"/>
</resRefBindings>
</com.ibm.ejs.models.base.bindings.webappbnd:WebAppBinding>
ibm-web-ext.xmi
<?xml version="1.0" encoding="UTF-8"?>
<com.ibm.ejs.models.base.extensions.webappext:WebAppExtension
xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:com.ibm.ejs.models.base.extensions.webappext="webappext.xmi"
xmi:id="WebAppExtension_1226331113121"
serveServletsByClassnameEnabled="true">
<webApp href="WEB-INF/web.xml#WebApp"/>
<jspAttributes xmi:id="JSPAttribute_1226331113121" name="reloadEnabled" value="true"/>
<jspAttributes xmi:id="JSPAttribute_1226331113122" name="reloadInterval" value="10"/>
</com.ibm.ejs.models.base.extensions.webappext:WebAppExtension>
So as per servlet3 and Websphere 8.5.5.8, I change to replace above two .xmi files with ibm-web-bnd.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd" version="1.0">
<virtual-host name="default_host"/>
<resource-ref name="AffinaDataSourceAlias_pma" binding-name="AffinaDataSource_pma"/>
</web-bnd>
and then while installing application on Websphere 8.5.5.8, it use to throw outofmemmory error, so to fix that I change below max memory parameter from 256m to 512m in wsadmin.bat
C:\WebSphere858\AppServer\bin\wsadmin.bat
set PERFJAVAOPTION=-Xms256m -Xmx512m -Xquickstart
Hope this helps.

Spring4 MVC not recognizing jsps

I am trying to make an MVC project using gradle and Spring4.
#Bean
public UrlBasedViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
...
#RequestMapping("/home")
public String welcome() {
return "index";
}
But when I run using gradle jettyRun I get...
http://localhost:8080/personal-war/home
HTTP ERROR 404
Problem accessing /personal-war/WEB-INF/jsp/index.jsp. Reason:
NOT_FOUND
Update Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Spring MVC Application</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.proj.spring.config</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I added this line
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
but then only html renders the server side stuff isn't working
First, you need to know that Servlet containers (I'll assume Jetty too) have a Servlet for rendering JSPs. This Servlet is typically extension mapped to *.jsp.
The Servlet Specification gives the order of url-pattern matching
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.
In your case, when you forward to
/WEB-INF/jsp/index.jsp
The Servlet container will match that path to your DispatcherServlet mapped to
/*
This happens before the container could match the JSP servlet mapped to *.jsp.
It therefore uses your DispatcherServlet to service(..) the request. But your DispatcherServlet does not have a handler for
/WEB-INF/jsp/index.jsp
The simple solution would be to map your DispatcherServlet to
/
and have it be the fallback Servlet if no match is found.

Catch-all (wildcard) servlet url-pattern overrides file extension patterns

I would like to achieve the following:
/webapp-context/Page-1 -> Handled by my custom "ContentServlet"
/webapp-context/Another-Page -> Handled by my custom "ContentServlet"
/webapp-context/Page-with-long-title -> Handled by my custom "ContentServlet"
/webapp-context/_cms/<something>.zul -> Handled by ZK framework
My latest attempt looks like this (web.xml extract):
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zul</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>myContentServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Unfortunately now my content servlet handles all requests (I thought the more specific pattern takes precedence?).
No conflict exists if i map my content servlet to the pattern "/webapp-context/content/*", but that's not what I want.
Thanks for your time.
I just found a solution through this question: Difference between / and /* in servlet mapping url pattern
Using '/' instead of '/*' did the trick for me.
<servlet-mapping>
<servlet-name>myContentServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Resources