Introduction

The server hands requests to a Container in which the servlet is deployed. The Container gives the servlet the HTTP request and response, and calls the servlet's method, such as doPost() or doGet(). It creates the HttpServletResponse and HttpServletRequest objects.

Process:

  1. Container creates HttpServletRequest/HttpServletResponse objects
  2. Container determines servlet based on URL-pattern, creates thread and calls service()
  3. services calls doGet() or doPost()
  4. servlet writes to response
  5. service() completes, control returns to container
  6. thread dies or returns to pool

The container provides:

  • web app communications support
  • lifecycle management
  • multithreading support
  • declarative security
  • support for JSPs

Attributes vs Parameters

  • Attributes are used directly by programmers
  • Parameters are set as part of deployment, or through user interactions
Attributes Parameters
Types Application/context, Request, Session context init parameters, Request parameters, Servlet init parameters
Method to set setAttribute(String name, Object value) N/A
Return type Object String
Method to get getAttribute(String name) getInitParameter(String name)

Attribute Scope

Accessibility Scope What it’s good for
Context Any part, including servlets, JSPs, ServletContextListeners, ServletContextAttributeListeners Lifetime of the ServletContext, which means life of the deployed app. Resources you want the entire application to share, including database connections, JNDI lookup names, email addresses., etc. NOT thread safe, use synchronized(getServletContext())
HttpSession Any servlet or JSP with access to this particular session. The life of the session. A session can be destroyed programmatically or can simply time-out. Data and resources related to this client’s session, not just a single request. NOT thread safe, use synchronized(session)
Request Any part of the application that has direct access to the Request object. That mostly means only the Servlets and JSPs to which the request is forwarded using a RequestDispateher. Also Request-related listeners. The life of the Request, which means until the Servlet’s service() method completes. In other words, for the life of the thread (stack) handling this request Passing model info from the controller to the view… or any other data specific to a single client request. Thread-safe


5.1 Understand the purpose and structure of deployment descriptors

Servlets have 3 names:

  • client name: URL (url-pattern)
  • internal name: e.g. HelloServlet (servlet-name)
  • fully qualified name: mypackage.HelloServlet (servlet-class)
<web-app>
  <servlet>
    <servlet-name>Basic Servlet</servlet-name>
    <servlet-class>com.example.servlets.BasicServlet</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>Basic Servlet</servlet-name>
    <url-pattern>/BasicServlet</url-pattern>
  </servlet-mapping>
</web-app>

