Saturday 19 March 2011

Spring - Java MVC Framework





Spring IDE Basics




Spring IDE is an eclipse plug-in that helps in developing Spring Application. First we will see how to install the Spring IDE and later we will create our first Spring project using it. I am using Eclipse 3.4.1 version to demonstrate this.
To install Spring IDE, Go to Help -> Software Updates.
 Click the "Add Site" button and enter "http://springide.org/updatesite" in the Add Site popup.
 Select all the Spring IDE features and click Install.
 Once the installation is complete you are done. Now let's see how to create the hello world example using the Spring IDE.
First create a Spring project, go to File -> New -> Project.
 Select Spring Project and click Next.
 Enter the project name and click Finish.
 The "S" in the upper right corner indictes it is a Spring Project.
Right click the src package and create a new package "opensourzesupport". Create the following HelloWorld class
package com.opensourzesupport;

public class HelloWorld {

    private String message;
    
    public void setMessage(String message) {
        this.message = message;
    }
    
    public void display()
    {
        System.out.println(message);
    }
}
The HelloWorld class has a message property and its value is set using the setMessage() method. This is called setter injection. Instead of directly hard coding the message, we inject it through an external configuration file. The design pattern used here is called Dependency Injection design pattern and it is explained in detail in the next example. (Spring Dependency Injection)The HelloWorld class also has a display() method to display the message.
Now we have created the HelloWorld bean class, the next step is to add an entry for this in the bean configuration file. The bean configuration file is used to configure the beans in the Spring IoC container. To create a new bean configuration file right click the src folder and select New -> Spring Bean Configuration File.
 Enter the bean name and click Next.
 Select the beans option and click Finish.
 Now the Spring configuration file is created. Add the following code to created an entry for the HelloWorld bean class.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloWorld" class="com.opensourzesupport.HelloWorld">
        <property name="message" value="Hello World!"></property>
    </bean>

</beans>
The id attribute of the bean element is used to give a logical name to the bean and the class attribute specifies the fully qualified class name of the bean. The property element within the bean element is used to set the property value. Here we set the message property to "Hello World!".
If you want to display a differnt message, the only change you need to is to change the value of the message in the bean configuration file. This is one of the main benefits of using the Dependency Injection design pattern, this makes the code loosely coupled.
To dispaly the message, create the following HelloWorldApp class.

package com.opensourzesupport;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support. ClassPathXmlApplicationContext;

public class HelloWorldApp {
    
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorld");
        helloWorld.display();
    }

}
First we instantiate the Spring IoC container with the bean configuration file beans.xml. We use the getBean() method to retrive the helloWorld bean from the application context and call the display() method to display the message in the console.


Add the following jar files to the classpath.
antlr-runtime-3.0
commons-logging-1.0.4
org.springframework.asm-3.0.0.M3
org.springframework.beans-3.0.0.M3
org.springframework.context-3.0.0.M3
org.springframework.context.support-3.0.0.M3
org.springframework.core-3.0.0.M3
org.springframework.expression-3.0.0.M3
To execute the example run the HelloWorldApp file. The "Hello World!" message gets printed on the console.

Spring IoC

In Spring, the Inversion of Control (IoC) principle is implemented using the Dependency Injection (DI) design pattern. Let's understand dependency injection with the help of an example. First we will see a java version of the example and later we will add spring functionalities to it. As far as the example go, its pretty simple. The QuizMater interface exposes the popQuestion() method. To keep things simple, our QuizMaster will generate only one question.

 QuizMaster.java
----------------------
  package com.opensourzesupport;
  public interface QuizMaster { 
  public String popQuestion();
  }

The StrutsQuizMaster and the SpringQuizMaster class implements QuizMaster interface and they generate questions related to struts and spring respectively.

StrutsQuizMaster.java
----------------------
package com.opensourzesupport;

