[ACCEPTED]-How to initialize a Servlet during startup with parameters?-initialization

Accepted answer
Score: 31

Can we write an argument constructor in a Servlet?

Yes, you can but it is useless since the 5 servlet container won't invoke it.

The proper 4 way to do it is to use the init() method:

@Override
public void init() throws ServletException {
    String foo = getInitParameter("foo");
    String bar = getServletContext().getInitParameter("bar");
    // ...
}

In this 3 example, getInitParameter("foo") returns the value of the <init-param> of the 2 specific <servlet> entry in web.xml, and getServletContext().getInitParameter("bar") returns the value 1 of the independent <context-param> in web.xml.

Score: 24

The problem can be state more generically:

"According 42 to the servlets (2.3) specification, the 41 servlets are instantiated by the servlet 40 engine by invoking the no-arg constructor. How can 39 I initialize a servlet properly given 38 that correct initialization depends on 37 the central/global/unique/application configuration?"

Actually, you 36 can use serlvets with constructor and/or 35 initialize them as you like. However, it 34 requires a little bit of plumbing.

Assuming 33 you have a servlet with a constructor having 32 arguments:

package org.gawi.example.servlets;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class SampleServlet extends HttpServlet
{
    private final String mMessage;

    public SampleServlet(String message)
    {
        mMessage = message;
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        response.setContentType("text/plain");
        response.getWriter().write(mMessage);
    }
}

The first thing you need is a 31 unique servlet whithin your application, let's 30 call it InitializationServlet, to create 29 all the required instances. Those instances 28 must then be exported in the servlet context 27 to be retrieve by another servlet (explained 26 later). The InitializationServlet may look 25 like this:

package org.gawi.example.servlets;

import javax.servlet.*;
import javax.servlet.http.*;

public class InitializationServlet extends HttpServlet
{
    public void init() throws ServletException
    {
        SampleServlet servletA = new SampleServlet("this is servlet A");
        SampleServlet servletB = new SampleServlet("this is servlet B");
        SampleServlet servletC = new SampleServlet("this is servlet C");

        getServletContext().setAttribute("servletA", servletA);
        getServletContext().setAttribute("servletB", servletB);
        getServletContext().setAttribute("servletC", servletC);
    }
}

You see that only the init() method 24 has been provided. This servlet is not 23 servicing any HTTP request. Its only purpose 22 is to store the servlet in the ServletContext. Note 21 that you could have also use this servlet 20 to load your application configuration. So 19 this can act as the web-application entry 18 point, like the main(String[] args) method of a program. This 17 might remind you of the ContextLoaderServlet 16 of SpringSource.

The last piece is the DelegateServlet 15 that will effectively be instantiated by 14 the servlet container, only this servlet 13 will forward all the pertinent method calls 12 to the wrapped servlet instance:

package org.gawi.example.servlets;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class DelegateHttpServlet extends HttpServlet
{
    private static final String SERVLET_CONTEXT_KEY_INIT_PARAMETER = "servletContextKey";

    private HttpServlet mServlet;

    public void init(ServletConfig servletConfig) throws ServletException
    {
        super.init(servletConfig);
        locateServlet(servletConfig);
        mServlet.init(servletConfig);
    }

    private void locateServlet(ServletConfig servletConfig) throws ServletException
    {
        String servletContextAttributeName = servletConfig.getInitParameter(SERVLET_CONTEXT_KEY_INIT_PARAMETER);
        if (servletContextAttributeName == null)
        {
            throw new ServletException("Unable to find init parameter '" + SERVLET_CONTEXT_KEY_INIT_PARAMETER + "'");
        }

        Object object = servletConfig.getServletContext().getAttribute(servletContextAttributeName);

        if (object == null)
        {
            throw new ServletException("Unable to find " + servletContextAttributeName + " in servlet context.");
        }

        if (!(object instanceof HttpServlet))
        {
            throw new ServletException("Object is not an instance of"
                                       + HttpServlet.class.getName()
                                       + ".  Class is "
                                       + object.getClass().getName()
                                       + ".");
        }

        mServlet = (HttpServlet) object;
    }

    public void destroy()
    {
        mServlet.destroy();
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
    {
        mServlet.service(req, res);
    }

}

During its 11 initialization, the DelegateServlet will 10 look-up the target servlet in the servlet 9 context using the servletContextKey servlet initial argument.

The 8 web.xml for such an application might look 7 like that:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

  <display-name>Example</display-name>
  <description>Example web showing handling of servlets w/ constructors.</description>


  <servlet>
    <servlet-name>Initialization</servlet-name>
    <servlet-class>org.gawi.example.servlets.InitializationServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>A</servlet-name>
    <servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class>

    <init-param>
      <param-name>servletContextKey</param-name>
      <param-value>servletA</param-value>
    </init-param>

    <load-on-startup>2</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>B</servlet-name>
    <servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class>

    <init-param>
      <param-name>servletContextKey</param-name>
      <param-value>servletB</param-value>
    </init-param>

    <load-on-startup>3</load-on-startup>
  </servlet>

  <servlet>
    <servlet-name>C</servlet-name>
    <servlet-class>org.gawi.example.servlets.DelegateHttpServlet</servlet-class>

    <init-param>
      <param-name>servletContextKey</param-name>
      <param-value>servletC</param-value>
    </init-param>

    <load-on-startup>4</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>A</servlet-name>
    <url-pattern>/servlet/a</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>B</servlet-name>
    <url-pattern>/servlet/b</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>C</servlet-name>
    <url-pattern>/servlet/c</url-pattern>
  </servlet-mapping>

  <session-config>
    <session-timeout>5</session-timeout>
  </session-config>
</web-app>

Be sure to load the InitializationServlet 6 first, using a low <load-on-startup> value.

The benefit of 5 this approach is that HttpServlet objects can be handled 4 like any other regular Java object or bean. Hence, it 3 provides a better control over initialization: no 2 more tricky stuff to do in the init() method, nor 1 messy servlet init-arg handling.

Score: 6

You can't. Servlet is instantiated reflectively 4 by container. If servlet spec have allowed 3 arguments in constructor, you would have 2 to have some complicated deployment descriptor 1 like,

<servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>MyServlet</servlet-class>
    <servlet-argument id="1" type="string">Test<servlet-argument>
    <servlet-argument id="2" type="int">10</servlet-argument>
    <load-on-startup>1</load-on-startup>
</servlet>

I guess no one wants that.

Score: 5

Constructors are objects managed by the 10 application server.

For initialization, see 9 the init() method.

Update:

Can I use a constructor 8 in my servlet?

A: A servlet is a normal Java 7 class, so when there are no custom constructors, there 6 is an implicit default constructor with 5 no arguments. Servlet containers typically 4 use the Class.newInstance() method to 3 load servlets, so you must be careful 2 to add an explicit default constructor 1 if you add non-default constructors.

source: http://www.codestyle.org/java/servlets/FAQ.shtml

More Related questions