<url-pattern>

  • More specific URL patterns (paths) take precedence over less specific.
  • You cannot have any prepending path for an extension mapping (e.g. test/*.jsp)

<load-on-startup>

<servlet>
    <servlet-name>KathyOne</servlet-name>
    <servlet-class>com.example.servlets.BasicServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<error-page>

<!-- catch-all error page -->
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/errorPage.jsp</location>
</error-page>
 
<!-- override for more specific exception -->
<error-page>
    <exception-type>java.lang.ArithmeticException</exception-type>
    <location>/arithmeticError.jsp</location>
</error-page>
 
<!-- error page based on an HTTP status code -->
<error-page>
    <error-code>404</error-code>
    <location>/notFoundError.jsp</location>
</error-page>

You cannot throw non runtime business exceptions from the servlet code because the signatures of the doXXX and service method only permit IOException and ServletException.

Let's say your AccountServlet wants to throw NotEnoughFundsException. It should be handled as follows:

//in doPost() of AccountServlet try {
     ...lot of code
     if(funds<amt) throw new NotEnoughFundsException();
     ...lot of code
  } catch(NotEnoughFundsException nfe) {
     throw new ServletException(nfe) // wrap the exception inside ServletException
 }

The error mapping in DD should be:

  <exception-type>com.mycorp.NotEnoughFundsException</exception-type>
  <location>/errorPage.jsp</location>

welcome files

No preceeding slash is allowed

<web-app>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>default.jsp</welcome-file>
    </welcome-file-list>
</web-app>

ejb tags

For more on these tags, see 10.2 Understand the many elements that make up the model

Local bean:

<ejb-local-ref>
    <ejb-ref-name>ejb/Customer</ejb-ref-name>
    <ejb-ref-type>Entity</ejb-ref-type>
    <local-home>com.wickedlysmart.CustomerHome</local-home>
    <local>com.wickedlysmart.Customer</local>
</ejb-local-ref>

Remote bean:

<ejb-ref>
    <ejb-ref-name>ejb/LocalCustomer</ejb-ref-name>
    <ejb-ref-type>Entity</ejb-ref-type>
    <home>com.wickedlysmart.CustomerHome</home>
    <remote>com.wickedlysmart.Customer</remote>
</ejb-ref>

JNDI

<env-entry>
    <env-entry-name>rates/discountRate</env-entry-name>
    <env-entry-type>java.lang.Integer</env-entry-type>
    <env-entry-value>10</env-entry-value>
</env-entry>

<mime-mapping>

No dot before the extension name.

<mime-mapping>
    <extension>mpg</extension>
    <mime-type>video/mpeg</mime-type>
</mime-mapping>

Directory locations

Any requests to access the resources in WEB-INF or META-INF directories must be returned with a SC_NOT_FOUND(404) response.

- JSPs
- WEB-INF
 - classes
    - compiled java classes
 - tags folder
    - tag files (.tag .tagx)
 - any folder
    - TLD files
 - lib folder
    - jar files
      - META-INF
        - tags
          - TLD files
        - any folder
          - TLD files
        - resources
            - static resources available from /context/static_resource.ext
- META-INF (generated when application bundled into war)



5.2 Control context root and servlet mapping

Context root mapping

In full stack Java EE containers, the context root can be set in application.xml. e.g.

<module>
        <web>
            <web-uri>web-client.war</web-uri>
            <context-root>myContextRoot</context-root>
        </web>
</module>

Servlet mapping

Can use wildcard (*).

<servlet>
    <servlet-name>Beer</servlet-name>
    <servlet-class>com.example.BeerSelect</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Beer</servlet-name>
    <url-pattern>/Beer/SelectBeer.do</url-pattern>
</servlet-mapping>

The <enabled>element (subelement of <servlet>) set to "false" forces the container to make the request for the servlet respond with HTTP Code 503 (Service unavailable)

Servlet unavailability

It is appropriate for a servlet to throw a ServletException or UnavailableException (remember, UnavailableException extends ServletException) if it is not able to initialize. In this case, the container will not send any request to this servlet. Other servlets will remain unaffected.

UnavailableException has two different constructors that are used to specify whether the resource is permanently or temporarily unavailable:

  • UnavailableException(java.lang.String msg): Constructs a new exception with a descriptive message indicating that the servlet is permanently unavailable.
  • UnavailableException(java.lang.String msg, int seconds): Constructs a new exception with a descriptive message indicating that the servlet is temporarily unavailable and giving an estimate of how long it will be unavailable.


5.3 Create and use context and init parameters

ServletConfig

  • Read only once when the Container initalizes the servlet
  • One ServletConfig object per servlet.
  • Use it to pass deploy-time information to the servlet that you don’t want to hard-code into the servlet.
  • Use it to access the ServletContext.
  • Parameters are configured in the Deployment Descriptor. Servlet cannot change values.
  • Cannot use getServletConfig() until init() called
  • Note that it's init(), not init(ServletConfig servletConfig) that is used in the superclass
<servlet>
    <servlet-name>BeerParamTests</servlet-name>
    <servlet-class>TestInitParams</servlet-class>
 
    <init-param>
         <param-name>adminEmail</param-name>
        <param-value>likewecare@wickedlysmart.com</param-value>
    </init-param>
</servlet>
out.println(getServletConfg().getInitParameter("adminEmail"));

ServletContext

  • One ServletContext per web app.
  • Use it to access web app parameters (also configured in the Deployment Descriptor).
  • Use it as a kind of application bulletin-board, where you can put up messages (called attributes) that other parts of the application can access
  • Use it to get server info, including the name and version of the Container, and the version of the API that’s supported.

Place context-param outside of servlet tags:

<context-param>
    <param-name>adminEmail</param-name>
    <param-value>clientheaderror@wickedlysmart.com</param-value>
</context-param>
out.println(getServletContext().getInitParameter("adminEmail"));

Note that the following are equivalent:

getServletConfig().getServletContext().getInitParameter()
this.getServletContext().getInitParameter()

ServletContext interface

addListener(String classname)
getInitParameter(String)
getInitParameterNames()
getAttribute(String)
getAttributeNames()
setAttribute(String, Object)
removeAttribute(String)
getMajorVersion()
getServerInfo()
getRealPath(String)
getResource(String) : URL
getResourceAsStream(String) : InputStream // path must begin with a "/" and is interpreted as relative to the context root
getRequestDispatcher(String)
log(String)
setInitParameter() // can set initParams before container initialised

ServletContextListener

The interface has two methods which can be used to setup and tear down resources for the container.

contextInitialized(ServletContextEvent)
contextDestroyed(ServletContextEvent)

web.xml requires:

<listener>
    <listener-class>
        com.example.MyServletContextListener
    </listener-class>
</listener>



5.4 Use annotations to configure servlets

  • @WebServlet(/path) - the path is relative to the context root
  • web.xml configuration overrides annotation configuration
  • web.xml and WEB-INF no longer required
  • The following annotations were added in 3.0:
@HandlesTypes
@HttpConstraint
@HttpMethodConstraint
@MultipartConfig
@ServletSecurity
@WebFilter
@WebInitParam
@WebListener
@WebServlet

Section 15.5 of Servlet 3.0 specification specifies all the annotations that must be supported by the servlet container for Servlet, Filter, or various Listener classes. The following is the list for your convenience:

15.5.1 @DeclareRoles 
15.5.2 @EJB Annotation
15.5.3 @EJBs Annotation
15.5.4 @Resource Annotation
15.5.5 @PersistenceContext Annotation
15.5.6 @PersistenceContexts Annotation
15.5.7 @PersistenceUnit Annotation
15.5.8 @PersistenceUnits Annotation
15.5.9 @PostConstruct Annotation
15.5.10 @PreDestroy Annotation
15.5.11 @Resources Annotation
15.5.12 @RunAs Annotation
15.5.13 @WebServiceRef Annotation
15.5.14 @WebServiceRefs Annotation

Precedence rules

  1. Web.xml always takes precedence over annotations.
  2. Web.xml always takes precedence over web-fragment.xml.
  3. Before processing annotations, all web-fragments are merged into web.xml.
  4. If web.xml specifies metadata-complete=true, then no class is parsed for annotations.
  5. If any web-fragment.xml specifies metadata-complete=true, only annotations specified in classes contained in that web fragment are ignored.
  6. Merge is always additive as long as the result does not violate any multiplicity constraint. For example, if you have an two different init-parameters defined in two places, both will be added because one can have any number of init-parameters.
  7. Information in Web.xml always supersedes anything else. For example, if you have the same init-parameters defined with different values in web.xml as well as a web-fragment.xml, the value specified in web.xml will be used.
  8. Contradictory information in two web-fragments, produces an error and application fails to deploy. For example, if you have an same init-parameters defined with different values in two different web-fragment.xml but no value in web.xml, it will cause an error.
  9. Differently named servlets with same url-pattern: two instances of the servlet should be created, but which instance should be used to service the url pattern is not clear. Since web.xml takes precedence, the instance created as per information in web.xml should be used
  10. If the url-pattern is defined in the DD it replaces the urlPatterns annotation for the particular servlet.

Basic configuration

@WebServlet("/a")
public class ServletAnnotatedA extends HttpServlet {

value

It is recommended to use value when the only attribute on the annotation is the url pattern and to use the urlPatterns attribute when the other attributes are also used. It is illegal to have both value and urlPatterns attribute used together on the same annotation.

@WebServlet(value="/b")
public class ServletAnnotatedB extends HttpServlet {

urlPatterns

  • can take a single String or array of Strings
  • cannot be used with value
  • either value or urlPatterns is required with @WebServlet
@WebServlet(urlPatterns = {"/c","/c2"})
public class ServletAnnotatedC extends HttpServlet {

name

The default name of the Servlet if not specified is the fully qualified class name.

@WebServlet(name="MyServlet")
public class ServletAnnotatedX extends HttpServlet {

initParams and @WebInitParam

@WebServlet(value = "/d",initParams = {@WebInitParam(name = "name", value = "Bob"),
                       @WebInitParam(name = "age", value = "12")})
public class ServletAnnotatedInitParams extends HttpServlet {

aSync (asynchronous)

@WebServlet(urlPatterns={"/asyncservlet"}, asyncSupported=true)
public class ServletAnnotatedAsync extends HttpServlet {

All options

boolean    asyncSupported 
          Declares whether the servlet supports asynchronous operation mode.
 java.lang.String    description 
          The description of the servlet
 java.lang.String    displayName 
          The display name of the servlet
 WebInitParam[]    initParams 
          The init parameters of the servlet
 java.lang.String    largeIcon 
          The large-icon of the servlet
 int    loadOnStartup 
          The load-on-startup order of the servlet
 java.lang.String    name 
          The name of the servlet
 java.lang.String    smallIcon 
          The small-icon of the servlet
 java.lang.String[]    urlPatterns 
          The URL patterns of the servlet
 java.lang.String[]    value 
          The URL patterns of the servlet



Web fragments

New in Java EE 6. Web fragments allow you to split up web.xml in a modular fashion. See these links:

The fragment should be stored in a file called web-fragment.xml inside the META-INF directory of a jar file in WEB-INF/lib. Here is an example of a web fragment that registers a servlet and a listener:

<web-fragment>
    <name>MyFragment1</name>
        <servlet>
            <servlet-name>myFrameworkServlet</servlet-name>
            <servlet-class>myFramework.myFrameworkServlet</servlet-class>
        </servlet>
 
        <listener>
            <listener-class>myFramework.myFrameworkListener</listener-class>
        </listener>
</web-fragment>

In web.xml, or a web-fragment.xml, you can specify metadata-complete="true" to halt processing of web fragments and annotations:

<web-app metadata-complete="true" ...
 
<web-fragment metadata-complete="true" ...

When used on a web-fragment.xml, it is only applied to a particular jar, if inside a jar file.

Ordering can be imposed on web fragments inside the web.xml using <absolute-ordering>.

Rules:

  • If <others/> is absent, no other web fragments then those specified will be added to the deployment descriptor
  • <absolute-ordering> overrides any web-fragment.xml ordering.
  • If <web-app metadata-complete="true">, ordering is disregarded
  • The situation in which two different web fragments defines the same name of a <init-param> but with different values is as a configuration conflict. It will result in an application deploy failure.
<absolute-ordering>
          <name>MyFragment2</name>
          <name>MyFragment1</name>
         <others/>
</absolute-ordering>
 
<!-- another example (in a separate file, as only one of these can exist) -->
 
<absolute-ordering>
    <name>WF1</name>
    <others/>
    <name>WF3</name>
 </absolute-ordering>

Or in the web-fragments themselves. using before, after and others. e.g. WF1, WF3, WF2

<web-fragment>
    <name>WF1</name>
    <ordering>
       <before><name>WF2</name></before>
    </ordering>
</web-fragment>
 
<web-fragment>
    <name>WF2</name>
    <ordering>
        <after><others/></after>
    </ordering>  
</web-fragment>
 
<web-fragment>
    <name>WF3</name>
    <ordering>
       <after><name>WF1</name></after>
    </ordering>
</web-fragment>



Programmatic registration of servlets

You can add a servlet or a filter dynamically only before the initialization of the servlet context is complete. Here, "initialization of a servlet context" means initialization of the web application. Initialization is not considered complete until contextInitialized() of all ServletContextListeners is complete. So you can register a servlet in contextInitialized() of a ServletContextListener.

Within the ServletContextListener or the ServletContainerInitializer you can:

  • add servlets
  • add filters
  • add listeners (all but HttpSessionActivationListener, HttpSessionBindingListener)
  • instantiate servlets class
  • instantiate filters class
  • access already registered servlets and filters (programmatically, annotations, web.xml)
  • modify url patterns the servlets / filters maps to

Rules:

  • When the servlet is programmatically created using the same name as previously defined (using annotations or DD), the behaviour is not specified.

The following are the methods available in ServletContext that allow you to register a servlet dynamically:

ServletRegistration.Dynamic addServlet(java.lang.String servletName, java.lang.Class<? extends Servlet> servletClass)           
// Adds the servlet with the given name and class type to this servlet context. 
 
ServletRegistration.Dynamic addServlet(java.lang.String servletName, Servlet servlet)           
// Registers the given servlet instance with this ServletContext under the given servletName. 
 
ServletRegistration.Dynamic addServlet(java.lang.String servletName, java.lang.String className)            
// Adds the servlet with the given name and class name to this servlet context.

And for adding a filter:

FilterRegistration.Dynamic addFilter(java.lang.String filterName, java.lang.Class<? extends Filter> filterClass)           
// Adds the filter with the given name and class type to this servlet context. 
 
FilterRegistration.Dynamic addFilter(java.lang.String filterName, Filter filter)            
// Registers the given filter instance with this ServletContext under the given filterName. 
 
FilterRegistration.Dynamic addFilter(java.lang.String filterName, java.lang.String className)            
// Adds the filter with the given name and class name to this servlet context.

It is good to know about the hierarchy of Registration Interfaces and the features they support.

javax.servlet.Registration :  
/* Allows adding init parameters using setInitParameter and setInitParameters. All Known Subinterfaces:
 FilterRegistration, FilterRegistration.Dynamic, Registration.Dynamic, ServletRegistration, ServletRegistration.Dynamic  */
 
javax.servlet.ServletRegistration extends javax.servlet.Registration: 
// Provides addMapping and addMappings All Known Subinterfaces: ServletRegistration.Dynamic   
 
javax.servlet.Registration.Dynamic extends javax.servlet.Registration:  
// Provides setAsyncSupported All Known Subinterfaces: FilterRegistration.Dynamic, ServletRegistration.Dynamic    
 
javax.servlet.ServletRegistration.Dynamic extends ServletRegistration :  setLoadOnStartup, setMultipartConfig,  setRunAsRole(java.lang.String roleName), setServletSecurity(ServletSecurityElement constraint)
class extends description
Registration n/a Allows adding init parameters using setInitParameter and setInitParameters.
ServletRegistration Registration Provides addMapping and addMappings
Registration.Dynamic Registration Provides setAsyncSupported
ServletRegistration.Dynamic ServletRegistration setLoadOnStartup, setMultipartConfig,  setRunAsRole(java.lang.String roleName), setServletSecurity(ServletSecurityElement constraint)






Comments

If you have questions, corrections, information or examples to add, please comment below.

Add a New Comment