JUG Sardegna supports Devoxx 2012
Vuoi ricevere uno zainetto? Clicca qui

Java User Groups
Java.net Partner
Get Firefox!

Spring Tutorial

Author:Fantayeneh Asres Giazaw ( http://my.opera.com/fantayeneh/blog )

In this tutotial I will show you how to build a simple web app
using the spring framework.

The app will consist in a simple implementation of a crud (create read update and delete) type app for simple person domain object.

1) What do you need ?

- Libs
1.1) The spring.jar from the springframework.org which contains almost all the jars neccessary
1.2) The mysql connector jar (from the mysql site)
1.3) commons-dbcp.jar and commons-pool.jar( if you download the spring framework) with all the dependencies you will find also these jars in the lib/jackarta-commons dir

- DB (I am using mysql, but I reccomend some lighter one for this app like Derby(which is included in the jsdk 6) Or HSQL)
- Your preferred IDE(I am using netbeans 5.5)

2)So, let start by defining the SQL Schema for the person table


// The Sql for the db is


  DROP TABLE IF EXISTS `springtutorial`.`person`;
  CREATE TABLE  `springtutorial`.`person` (
    `id` int(10unsigned NOT NULL auto_increment,
    `firstname` varchar(45NOT NULL,
    `lastname` varchar(45NOT NULL,
    PRIMARY KEY  (`id`)
  )




Then, we define the associated domain object

  package net.fantayeneh.springtutorial.domain
  
  public class Person {
     private Long id;
     private String firstName;
     private String lastName;
     
     /** Creates a new instance of Person */
     public Person()
     {
     }
    // define all the getters and setters
  }


Next, we define what service we want to expose for the end user
so, since it is a crud app, it will be:

  package net.fantayeneh.springtutorial.service
  
  public interface IPersonService
  {
     Person getPersonById(Long id);
     List<Person> getAllPerson();
     void savePerson(Person person);
     void updatePerson(Person person);
     void deletePerson(Long id);
  }


For the implementation we need some sort of dao object that will
incapsulate all the details regarding the interaction with the underlined db.
In our case we will use the spring jdbctemplate implementation.
So...

package net.fantayeneh.springtutorial.service
  
  public class PersonServiceImpl implements IPersonService
  {
     //we need the dao object
     private IPersonDAO personDAO;
     
     public void setPersonDAO(IPersonDAO personDAO)
     {
        this.personDAO = personDAO;
     }
     
     // now we only have to call the dao object for completing
     // our service
     public Person getPersonById(Long id)
     {
        return getPersonDAO().getPersonById(id);
     }
     
     public List<Person> getAllPerson()
     {
        return getPersonDAO().getAllPerson();
     }

    
     public void savePerson(Person person)
     {
        getPersonDAO().savePerson(person);
     }
    
    // conitnue delegating to the dao object
  }


Note: As you note I did not create explicitly any IPersonDAO object in the previous code.
Here is where the magic happens, the spring containter will inject at runtime
the object in the PersonServiceImpl space, using the dependency injection feature based on a configuration file. But for now don't bother, we will come back to it at the end when wiring all the modules together.

Now the DAO.
Firstly, we define the DAO interface (remember program against an interface)

  
  package net.fantayeneh.springtutorial.dao
  interface IPersonDAO {
    Person gerPersonById(Long id);
    List<Person> getAllPerson();
    void savePerson(Person person);
    void updatePerson(Perosn person);
    void deletePerson(Long id);
  }


an implementation will use, as I said, the jdbctemplate of the spring framework


package net.fantayeneh.springtutorial.dao
  public class PersonDAOJdbc extends JdbcDaoSupport implements IPersonDAO
  {
     private static final String GET_ALL_PERSON_SQL =
          "select * from person";
     
     public List getAllPerson()
     {
        return getJdbcTemplate().query(GET_ALL_PERSON_SQL, new PersonMapper());
     }

     
     private static final String GET_PERSON_SQL = "SELECT * FROM person WHERE id = ?";
     public Person getPersonById(Long id)
     {
        try
        {
          return (Person)getJdbcTemplate()
          .queryForObject(GET_PERSON_SQL,
                new Object[]{id},
                new PersonMapper());
        }
        catch (DataAccessException dae)
        {
          return null;
        }
     }
     
     private static final String UPDATE_PERSON_SQL = "" +
          "update person set firstname = ?, lastname = ? " +
          "where id = ?";
     public void updatePerson(Person person)
     {
        Object[] parameters = new Object[]{
          person.getFirstName(),
          person.getLastName(),
          person.getId()};
        
        getJdbcTemplate().update(UPDATE_PERSON_SQL, parameters);
     }
     
     
     private static final String INSERT_PERSON_SQL=
          "insert into person(firstname, lastname) values (?, ?)";
     
     public void savePerson(final Person person)
     {
        Object[] parameters = 
             new Object[]{person.getFirstName(), person.getLastName()};
        getJdbcTemplate().update(INSERT_PERSON_SQL, parameters);
        
     }

     
     public void deletePerson(Long id)
     {
     }
     
     
     // Here we implement the rowmapper callback
     // for mapping a single row to a domain object
     
     private class PersonMapper implements RowMapper
     {
        public Object mapRow(ResultSet resultSet, int ithrows SQLException
        {
          Person person = new Person();
          person.setId(resultSet.getLong("id"));
          person.setFirstName(resultSet.getString("firstname"));
          person.setLastName(resultSet.getString("lastname"));
          
          return person;
        }
        
     }
     
  }


Now that we are done with the backend stuff we move to the configuration.

- We have four conf files to deal with
- springtutorial-servlet.xml
- springtutorial-dao.xml
- springtutorial-service.xml
- web.xml

we can merge the first three files in one but it is a good style to keep the various conf stuff in a separate file, so, keep the configuration that interests the service layer in an apropriate file, and so on
First We start by wiring the dao layer and the service layer:

springtutorial-dao.xml


  <beans>
   
     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
         destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/springtutorial" />
        <property name="username" value="xxxx" />
        <property name="password" value="xxxx" />
     </bean>
     
     <bean id="personDAO" class="net.fantayeneh.springtutorial.dao.jdbc.PersonDAOJdbc">
        <property name="dataSource" ref="dataSource" />
     </bean>
     
     
     <!-- Transaction Manager For a Single JDBC DataSource-->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource"> <ref local="dataSource" /></property>
     </bean>
     
  </beans>


Note: Here we define the personDAO that we will be referring to in the springtutorial-service.xml
For the service layer we have only one bean to deal with, so :
springtutorial-service.xml


<beans>
     <bean id="personService" class="net.fantayeneh.springtutorial.service.PersonServiceImpl">
        <property name="personDAO" ref="personDAO"/>
     </bean>
  </beans>


Now the springtutorial-servlet.xml file a typical bean configuration is


<bean name="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
   </bean>
     
   <!--
      This bean will associate what method to associate to a given action
   -->
   <bean id="methodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
      <property name="mappings">
        <value>
           /view.html=view
           /viewAllPerson.html=viewAllPerson
        </value>
      </property>
   </bean>
   
   <bean name="/*.html" class="net.fantayeneh.springtutorial.web.PersonController" >
      <property name="personService" ref="personService" />
      <property name="methodNameResolver" ref="methodNameResolver"/>
   </bean>
    
   
   <bean id="personAddEdit" class="net.fantayeneh.springtutorial.web.AddEditPersonFormController">
      <property name="commandClass" value="net.fantayeneh.springtutorial.domain.Person"/>
      <property name="commandName" value="person"/>
      <property name="formView" value="addEditPerson"/>
      <property name="successView" value="redirect:/viewAllPerson.html"/>
      <property name="personService" ref="personService" />
   </bean>
   
   <bean name="/addPerson.html" parent="personAddEdit">
      <property name="action" value="add" />
   </bean>
   <bean name="/editPerson.html" parent="personAddEdit">
      <property name="action" value="edit" />
   </bean>
   
   <!-- View Resolution -->
   <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver">
      <property name="order" value="0"/>
   </bean>
   
   <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
      <property name="prefix" value="/WEB-INF/jsp/"/>
      <property name="suffix" value=".jsp"/>
   </bean>


Note: As you see I use the same class to make the add and edit stuff( I hate repeating codes)the two beans addPerson and editPerson have the attribute parent set to personAddEdit so they are extending the parent class and they have access to all the properties.
When we implement the controller class we have to figure out which operation
we are dealing with, here comes that innocent property "action",
the spring framework will inject the actual value, so we only need to make a simple test. great no????

Before implementing the controllers that handle the various
user request we configure the web.xml .

Every Spring MVC needs the DispatherServlet


 <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
        /WEB-INF/springtutorial-servlet.xml
        classpath:net/fantayeneh/springtutorial/dao/springtutorial-dao.xml
        classpath:net/fantayeneh/springtutorial/service/springtutorial-service.xml
      </param-value>
   </context-param>
   
   <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   
   
   <servlet>
      <servlet-name>springtutorial</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
   
   <servlet-mapping>
      <servlet-name>springtutorial</servlet-name>
      <url-pattern>*.html</url-pattern>
   </servlet-mapping>
  


The main things to note are:
1) there is a direct link between the dispatcher servlet name and the spring configuration file springtutorial-servlet.xml, so if you call your dispatcher servlet with foo, you have to name also the config file with foo-servlet.xml.
2) We also specify the place where the spring framework container has to look for the various xml conf files.
Now that all the wirings are set, let's complete the tutorial by implementig
the various controllers

We start with the PersonController which is a MultiActionContrller(handle the all the get stuff:(showing a single or the list of person).
For various other type of controllers please refer to the spring doc)


public class PersonController extends MultiActionController
    {
       private IPersonService personService;
       
       public ModelAndView view(HttpServletRequest request,
            HttpServletResponse responsethrows IOException,
            HttpRequestMethodNotSupportedException, ServletRequestBindingException
       {
          if (!request.getMethod().equals(METHOD_GET))
          {
            throw new HttpRequestMethodNotSupportedException("The requested method is not supported");
          }
          Long id = ServletRequestUtils.getLongParameter(request, "id");
          return new ModelAndView("view""person",
               personService.getPersonById(new Long(id)));
          
       }
       
       public ModelAndView viewAllPerson(HttpServletRequest request,
            HttpServletResponse responsethrows IOException,
            HttpRequestMethodNotSupportedException
       {
          List<Person> personList = personService.getAllPerson();
          
          return new ModelAndView("viewAllPerson""personList", personList);
       }

       
       public void setPersonService(IPersonService personService)
       {
          this.personService = personService;
       }
    }


The MultiActionController is useful because we can define multiple actions in the same controller class, so use this one for getting data.
The next thing to note is that in both cases we are sending a model object to the view(person, and personList):
The view resolver will be resposible for selecting the actual resolver based on the configuration(in this case jsp resolver).
This allow us to separate completley the view from the controller

The associated jsp files for this two actions are
1) view.jsp

      // include all the neccessary taglibs
      .....
      <h4>Person Detail</hr>
      <b>First Name: </b> <c:out value="{person.firstName}" />
      <b>LastName Name: </b> <c:out value="{person.lastName}" />


2) viewPerson.jsp

<table>
         <thead>
            <tr>
              <th>First Name</th>
              <th>Last Name</th>
              <th> </th>
              <th> </th>
            </tr>
            
         </thead>
         
         <tbody>
            <c:forEach items="${personList}" var="person">
              <tr>
                 <td><c:out value="${person.firstName}" /></td>
                 <td><c:out value="${person.lastName}" /></td>
                 <td colspan="2">
                    <a href="/springtutorial/editPerson.html?id=<c:out value="${person.id}" />">Edit</a> |
                    <a href="/springtutorial/delete.html?id=<c:out value="${person.id}" />">Delete</a>      
                 </td>
              </tr>
            </c:forEach>                          
         </tbody>
      </table>


Now the add and edit case:
We implement the AddEditPersonFormController which is a SimpleFormController


public class AddEditPersonFormController extends SimpleFormController
  {

      private IPersonService personService;
     private String action;
     
     /** Creates a new instance of AddChildFormController */
     public AddEditPersonFormController()
     {
     }
     
     protected Object formBackingObject(HttpServletRequest requestthrows Exception
     {
        Long id = ServletRequestUtils.getLongParameter(request, "id");
        if(id != null)
        {
          Person person = personService.getPersonById(id);
          if(person != null)
             return person;
          else
             throw new PersonNotFoundException();
        }
        return new Person();
     }
     
     
     protected ModelAndView onSubmit(
          final HttpServletRequest request,
          final HttpServletResponse response,
          final Object object,
          final BindException bindExceptionthrows Exception
     {
        
        Person person = (Person)object;
        if(action.equals("add"))
        {
          personService.savePerson(person);
        }
        else
        {
          personService.updatePerson(person);
        }
        
        return new ModelAndView(getSuccessView());
     }

     public void setPersonService(IPersonService personService)
     {
        this.personService = personService;
     }

    
     public void setAction(String action)
     {
        this.action = action;
     }
  }


There are two things to note:
1) the first one is the formBackingObject method which by default intiantiates a person object. By overriding it we can either create a new one or pull it from the db. This depends if we are dealing with an edit or add operation.
In the request we try to get on from the db.

2) The second observation is that in the onSubmit method the service method to call is choosen according to the configured action property(do you remember that???)

Now we set the jsp file for the insert and edit operation:(we are using the same for both) addEditPerson.jsp


<form:form commandName="person">
       <p>
          <label>First Name: </label><form:input path="firstName" /><br />
          <label>LastName: </label><form:input path="lastName" /><br />
       </p>
       <p class="botton">
          <input class="button" type="submit" value="Save" />
          <input class="button" type="reset" value="Reset" />
       </p>
    </form:form>


Here we are using the new spring 2.0 form tags for binding.

We have almost done...
I know, I know... I didn't forget about the delete method, I leave it to you:

Conclusion:
1)I did not implement any validation stuff, but in the next tutorial
I will do it in a detailed way.
2)I attach the project files.

for any question you can reach me at fantayeneh at netscape dot net

att:20070705210801189-0-springtutorial.rar



VeryQuickWiki Version 2.7.8 | Admin
Copyright © 2003-20011 Java User Group Sardegna Onlus. - Java, the Java Coffee Cup Logo and the Duke Logo are trademarks or registered trademarks of Oracle corporation in the U.S. and other countries.