MrBool
You must be logged in to give feedback. Click here to login
[Close]

You must be logged to download.

Click here to login

[Close]

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

[Close]

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Configuring servlets with annotations and Spring

This article will discuss about configuring servlets with annotations and Spring.

[close]

You didn't like the quality of this content?

Would you like to comment what you didn't like?

Introduction

This article picks up where the previous article, Servlet dependency injection with Spring, left off. It is highly recommended you read that article first as the technique described in this article is heavily based on the technique that article describes.

At the end of the last article, we had successfully found a way to configure Spring and a servlet container (supporting the Servlet 3.0 API) without duplicating effort by maintaining entries for each servlet in two different configuration files. But, as I hinted in that article, there is another way that involves even less configuration - it is possible to set up a Servlet 3.0 container and Spring with no XML configuration required at all.

To achieve this, we need to replace some of the code from the previous article. If we no longer have a web.xml file, we can no longer use it to load Spring’s ContextLoaderListener. We can present our own listener to the container, however, by annotating it with @WebListener, so we will just have to set up the Spring context ourselves. This works out OK, because it also turns out we need to adjust some of the servlet context’s init parameters before Spring initialises, and without a web.xml file there’d be no way of doing this other than having our own listener run first anyway. So let’s take a look at some code:

Listing 1: Initialising the Spring context

 
@WebListener
public class SpringAnnotationBasedServletRegistrationListener implements ServletContextListener
{
	ContextLoader contextLoader = new ContextLoader ();
	
	@Override
	public void contextInitialized (ServletContextEvent event)
	{
		
		ServletContext servletContext = event.getServletContext ();
		
		// configure the necessary parameters in the servlet context to get
		// Spring to configure the application without needing an XML file
		servletContext.setInitParameter (
			"contextClass", 
			"org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
		servletContext.setInitParameter (
			"contextConfigLocation", 
			"com.example.springnoconfig");
		
		WebApplicationContext context = contextLoader.initWebApplicationContext (servletContext);

We start by creating a ContextLoader which we will use to create the Spring application context. But before we do, we have to change the type of context it will create - the default type would try to load an XML configuration file, but we want to use annotations instead, so we specify a class that works purely on annotations. And then we tell that class where to find its configuration, which it will do by scanning all classes in the package com.example.springnoconfig for annotations. Finally, we create the context.

The next step is registering the servlets, and is quite similar to our previous version; the only noteworthy difference is that we use the getBeansOfType(Class) method rather than relying on a map being defined, as there is no easy way to define such a map with annotations:

Listing 2: Scanning the context for servlets

 
		for (Map.Entry<String, HttpServlet> servlet : 
context.getBeansOfType (HttpServlet.class).entrySet ())
		{
			ServletRegistration.Dynamic registration = 
				servletContext.addServlet (
servlet.getKey (), servlet.getValue ());

            	// add multipart config if present
            		if (servlet.getValue ().getClass ().isAnnotationPresent (MultipartConfig.class))
                			registration.setMultipartConfig (new MultipartConfigElement (
					servlet.getValue ().getClass ().getAnnotation (
MultipartConfig.class)));

Next, we must add the URL mapping for the servlet. Unfortunately this is not as simple as previously, as we no longer have a simple way of defining a key to be associated with the servlet. Two approaches seem sensible: either configuration via an annotation (which we’ll have to define ourselves) or convention based on the servlet’s class name. The use of a helpful convention can simplify the task of setting up an application in many cases, and the simple convention of taking the servlet class’s name (without the package name), dropping “Servlet” from the end if it’s present, and prepending “/” gives useful results in many cases, for example:

com.example.myapp.LoginServlet becomes /Login

This will work for many applications, but sometimes we will need more detailed configuration, so we’ll use an annotation if one is present, and fall back to the convention if not. The annotation interface looks like this:

Listing 3: An annotation interface for mapping servlets to URLs

 
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface URLMapping
{
	/** The URL pattern for which the servlet will be mapped */
	String value ();
}

With this in place, we can now finish our servlet context listener’s initialisation method:

Listing 4: Mapping the URL for the servlet

 
			URLMapping mapping = servlet.getValue ().getClass ().getAnnotation (URLMapping.class);
			if (mapping != null)
			{
				registration.addMapping (mapping.value());
			}
			else
			{
				// no annotation, so fall back to a hopefully-useful convention
				String servletClassName = servlet.getValue ().getClass ().getName ();
				int lastDot = servletClassName.lastIndexOf ('.');
				if (lastDot >= 0) servletClassName = servletClassName.substring (lastDot + 1);
				if (servletClassName.endsWith ("Servlet"))
					servletClassName = servletClassName.substring (
0, servletClassName.length () - 7);
				registration.addMapping ("/" + servletClassName);
			}
		}
	}

Our servlet context listener should also destroy the Spring context when the servlet context is destroyed:

Listing 5: Cleaning up

 
	@Override
	public void contextDestroyed (ServletContextEvent event)
	{
		contextLoader.closeWebApplicationContext (event.getServletContext ());
	}

Now we just need to create some servlets, and they should appear automatically. We’ll start with a simple “hello, world” servlet:

Listing 6: A “Hello, world” servlet

 
@Component
@URLMapping("/hello")
public class HelloWorldServlet extends HttpServlet
{
	@Override
	protected void doGet (HttpServletRequest req, HttpServletResponse resp) 
           throws ServletException, IOException
	{
		resp.getWriter ().println ("Hello, world");
	}
}

The “@Component” attribute instructs Spring to instantiate the object as a bean, causing it to appear in the collection of servlets we extracted from the Spring context above. We’ve specified an explicit URL mapping, so this servlet should appear at “/hello” (under whatever context root you specify when you publish the project).

Now that works, let’s try something a little more advanced - a servlet whose URL is determined by convention rather than configuration.

Listing 7: A servlet configured by convention

 
@Component
public class ConventionallyConfiguredServlet extends HttpServlet
{
	@Override
	protected void doGet (HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException
	{
		resp.getWriter().println("Hello again!");
	}
}

The only real difference is the lack of the “@URLMapping” attribute. This servlet appears at the address “/ConventionallyConfigured”.

And there’s one final example, which is a servlet that has a field automatically injected by Spring. First, we’ll need some kind of dependency. Here’s a simple example:

Listing 8: A dependency

 
@Component
public class MyDependency
{
	public String getMessage () { return "Hello, dependent"; }
}

And here’s a servlet that uses it:

Listing 9: A servlet with a dependency to be injected by Spring

 
@Component
public class DependentServlet extends HttpServlet
{
	@Autowired
	private MyDependency myDependency;
	
	public void setMyDependency (MyDependency myDependency)
{
	    this.myDependency = myDependency;
}
	
	@Override
	protected void doGet (HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException
	{
		resp.getWriter ().println (myDependency.getMessage ());
	}
}

We use an “@Autowired” attribute to tell Spring that we expect it to provide a value for the “myDependency” field. It obliges by passing the instance it created of MyDependency to the setMyDependency() method.

Head over to “/Dependent” and you’ll see the results: a message provided to the servlet by the dependency.

That is all for this article. Hope you liked it. See you next time.



My main area of specialization is Java and J2EE. I have worked on many international projects like Recorders,Websites,Crawlers etc.Also i am an Oracle Certified java professional as well as DB2 certified

What did you think of this post?
Services
Know how to keep MrBool Online
SUPPORT US
SUPPORT US
With your help, we can keep providing free content and helping you to be a better professional
support us
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually � in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits � in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login