public class StrutsQuizMaster implements QuizMaster { 
   @Override
   public String popQuestion() {
        return "Are you new to Struts?";
   }
}
SpringQuizMaster.java
.----------------------
package com.opensourzesupport; 
public class SpringQuizMaster implements QuizMaster {
    @Override
    public String popQuestion() {
        return "Are you new to Spring?";
   }
}
We have a QuizMasterService class that displays the question to the user. The QuizMasterService class holds reference to the QuizMaster.
QuizMasterService.java
-----------------------
package com.opensourzesupport;
public class QuizMasterService { 
   private QuizMaster quizMaster = new SpringQuizMaster();    
   public void askQuestion()
    {
       System.out.println(quizMaster.popQuestion());
   }
}
Finally we create the QuizProgram class to conduct quiz.  

QuizProgram.java
----------------
package com.opensourzesupport;

 
public class QuizProgram {

    public static void main(String[] args) {
        QuizMasterService quizMasterService = new QuizMasterService();
      quizMasterService.askQuestion();
    }

}
As you can see it is pretty simple, here we create an instance of the QuizMasterService class and call the askQuestion() method. When you run the program as expected "Are you new to Spring?" gets printed in the console.
Let's have a look at the class diagram of this example. The green arrows indicate generalization and the blue arrows indicates association.
 As you can see this architecture is tightly coupled. We create an instance of the QuizMaster in the QuizMasterService class in the following way.
1.private QuizMaster quizMaster = new SpringQuizMaster();
To make our quiz master Struts genius we need to make modifications to the QuizMasterService class like this.
1.private QuizMaster quizMaster = new StrutsQuizMaster();
So it is tightly coupled. Now lets see how we can avoid this by using the Dependency Injection design pattern. The Spring framework provides prowerful container to manage the components. The container is based on the Inversion of Control (IoC) principle and can be implemented by using the Dependency Injection (DI) design pattern. Here the component only needs to choose a way to accept the resources and the container will deliver the resource to the components.
In this example instead of we, directly creating an object of the QuizMaster bean in the QuizMasterService class, we make use of the container to do this job for us. Instead of hard coding any values we will allow the container to inject the required dependancies.
We can inject the dependancies using the setter or constructor injection. Here we will see how we can do this using the setter injection.


QuizMasterService.java
.-----------------------
package com.opensourzesupport;

 
public class QuizMasterService {

    QuizMaster quizMaster;
   
   public void setQuizMaster(QuizMaster quizMaster) {
        this.quizMaster = quizMaster;
   }
    
    public void askQuestion()
    {
        System.out.println(quizMaster.popQuestion());
    }
}

The value for the QuizMaster will be set using the setQuizMaster() method. The QuizMaster object is never instantiated in the QuizMasterService class, but still we access it. Usually this will throw a NullPointerException, but here the container will instantiate the object for us, so it works fine.
After making all the changes, the class diagram of the example look like this.
 The container comes into picture and it helps in injecting the dependancies.
The bean configuration is done in the beans.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="springQuizMaster" class="com.opensourzesupport.SpringQuizMaster"></bean>
    <bean id="strutsQuizMaster" class="com.opensourzesupport.StrutsQuizMaster"></bean>
    <bean id="quizMasterService" class="com.opensourzesupport.QuizMasterService">
        <property name="quizMaster">
        <ref local="springQuizMaster"/>
       </property>
    </bean>
</beans>
We define each bean using the bean tag. The id attribute of the bean tag gives a logical name to the bean and the class attribute represents the actual bean class. The property tag is used to refer the property of the bean. To inject a bean using the setter injection you need to use the ref tag.
Here a reference of SpringQuizMaster is injected to the QuizMaster bean. When we execute this example, "Are you new to Spring?" gets printed in the console.
To make our QuizMaster ask questions related to Struts, the only change we need to do is, to change the bean reference in the ref tag.
<bean id="quizMasterService" class="com.opensourzesupport.QuizMasterService">
    <property name="quizMaster">
        <ref local="strutsQuizMaster"/>
    </property>
