(I already know the answer, but because I often find myself re-looking for the answer, so I post it here as documentation for myself and others. This is encouraged on Stackoverflow.)
Background intro
Many Servlet developers have read the book "Head First Serlet & JSP" to get their "Certified Web Component Developer Exam" or just to learn Servlets. But the book hasn't been updated since 2009, and only covers Servlet 2.4. A lot has changed since then. The current latest version is 4.0.
One of the things that changed is the boot process of servlet web applications, which can make it unclear what happens during startup and how the web application is initialized.
Question
In Servlet version 2.4 and lower, web.xml is used to fully configure web applications. But higher version seem to have other ways to configure web applications, without touching web.xml and without annotations. For example, web frameworks provided as .jar files are somehow able to hook into the Servlet container and add url mappings.
How does this mechanism work?
Introduction
In Servlet 2.4 (November 2003) a servlet container (such as Tomcat and Jetty) simply booted the web application by looking for the file WEB-INF/web.xml (the deployment descriptor). The file web.xml contains references to servlets, filters and listeners, with their associated url patterns and parameters. Using web.xml the servlet container knows exactly where to find everything and how to configure them.
Since Servlet 3.0 (December 2009), web.xml is optional, you can also use annotations or a programmatic configuration instead.
Annotations are simpler in use. They are located in the javax.servlet.annotation package, and allow you to annotate a servlet with #WebServlet, a filter with #WebFilter, and a listener with #WebListener. The servler container will then automatically find and detect these classes. Annotations however do provide less configuration features than web.xml and a programmatic configuration.
This text further focuses at how programmatic configuration can be configured and how it starts Spring MVC. It's a bit more complex than annotations, but does give you and framework designers more control over the booting process.
If you wanted to use a web framework before Servlet version 3.0, you have to add a servlet or filter to your web.xml and configure the framework from there. After this initialization, you could start writing classes (usually non-Servlet classes) known by the web framework to create a web application.
Since Servlet 3.0, the system is modular. This allows framework and library designers to initialize the servlet container without you having to configure the framework via web.xml. You can immediately start writing the web framework specific classes to create a web application without touching Servlet classes.
(It's also possible in Servlet 3.0 to create your own web.xml and still let the framework do the initialization of the framework, without it being defined in web.xml.)
How can a framework or library hook into the Servlet container automatically?
When booting up, the Servlet container first looks for the deployment descriptor located at WEB-INF/web.xml. If this file has a metadata-complete attribute set to false, or if it isn't defined at all, the container will also search for annotated classes, such as #WebServlet.
Apart from looking for web.xml and annotated classes, since Servlet 3.0, the container will also look for META-INF/web-fragment.xml files within the .jar files located in the WEB-INF/lib directory.
The file web-fragment.xml is a web fragment, which is
(quote from Java Servlet Specification)
a logical partitioning of the web application in such a way that the
frameworks being used within the web application can define all the
artifacts without asking developers to edit or add information in the
web.xml. It can include almost all the same elements that the web.xml
descriptor uses. However the top level element for the descriptor MUST
be web-fragment and the corresponding descriptor file MUST be called
web-fragment.xml. The ordering related elements also differ between
the web-fragment.xml and web.xml
The content of web-fragment.xml is like web.xml, but with a web-fragment root element instead of web-app element:
<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
https://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
version="3.0">
<filter>
<filter-name>FrameworkFilter</filter-name>
<filter-class>framework.FrameworkFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FrameworkFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-fragment>
The exact ordering of loading of a single web.xml and multiple web-fragment.xml files, can be configured using the <absolute-ordering> and <ordering>.
Apart from web fragments, there is also a programmatic method to partition the web application: by writing an implementation of the interface javax.servlet.ServletContainerInitializer. ServletContainerInitializer gives access to the ServletContext, which contains methods to programmatically add servlets, filters and listeners.
To use ServletContainerInitializer, it has to be specified in a file located in META-INF/services/javax.servlet.ServletContainerInitializer. The content of this file has to be the fully qualified path to the implementation class.
How does this work for Spring MVC?
Although Spring MVC does contain a web-fragment.xml, it doesn't define any servlets, filters or listeners. Spring uses the META-INF/services/javax.servlet.ServletContainerInitializer file to refer to its own ServletContainerInitializer implementation class, which is the class SpringServletContainerInitializer.
SpringServletContainerInitializer is a ServletContainerInitializer, so it receives a ServletContext on startup. The goal of SpringServletContainerInitializer is to pass the servletContext to a more developer friendly WebApplicationInitializer, so that you can add servlets, such as Springs DispatcherServlet, which is a front-controller that directs incoming requests to other controllers. (See spring-framework-reference about how to configure a DispatcherServlet to Spring.)
Spring MVC doesn't provide a concrete implementation of WebApplicationInitializer, only a number of abstract classes, so that you have control over the booting process. In case of Spring Boot, a concrete implementation is provided: SpringApplicationWebApplicationInitializer to reduce the amount of boilerplate code.
Further info
A detailed description about how the Servlet container booting process exactly works, can be found in the official Java Servlet Specification. Further info about Spring MVC can be found in the Spring Framework reference.
I want to create a simple web application that runs on tomcat with pure java configuration.
I know how to do it with Spring frameworks WebApplicationInitializer. But i don't know without Spring.
I have heard about #WebServlet
Please guide me.
This is true that from Java EE 6, web.xml is no longer required for a Webapp to deploy. Instead of using web.xml, you can use annotations to replace the xml file (#WebServlet, etc.)
More information is given in this thread : How to use annotations instead of web.xml in the servlet to specify url
I am having a WAB application which is just having only one html file, and its working fine. the code is available on the below git link
https://github.com/vineethvnair0/Karaf/tree/master/first-wab
Now I want to define a rest service in the wab, with the same context root as my web app for example like below.
http://localhost:8181/first-wab/rest/hello
Please let me know how can i do it?
Simply add a CXF servlet to the web.xml. The exact solution depends on how you expose your Rest endpoints. Do you plan to use spring?
I have a class named AppService, annotated with JaxWS annotations: #WebService, #WebMethod.
It deploys correctly, and exposes an endpoint at the URL http://myhost/myapp/AppService.
I need to respond to a slightly different URL, at http://myhost/myapp/services/AppService (notice the 'services' segment).
How should I change the annotations or xml files in the application in order to expose the services under this new URL ?
This application is deployed on IBM WebSphere. Usage of standard JavaEE API would be preferred, but WebSphere specific instructions are fair game as well.
You need to add a servlet mapping in the web.xml: Change JAX-WS Service URL
I would like to set up a webservice endpoint using Spring's SimpleJaxWsServiceExporter for ease of use, but I also need to protect the webservice using a subclass of Jespa's HttpSecurityFilter
I suspect this does not work out of the box as SimpleJaxWsServiceExporter is using a separate HTTP server to the host webapp containing the filter - how should I accomplish this?
I have a class annotated with #WebService and in my applicationContext.xml
<bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"
p:baseAddress="http://localhost:9581/"/>
I found a couple of alternative ways to host the endpoint within the same HTTP server (behind the filter)
Either using JAX-WS WSSpringServlet and registering my #WebService beans via the wss:binding xml tag under the http://jax-ws.dev.java.net/spring/servlet namespace, or my preferred option, as JAX-WS Spring integration has Maven dependencies on Spring 2, using CXF.