Spring MVC Annotations Wierdness

I have been learning about Spring MVC for a past few days and have been trying to implement a "hello world" page using Spring’s annotation based controllers.  I have followed a step-by-step tutorial I found in the net. The funny thing is that the tutorial or any other tutorial that I could find, never works in my system, although I see screenshots of the same thing working at the tutorial author’s end. 
Spring is amazing, you just have to use the spring’s dispatcher servlet in your project and after configuring that, you basically end up creating beans namely – controllers, services, Dao. You just define all your beans in a context descriptor file which is an xml and the spring backend, takes care of the rest.
This is the story before Spring 2.5 came out. in 2.5, the designers thought that the idea of actually writing the descriptors as a seperate file is too much work. So, they ended up creating what is known as "annotation based controller support". Here, what they say is that you can keep most of your spring descriptor within your individual classes. For eg, if you want to specify that a class is a service level class, you put @Service at the top of the class. 
The most amazing annotation they came up with is the @Autowired. This facilitates the most prized feature of spring namely, the dependency injection. Earlier, for all beans, we would specify all dependency within the descriptor file. ie,, if your class A uses a property that belongs to class B, then we would specify which property of the class A needs class B while defining the bean for class A in the descriptor. With @Autowired annotation, spring would take care of the dependency automatically. All we have to do is to use it with the properties we would expect a dependency injection for. 

Now, coming back to my example, this is what my web.xml looks like. 

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Springtest1</display-name>

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>redirect.jsp</welcome-file>
</welcome-file-list>
</web-app>

Here, I have defined the dispatcher servlet and its mapped to all urls ending with ".htm".  Like I said before the descriptor cannot be entirely omitted. But heres what it looks like now :  

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<context:component-scan base-package="com.ak.hello" />

<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>

<bean name="/welcome" class="com.ak.hello.HelloWorldController"/>

</beans>
The default naming convention which spring expects for the context descriptor is <servletname>-context.xml. If we are using any other kind of names for that file, we would have to explicitely specify in the web.xml while defining the dispatcher servlet. I do have one concern here. You can see that I have defined the controller as a bean in the descriptor. I have seen that when I don’t give it, the web flow doesn’t happen at all and I keep getting 404 errors. None of the tutorials I have seen so far says that we need to define controller beans. When I specify only the controllers in the context file, the whole thing works. What bothers me even more is that when I tried this whole code in Netbeans IDE, I kept getting 404 errors irrespective of whether I have defined the controllers here or not. In eclipse however, this works fine now. 

Heres my controller class : 

/**
* @author Anoop.Kammaran
*
*/
@Controller
@RequestMapping("/welcome/*")
public class HelloWorldController{

/* (non-Javadoc)
* @see org.springframework.web.servlet.mvc.AbstractController#handleRequestInternal(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/

@RequestMapping("/welcome.htm")
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
return new ModelAndView("welcomePage","welcomeMessage", "Welcome: by Anoop");
}

@RequestMapping("/notwelcome.htm")
protected ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
return new ModelAndView("welcomePage","welcomeMessage", "Not Welcome: by Anoop");
}

}

The @RequestMapping annotation is used to specify the action mapping if you use the language of Struts users here. basically I am mapping URIs here. By specifying "/welcome/*" for this class, spring would send all requests containing URIs of the format "/welcome/*" to this controller. By specifying only the methods, spring would invoke that method when the URI matches. When you specify in both class level and method level, spring combines the two, like in this example, the first method, handleRequestInternal gets invoked if the URI contains "/welcome/welcome.htm". as for the second method, the URI should contain "/welcome/notwelcome.htm". 

In this project, I just use a redirect.jsp which will send request and the result is displayed in the welcomePage.jsp. You can see that in the ModelAndView object, I am not specifying the .jsp extention. The viewResolver that I have defined in the context descriptor file takes care of adding the prefix and posfix that I have specified there to get the full path of the jsp. 

Heres the welcomePage.jsp : 

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome Page</title>
</head>
<body>
${welcomeMessage}
</body>
</html>

I am yet to find an explanation to that wierd behaviour that I mentioned in the case of the context descriptor. 

More From Author

The closest thing to replace pen and paper for good :)

I have used two other styluses namely, the Bamboo Stylus and the Cregle iPen. By…

Apple Event October 2012

Been watching the live streaming of the Oct 23rd apple event. This is the event where…

Bootcamping Windows 8

Finally installed Windows 8 to Bootcamp(to non-mac users, this means that the windows now runs…

Leave a Reply

Your email address will not be published. Required fields are marked *