</bean>
In this way the Dependency Injection helps in reducing the coupling between the components.
To execute this example add the following jar files to the classpath.
1.antlr-runtime-3.0
2.commons-logging-1.0.4
3.org.springframework.asm-3.0.0.M3
4.org.springframework.beans-3.0.0.M3
5.org.springframework.context-3.0.0.M3
6.org.springframework.context.support-3.0.0.M3
7.org.springframework.core-3.0.0.M3
8.org.springframework.expression-3.0.0.M3



Spring Setter Injection

In this example you will learn how to set a bean property via setter injection. Consider the following User bean class.
package com.opensourzesupport;
public class User {
   private String name;
    private int age;
  private String country;
    
   public String getName() {
      return name;
   }
   
    public void setName(String name) {
       this.name = name;
   }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }

     
    public String getCountry() {
        return country;
    }
   
    public void setCountry(String country) {
        this.country = country;
    }
    
    public String toString() {
       return name + " is " + age + " years old, living in " + country;
    }
}
The User bean class has three attributes viz. name, age and country. All the three attributes are set using the setter injection. The toString() method of the User bean class is overridden to display the user object.
Here the beans.xml file is used to do spring bean configuration. The following code shows how to set a property value thru setter injection.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   <bean id="user" class="com.opensourzesupport.User" >
        <property name="name" value="Prasobh" />
        <property name="age" value="26"/>
        <property name="country" value="India"/>
    </bean>

 
</beans>
The id attribute of the bean element is used to specify the bean name and the class attribute is used to specify the fully qualified class name of the bean. The property element with in the bean element is used to inject property value via setter injection. The name attribute of the property element represents the bean attribute and the value attribute specifies the corresponding property value.
Here we set "Prasobh", "26" and "India" for the User bean properties name, age and country respectively. The following Main class is used to get the User bean from the Spring IoC container and dispaly its value it to the user.
package com.opensourzesupport;

 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support. ClassPathXmlApplicationContext;

 
public class Main {

     
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
       User user = (User)context.getBean("user");
        System.out.println(user);
    }

 
}
On executing the Main class the following message gets displayed on the console.
1.Prasobh is 26 years old, living in India

Spring Constructor Injection

In this example you will learn how to set a bean property via constructor injection. Consider the following User bean class.
package com.opensourzesupport;

    public class User {
    
    private String name;
    private int age;
    private String country;
    
    User(String name, int age, String country)
    {
        this.name=name;
        this.age=age;
        this.country=country;
    }

     
    public String toString() {
        return name + " is " + age + " years old, living in " + country;
    }
}
The User bean class has three attributes viz. name, age and country. All the three attributes are set thru constructor injection. The toString() method of the User bean class is overridden to display the user object.
Here the beans.xml file is used to do spring bean configuration. The following code shows how to set a property value thru constructor injection.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
mlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

 
    <bean id="user" class="com.vaanopensourzesupportnila.User" >
        <constructor-arg value="Prasobh" />
        <constructor-arg value="26"/>
        <constructor-arg value="India"/>
    </bean>

 
</beans>
The constructor-arg element within the bean element is used to set the property value thru constructor injection. Since there is only one constructor in the User bean class, this code will work fine. When there is more than one constructor with the same number of arguments, then the following ambiguities will occur. Conside the following code.
User( int age, String country)
{
    this.age=age;
   this.country=country;
}

 
User(String name, String country)
{
       this.name=name;
    this.country=country;
}
The bean configuration file.
<bean id="user" class="com.opensourzesupport.User" >
    <constructor-arg value="26"/>
   <constructor-arg value="India"/>
</bean>
Now which constructor do you think will be invoked? The first one with the int and the String argument, right? But for your surprise it will call the second constructor with both String arguments. Though we know the first argument is of type int and the second argument is of type String, spring interprets both as String arguments. To avoid this confusion you need to specify the type attribute of the constructor-arg element. Now with the following bean configuration, the first constructor will be invoked.
<bean id="user" class="com.opensourzesupport.User" >
    <constructor-arg type="int" value="26"/>
    <constructor-arg type="java.lang.String" value="India"/>
</bean>
Now consider this case. We have the following constructors in the User bean class.
User(String name, int age)
{
    this.name=name;
   this.age=age;
}

