Next up is the idea of programmatic definition of components. One might argue that this is not a real benefit, and I might even agree.

For a while now, it has been vogue to decry the explicit instantiation of components – and the new operator has been driven out of its usual home, and into factory methods and abstract factories. Then there was the XML movement which decreed that everything configurable should happen within configuration files – which gave rise to a slew of deployment descriptors. The idea was sound – why should a configuration change need a compile/build and deploy? Well it seems we’re back full circle. With programmatic definition, we can once again instantiate components programmatically and then configure them.

In this example, we’ll see how you might programmatically instantiate servlets, filters, and listeners.

First, let’s revisit our servlet context listener from the last post. For brevity, I’m only showing the parts that are new.

@WebListener
public class MyServletContextListener implements ServletContextListener {
		…
    public void contextInitialized(ServletContextEvent sce) {
        logger.info("Context Listener > Initialized");
        doProgrammaticRegistration(sce.getServletContext());
    }

    private void doProgrammaticRegistration(ServletContext sc) {
        ServletRegistration.Dynamic dynamic = sc.addServlet(
					"ProgrammaticServlet",
					"com.swengsol.servlets.MyProgrammaticServlet");
        dynamic.addMapping("/ProgrammaticServlet");
        FilterRegistration.Dynamic filter = sc.addFilter(
					"MyProgrammaticFilter",
					"com.swengsol.filters.MyProgrammaticFilter");
        EnumSet<DispatcherType> disps = EnumSet.of(
					DispatcherType.REQUEST, DispatcherType.FORWARD);
        filter.addMappingForServletNames(disps, true,
					"ProgrammaticServlet");
    }
}

As shown, during context initialization, we instantiate a new servlet, and use its returned ServletRegistration.Dynamic instance to configure the appropriate mapping. We take similar steps with a filter. These steps are similar to what would have happened when a servlet container encountered the <servlet>, <servlet-mapping>, <filter>, and <filter-mapping> elements in a web deployment descriptor.

As can be seen in the next listings, the servlet and filter are rather straightforward. Since the configuration occurs programmatically, they do not even need any annotations to be used.

package com.swengsol.filters;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.logging.Logger;

/**
 * User: Monsty
 * Date: Jul 24, 2010
 * Time: 8:45:10 AM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */

//1. Not even annotation is required
public class MyProgrammaticFilter implements Filter {
    private static final Logger logger = Logger.getLogger("com.swengsol");

    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp,
	FilterChain chain) throws ServletException, IOException {
        logger.info("> Filtering: " +
			((HttpServletRequest)req).getRequestURI());
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
        logger.info("> Filter: " + "Initializing ProgrammaticFilter");
	}
}

The servlet class is similarly simple. We will see the Squawker class in the next post. For now, all you need to know is that it is used to generate the HTML scaffolding around the text being displayed.

package com.swengsol.servlets;

import com.swengsol.Squawker;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.logging.Logger;

/**
 * User: Damodar Chetty
 * Date: Jul 24, 2010
 * Time: 8:46:17 AM
 * An introduction to Servlet 3.0 and Java 6 (TC JUG)
 * (c) Software Engineering Solutions, Inc.
 */

//1. Note not even an annotation is required.
public class MyProgrammaticServlet extends HttpServlet {
    private static final Logger logger =
		Logger.getLogger("com.swengsol");

    protected void doPost(HttpServletRequest request,
	HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request,
		HttpServletResponse response) throws ServletException, IOException {
        logger.info("Within request>>>" + getServletName());
        Squawker squawker = new Squawker("Added programmatically " +
				"(no annotation/web.xml entries): " + new Date());
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println(squawker.getHTML());
    }
}

Simple enough?