User( int age, String country)
{
    this.age=age;
    this.country=country;
}
The bean configuration file.
<bean id="user" class="com.opensourzesupport.User" >
    <constructor-arg type="int" value="26"/>
   <constructor-arg type="java.lang.String" value="India"/>
</bean>
Now which constructor do you think will be called? The second constructor, right? But again for your surprise the first constructor will be called, this is because the order in which the arguments appear in the bean configuration file will not be considered while invoking the constructor. To solve this problem you can use the index attribute to specify the constructor argument index.
Here is the bean configuration file after adding the index attribute.
<bean id="user" class="com.opensourzesupport.User" >
   <constructor-arg index="0" type="int" value="26"/>
   <constructor-arg index="1" type="java.lang.String" value="India"/>
</bean>
Now as expected, the second constructor will be invoked.


Spring MVC

Spring MVC helps in building flexible and loosely coupled web applications. The Model-view-controller design pattern helps in seperating the business logic, presentation logic and navigation logic. Models are responsible for encapsulating the application data. The Views render response to the user with the help of the model object . Controllers are responsible for receiving the request from the user and calling the back-end services.
The figure below shows the flow of request in the Spring MVC Framework.
 When a request is sent to the Spring MVC Framework the following sequence of events happen.
  • The DispatcherServlet first receives the request.
  • The DispatcherServlet consults the HandlerMapping and invokes the Controller associated with the request.
  • The Controller process the request by calling the appropriate service methods and returns a ModeAndView object to the DispatcherServlet. The ModeAndView object contains the model data and the view name.
  • The DispatcherServlet sends the view name to a ViewResolver to find the actual View to invoke.
  • Now the DispatcherServlet will pass the model object to the View to render the result.
  • The View with the help of the model data will render the result back to the user.
To understand the Spring MVC Framework we will now create a simple hello world example using the Eclipse IDE. I am using Exclipse IDE 3.4 , Spring IDE plugin, Tomcat 6.0 and Spring 3.0 to demonstrate this example.
Go to File -> New -> Dynamic Web Project, to create a web project.
 Enter the project name and click the Finish button.
 Right click the project folder, and select Spring Tools -> Add Spring Project Nature, to add Spring capabilities to the web project. This feature will be available once you install the Spring IDE.
 Create a new package com.opensourzesupport inside the src directory. The Spring controller class extends org.springframework.web.servlet.mvc.AbstractController class. To create a new controller class right click the src directory and create a new java class, enter the controller class name and super class name and the Finish button.
 Copy the following code inside the HelloWorldController class.
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class HelloWorldController extends AbstractController {

 
    private String message;
   
   @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
       return new ModelAndView("welcomePage","welcomeMessage", message);
    }
    
    public void setMessage(String message) {
       this.message = message;
    }
}
The HelloWorldController class has a message property that is set thru the setter injection. The HelloWorldController class should override the handleRequestInternal() method to process the request. After processing the request the handleRequestInternal() method returns a ModelAndView object back to the DispatcherServlet.
The DispatcherSevlet, as the name indicates, is a single servlet that manages the entire request-handling process. When a request is sent to the DispatcherServlet it delegates the job by invoking the appropriate controllers to process the request. Like any other servlet the DispatcherServlet need to be configured in the web deployment descriptor as shown.
<?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">
    <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 the servlet name is dispatcher. By default the DispatcherServlet will look for a file name dispatcher-servlet.xml to load the Spring MVC configuration. This file name is formed by concatenating the servlet name ("dispatcher") with "-servlet.xml". Here we user the the url-pattern as ".htm" inorder to hide the implementations technology to the users.
The redirect.jsp will be invoked first when we execute the Spring web application. This is the only jsp file outside the WEB-INF directory and it is here to provide a redirect to the DispatcherServlet. All the other views should be stored under the WEB-INF directory so that they can be invoked only through the controller process.
To create a bean configuration file right click the WebContent folder and select New -> Other. The following dialog box appears.
 Select the Spring Bean Configuration file and click Next.
 Enter the file name as "dispatcher-servlet.xml" and click the Finish button.
Now the Spring bean configuration file is created, we need to configure the Controller and the ViewResolver classes. The following code shows how to do this.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <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.htm" class="com.opensourzesupport.HelloWorldController" >
    </bean>
</beans>
First let's understand how to configure the controller.
1.<bean name="/welcome.htm" class="com.opensourzesupport.HelloWorldController" >
2.    <property name="message" value="Hello World!" />
3.</bean>
Here the name attribute of the bean element indicates the URL pattern to map the request. Since the id attribute can't contain special characters like "/" , we specify the URL pattern using the name attribute of the bean element. By default the DispatcherServlet uses the BeanNameUrlHandlerMapping to map the incoming request. The BeanNameUrlHandlerMapping uses the bean name as the URL pattern. Since BeanNameUrlHandlerMapping is used by default, you need not do any seperate configuration for this.
We set the message attribute of the HelloWorldController class thru setter injection. The HelloWorldController class is configured just like an another JavaBean class in the Spring application context, so like any other JavaBean we can set values to it through Dependency Injection(DI).
The redirect.jsp will redirect the request to the DispatcherServlet, which inturn consults with the BeanNameUrlHandlerMapping and invokes the HelloWorldController. The handleRequestInternal() method in the HelloWorldController class will be invoked. Here we return the message property under the name welcomeMessage and the view name welcomePage to the DispatcherServlet. As of now we only know the view name, and to find the actual view to invoke we need a ViewResolver.
The ViewResolver is configured using the following code.
<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>
Here the InternalResourceViewResolver is used to resolve the view name to the actual view. The prefix value + view name + suffix value will give the actual view location. Here the actual view location is /WEB-INF/jsp/welcomePage.jsp
The following library files are needed to run the example.
01.antlr-runtime-3.0
02.commons-logging-1.0.4
03.org.springframework.asm-3.0.0.M3
04.org.springframework.beans-3.0.0.M3
05.org.springframework.context-3.0.0.M3
06.org.springframework.context.support-3.0.0.M3
07.org.springframework.core-3.0.0.M3
08.org.springframework.expression-3.0.0.M3
09.org.springframework.web-3.0.0.M3
10.org.springframework.web.servlet-3.0.0.M3
To execute the example run the redirect.jsp file.




Spring SimpleFormController

To handle forms in Spring you need to extend your controller class from SimpleFormController class. Here we will create a user registration form to understand how this works. The SimpleFormController is deprecated as of Spring 3.0 so if you are using Spring 3.0 or above use the annotate controllers instead.
package com.opensourzesupport.web;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.SimpleFormController;
import com.opensourzesupport.domain.User;
import com.opensourzesupport.service.UserService;

 
@SuppressWarnings("deprecation")
public class UserController extends SimpleFormController {

 
    private UserService userService;

    public UserController() {
        setCommandClass(User.class);
        setCommandName("user");
    }

     
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

 
    @Override
   protected ModelAndView onSubmit(Object command) throws Exception {
        User user = (User) command;
        userService.add(user);
        return new ModelAndView("userSuccess","user",user);
    }
    
}
I am using Spring 3.0 so you see the SuppressWarnings annotation there. Here we extend the UserController from SimpleFormController, this makes the controller class capable of handling forms. Usually a form will be associated with a particular domain object, in our case it is the User class. In Spring this domain object is called command object by default. To refer the command object in the jsp page you need to set the command class using the setCommandClass() method in the constructor. Let say the User class has a name property, and to refer this in the jsp page you will use "command.name". You can also change this name by using the setCommandName() method. Here we set the name to user, so to access the user name in the jsp page we use "user.name".
You need to have a method to handle the form when the form is submitted, here the onSubmit() method is used for this purpose. The onSubmit() method has access to the command object, we first typecast the command object to User (our domain object) and then to register the user we call the add() method of the service class and finally return the ModelandView object.
All the forms field values will be submitted as Strings to the form controller. Spring has several pre registered property editors to convert the String values to common data types. Incase you have a custom data type you need to create custom property editors to handle them.
The User domain object has the following attributes.
package com.opensourzesupport.domain;

 
public class User {

 
    private String name;
    private String password;
    private String gender;
    private String country;
    private String aboutYou;
    private String[] community;
    private Boolean mailingList;

     
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String getCountry() {
        return country;
    }
    public void setCountry(String country) {
        this.country = country;
    }
    public String getAboutYou() {
        return aboutYou;
    }
    public void setAboutYou(String aboutYou) {
        this.aboutYou = aboutYou;
    }
    public String[] getCommunity() {
        return community;
    }
    public void setCommunity(String[] community) {
        this.community = community;
    }
    public Boolean getMailingList() {
        return mailingList;
    }
    public void setMailingList(Boolean mailingList) {
        this.mailingList = mailingList;
    }
    

     
}
Our User Service interface.
package com.opensourzesupport.service;
import com.opensourzesupport.domain.User;

public interface UserService {
    public void add(User user);
}
Our User Service Implementation class.
package com.opensourzesupport.service;

 
import com.opensourzesupport.domain.User;

public class UserServiceImpl implements UserService {

    @Override
    public void add(User user) {
        //Persist the user object here.
        System.out.println("User added successfully");

    }

 
}
Let's now create the user registration form using the Spring form tags. To use the form tags you need to first import the Spring's form tag library.
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Registration Page</title>
</head>
<body>

 
<form:form method="POST" commandName="user">
<table>
    <tr>
        <td>User Name :</td>
        <td><form:input path="name" /></td>
    </tr>
    <tr>
        <td>Password :</td>
        <td><form:password path="password" /></td>
    </tr>
    <tr>
        <td>Gender :</td>
        <td>
            <form:radiobutton path="gender" value="M" label="M" />
            <form:radiobutton path="gender" value="F" label="F" />
        </td>
    </tr>
    <tr>
       <td>Country :</td>
        <td>
       <form:select path="country">
            <form:option value="0" label="Select" />
            <form:option value="1" label="India" />
            <form:option value="2" label="USA" />
            <form:option value="3" label="UK" />
        </form:select></td>
    </tr>
    <tr>
        <td>About you :</td>
        <td><form:textarea path="aboutYou" /></td>
    </tr>
    <tr>
        <td>Community :</td>
        <td>
            <form:checkbox path="community" value="Spring" label="Spring" />
            <form:checkbox path="community" value="Hibernate" abel="Hibernate" />
            <form:checkbox path="community" value="Struts" label="Struts" />
       </td>
    </tr>
    <tr>
        <td></td>
        <td>
        <form:checkbox path="mailingList" label="Would you like to join our mailinglist?" /></td>
    </tr>
    <tr>
        <td colspan="2"><input type="submit"></td>
    </tr>
</table>
</form:form>

 
</body>
</html>
Here the path attribute is used to bind the form fields to the domain object. Here we use the HTTP POST method to submit the form. Inorder to bind the form fields to the domain object successfully the command object should be set to the same name in the jsp page and the controller class. To set the command object name in the jsp page, use the commandName attribute of the form tag.
The web.xml file.
<?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>SpringExample6</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>
Next create the Spring Bean Configuration file.
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="viewResolver"
    class="org.springframework.web.servlet.view. InternalResourceViewResolver"
    p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
    
    <bean id="userService" class="com.opensourzesupport.service.UserServiceImpl" />
    
    <bean name="/userRegistration.htm" class="com.opensourzesupport.web.UserController" p:userService-ref="userService" p:formView="userForm" p:successView="userSuccess" />  

     
</beans>
As you can see, we use "p" namespace here. The "p" namespace is simple and easy to use. Using "p" namespace the properties can be supplied using attributes, rather than elements.
For injecting the simple types we use property name in the "p" namespace and for injecting references we add "-ref" suffix to it. For example we use p:formView for injecting the form view property and p:userService-ref for injecting the user service.
During the HTTP GET request the formView will be rendered. When the form is submitted (during the HTTP POST request) the onSubmit() method of the UserController class will be called, on successful execution of the method the successView will be rendered. Incase of any type conversion errors or validation errors the formView will be automatically displayed the user.
Run the example by executing the redirect.jsp file. The redirect.jsp file, redirect the request to "userRegistration.htm".
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<% response.sendRedirect("userRegistration.htm"); %>
The following user registration page will be displayed.
 Fill the form and submit it.
 The onSubmit() method of the UserController class will be called and the control will be transfered to the view "userSuccess". We use InternalResourceViewResolver here, so the userSuccess.jsp page will be dispalyed. In the userSuccess.jsp page we dispaly all the user details using the jstl tags.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<html>
<head>
<title>Success Page</title>
</head>
<body>
User Details
<hr>
User Name   : ${user.name} <br/>
Gender      : ${user.gender} <br/>
Country     : ${user.country} <br/>
About You   : ${user.aboutYou} <br/>
Community   : ${user.community[0]}  ${user.community[1]} ${user.community[2]}<br/>
Mailing List: ${user.mailingList}
</body>
</html>
The userSuccess.jsp page.


The Spring Workflow

Before taking a look over the various Components that are involved in the Spring MVC Framework, let us have a look on the style of Spring Web Flow.
  1. The Client requests for a Resource in the Web Application.
  2. The Spring Front Controller, which is implemented as a Servlet, will intercept the Request and then will try to find out the appropriate Handler Mappings.
  3. The Handle Mappings is used to map a request from the Client to its Controller object by browsing over the various Controllers defined in the Configuration file.
  4. With the help of Handler Adapters, the Dispatcher Servlet will dispatch the Request to the Controller.
  5. The Controller processes the Client Request and returns the Model and the View in the form of ModelAndView object back to the Front Controller.
  6. The Front Controller then tries to resolve the actual View (which may be Jsp, Velocity or Free marker) by consulting the View Resolver object.
  7. Then the selected View is rendered back to the Client.
Let us look into the various Core Components that make up the Spring Web Tier. Following are the components covered in the next subsequent sections.

Dispatcher Servlet

The Dispatcher Servlet as represented by org.springframework.web.servlet.DispatcherServlet, follows the Front Controller Design Pattern for handling Client Requests. It means that whatever Url comes from the Client, this Servlet will intercept the Client Request before passing the Request Object to the Controller. The Web Configuration file should be given definition in such a way that this Dispatcher Servlet should be invoked for Client Requests.
Following is the definition given in the web.xml to invoke Spring's Dispatcher Servlet.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4">

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.*</url-pattern>
    </servlet-mapping>

</web-app>
    
Look into the definition of servlet-mapping tag. It tells that whatever be the Client Request (represented by *.* meaning any Url with any extension), invoke the Servlet by name 'dispatcher'. In our case, the 'dispatcher' servlet is nothing but an instance of type 'org.springframework.web.servlet.DispatcherServlet'.
Closing associated term with the Dispatcher Servlet is the Application Context. An Application Context usually represents a set of Configuration Files that are used to provide Configuration Information to the Application. The Application Context is a Xml file that contain various Bean Definitions. By default the Dispatcher Servlet will try to look for a file by name <servlet-name>-servlet.xml in the WEB-INF directory. So, in our case the Servlet will look for a file name called dispatcher-servlet.xml file in the WEB-INF directory.
It is wise sometimes to split all the Configuration information across multiple Configuration Files. In such a case we have to depend on a Listener Servlet called Context Loader represented by org.springframework.web.context.ContextLoaderListener.


<web-app>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

</web-app>
    
By default, this Context Listener will try to look for the Configuration File by name 'applicationContext.xml' in the '/WEB-INF' directory. But with the help of the parameter 'contextConfigLocation' the default location can be overridden. Even multiple Configuration Files each containing separate piece of Information is also possible.
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4">

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/contacts.xml, /WEB-INF/resources.xml</param-value>
    </context-param>

</web-app>
    
The above definition instructs the Framework to look and load for the Configuration Files by name 'contacts.xml' and 'resources.xml' in the WEB-INF directory.

No comments:

Post a Comment