To learn any web framework starting with a HelloWorld application is a good idea. Once we get familiarity with the framework configuration it would be better to do a CRUD (Create,Read,Update,Delete) application which covers various aspects of a web framework like Validations, Request URL Mappings, Request Parameter Binding, Pre-populating forms etc.
Now I am going to explain how to write a Simple CRUD application using Spring MVC3, Hibernate and MySQL. Our Application is ContactsManagements where you can view or search contacts, create new contacts, edit or delete existing contacts.
Step#1: Create the CONTACTS Table
CREATE TABLE CONTACTS ( id int(10) unsigned NOT NULL AUTO_INCREMENT, name varchar(45) NOT NULL, address varchar(45) DEFAULT NULL, gender char(1) DEFAULT 'M', dob datetime DEFAULT NULL, email varchar(45) DEFAULT NULL, mobile varchar(15) DEFAULT NULL, phone varchar(15) DEFAULT NULL, PRIMARY KEY (id) );
<dependencies> <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>4.8.1</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-web</artifactid> <version>3.0.5.RELEASE</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-core</artifactid> <version>3.0.5.RELEASE</version> <type>jar</type> <scope>compile</scope> <exclusions> <exclusion> <artifactid>commons-logging</artifactid> <groupid>commons-logging</groupid> </exclusion> </exclusions> </dependency> <dependency> <groupid>log4j</groupid> <artifactid>log4j</artifactid> <version>1.2.14</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-tx</artifactid> <version>3.0.5.RELEASE</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>jstl</groupid> <artifactid>jstl</artifactid> <version>1.1.2</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>taglibs</groupid> <artifactid>standard</artifactid> <version>1.1.2</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-webmvc</artifactid> <version>3.0.5.RELEASE</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-aop</artifactid> <version>3.0.5.RELEASE</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>commons-digester</groupid> <artifactid>commons-digester</artifactid> <version>2.1</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>commons-collections</groupid> <artifactid>commons-collections</artifactid> <version>3.2.1</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.hibernate</groupid> <artifactid>hibernate-core</artifactid> <version>3.3.2.GA</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>javax.persistence</groupid> <artifactid>persistence-api</artifactid> <version>1.0</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>c3p0</groupid> <artifactid>c3p0</artifactid> <version>0.9.1.2</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.springframework</groupid> <artifactid>spring-orm</artifactid> <version>3.0.5.RELEASE</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-api</artifactid> <version>1.6.1</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.slf4j</groupid> <artifactid>slf4j-log4j12</artifactid> <version>1.6.1</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>cglib</groupid> <artifactid>cglib-nodep</artifactid> <version>2.2</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>org.hibernate</groupid> <artifactid>hibernate-annotations</artifactid> <version>3.4.0.GA</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>jboss</groupid> <artifactid>javassist</artifactid> <version>3.7.ga</version> <type>jar</type> <scope>compile</scope> </dependency> <dependency> <groupid>mysql</groupid> <artifactid>mysql-connector-java</artifactid> <version>5.1.14</version> <type>jar</type> <scope>compile</scope> </dependency> </dependencies>
<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>*.do</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value> </context-param>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/jsp/" p:suffix=".jsp"> </bean>
<context:annotation-config></context:annotation-config> <context:component-scan base-package="com.sivalabs"></context:component-scan> <mvc:annotation-driven> </mvc:annotation-driven> <context:property-placeholder location="classpath:config.properties"></context:property-placeholder> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource" p:basename="Messages"></bean>
################### JDBC Configuration ########################## jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/sivalabs jdbc.username=root jdbc.password=admin ################### Hibernate Configuration ########################## hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true #hibernate.hbm2ddl.auto=update hibernate.generate_statistics=true
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverclassname="${jdbc.driverClassName}" p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}"> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> </props> </property> <property name="packagesToScan" value="com.sivalabs"></property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionfactory-ref="sessionFactory"> </bean> <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
App.Title=SivaLabs typeMismatch.java.util.Date={0} is Invalid Date. dob=DOB
package com.sivalabs.contacts; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import org.apache.commons.lang.builder.ToStringBuilder; @Entity @Table(name="CONTACTS") public class Contact { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int id; @Column private String name; @Column private String address; @Column private String gender; @Column private Date dob; @Column private String email; @Column private String mobile; @Column private String phone; @Override public String toString() { return ToStringBuilder.reflectionToString(this); } //setters & getters }
package com.sivalabs.contacts; import java.util.List; import org.hibernate.Criteria; import org.hibernate.SessionFactory; import org.hibernate.criterion.Restrictions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; @Repository @Transactional public class ContactsDAO { @Autowired private SessionFactory sessionFactory; public Contact getById(int id) { return (Contact) sessionFactory.getCurrentSession().get(Contact.class, id); } @SuppressWarnings("unchecked") public List searchContacts(String name) { Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Contact.class); criteria.add(Restrictions.ilike("name", name+"%")); return criteria.list(); } @SuppressWarnings("unchecked") public List getAllContacts() { Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Contact.class); return criteria.list(); } public int save(Contact contact) { return (Integer) sessionFactory.getCurrentSession().save(contact); } public void update(Contact contact) { sessionFactory.getCurrentSession().merge(contact); } public void delete(int id) { Contact c = getById(id); sessionFactory.getCurrentSession().delete(c); } }
package com.sivalabs.contacts; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; @Component("contactFormValidator") public class ContactFormValidator implements Validator { @SuppressWarnings("unchecked") @Override public boolean supports(Class clazz) { return Contact.class.isAssignableFrom(clazz); } @Override public void validate(Object model, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name","required.name", "Name is required."); } }
package com.sivalabs.contacts; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.support.SessionStatus; import org.springframework.web.servlet.ModelAndView; @Controller public class ContactsControllers { @Autowired private ContactsDAO contactsDAO; @Autowired private ContactFormValidator validator; @InitBinder public void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MM-yyyy"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true)); } @RequestMapping("/searchContacts") public ModelAndView searchContacts(@RequestParam(required= false, defaultValue="") String name) { ModelAndView mav = new ModelAndView("showContacts"); List contacts = contactsDAO.searchContacts(name.trim()); mav.addObject("SEARCH_CONTACTS_RESULTS_KEY", contacts); return mav; } @RequestMapping("/viewAllContacts") public ModelAndView getAllContacts() { ModelAndView mav = new ModelAndView("showContacts"); List contacts = contactsDAO.getAllContacts(); mav.addObject("SEARCH_CONTACTS_RESULTS_KEY", contacts); return mav; } @RequestMapping(value="/saveContact", method=RequestMethod.GET) public ModelAndView newuserForm() { ModelAndView mav = new ModelAndView("newContact"); Contact contact = new Contact(); mav.getModelMap().put("newContact", contact); return mav; } @RequestMapping(value="/saveContact", method=RequestMethod.POST) public String create(@ModelAttribute("newContact")Contact contact, BindingResult result, SessionStatus status) { validator.validate(contact, result); if (result.hasErrors()) { return "newContact"; } contactsDAO.save(contact); status.setComplete(); return "redirect:viewAllContacts.do"; } @RequestMapping(value="/updateContact", method=RequestMethod.GET) public ModelAndView edit(@RequestParam("id")Integer id) { ModelAndView mav = new ModelAndView("editContact"); Contact contact = contactsDAO.getById(id); mav.addObject("editContact", contact); return mav; } @RequestMapping(value="/updateContact", method=RequestMethod.POST) public String update(@ModelAttribute("editContact") Contact contact, BindingResult result, SessionStatus status) { validator.validate(contact, result); if (result.hasErrors()) { return "editContact"; } contactsDAO.update(contact); status.setComplete(); return "redirect:viewAllContacts.do"; } @RequestMapping("deleteContact") public ModelAndView delete(@RequestParam("id")Integer id) { ModelAndView mav = new ModelAndView("redirect:viewAllContacts.do"); contactsDAO.delete(id); return mav; } }
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@include file="taglib_includes.jsp" %> <html> <head> <title><spring:message code="App.Title"></spring:message> </title> <script type="text/javascript" src="js/contacts.js"></script> </head> <body style="font-family: Arial; font-size:smaller;"> <center> <form action="searchContacts.do" method="post"><table style="border-collapse: collapse;" width="500" border="0" bordercolor="#006699"><tbody><tr> <td>Enter Contact Name</td> <td><input name="name" type="text"> <input value="Search" type="submit"> <input value="New Contact" onclick="javascript:go('saveContact.do');" type="button"> </td></tr> </tbody></table></form><c:if test="${empty SEARCH_CONTACTS_RESULTS_KEY}"> </c:if><c:if test="${! empty SEARCH_CONTACTS_RESULTS_KEY}"> <c:foreach var="contact" items="${SEARCH_CONTACTS_RESULTS_KEY}"> </c:foreach></c:if><table style="border-collapse: collapse;" width="500" border="1" bordercolor="#006699"><tbody><tr bgcolor="lightblue"> <th>Id</th> <th>Name</th> <th>Address</th> <th>Mobile</th> <th></th> </tr> <tr> <td colspan="4">No Results found</td> </tr> <tr> <td><c:out value="${contact.id}"></c:out></td> <td><c:out value="${contact.name}"></c:out></td> <td><c:out value="${contact.address}"></c:out> </td> <td><c:out value="${contact.mobile}"></c:out></td> <td> <a href="updateContact.do?id=$%7Bcontact.id%7D">Edit</a> <a href="javascript:deleteContact('deleteContact.do?id=${contact.id}');">Delete</a> </td> </tr> </tbody></table></center> </body> </html>
<%@include file="taglib_includes.jsp" %> <html> <head> <script type="text/javascript" src="js/contacts.js"></script> <title><spring:message code="App.Title"></spring:message> </title> </head> <body style="font-family: Arial; font-size:smaller;"> <table style="border-collapse: collapse;" width="750" align="center" bgcolor="lightblue" border="1" bordercolor="#006699" height="500"><tbody><tr> <td align="center"><h3>Edit Contact Form</h3></td> </tr> <tr valign="top" align="center"> <td align="center"> <form:form action="saveContact.do" method="post" commandname="newContact"><table style="border-collapse: collapse;" width="500" border="0" bordercolor="#006699" cellpadding="2" cellspacing="2"><tbody><tr> <td width="100" align="right">Name</td> <td width="150"> <form:input path="name"></form:input></td> <td align="left"> <form:errors path="name" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">DOB</td> <td><form:input path="dob"></form:input></td> <td align="left"><form:errors path="dob" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Gender</td> <td> <form:select path="gender"><form:option value="M" label="Male"><form:option value="F" label="Female"></form:option></form:option></form:select></td> <td> </td> </tr> <tr> <td width="100" align="right">Address</td> <td><form:input path="address"></form:input></td> <td align="left"> <form:errors path="address" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Email</td> <td><form:input path="email"></form:input></td> <td align="left"><form:errors path="email" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Mobile</td> <td><form:input path="mobile"></form:input></td> <td align="left"> <form:errors path="mobile" cssstyle="color:red"></form:errors></td> </tr> <tr> <td colspan="3" align="center"> <input name="" value="Save" type="submit"> <input name="" value="Reset" type="reset"> <input value="Back" onclick="javascript:go('viewAllContacts.do');" type="button"> </td> </tr> </tbody></table></form:form></td> </tr> </tbody></table></body> </html>
<%@include file="taglib_includes.jsp" %> <html> <head> <script type="text/javascript" src="js/contacts.js"></script> <title><spring:message code="App.Title"></spring:message> </title> </head> <body style="font-family: Arial; font-size:smaller;"> <table style="border-collapse: collapse;" width="750" align="center" bgcolor="lightblue" border="1" bordercolor="#006699" height="500"><tbody><tr> <td align="center"><h3>Edit Contact Form</h3></td> </tr> <tr valign="top" align="center"> <td align="center"> <form:form action="updateContact.do" method="post" commandname="editContact"><table style="border-collapse: collapse;" width="500" border="0" bordercolor="#006699" cellpadding="2" cellspacing="2"><tbody><tr> <td width="100" align="right">Id</td> <td width="150"> <form:input path="id" readonly="true"></form:input></td> <td align="left"> <form:errors path="id" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Name</td> <td> <form:input path="name"></form:input></td> <td align="left"> <form:errors path="name" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">DOB</td> <td><form:input path="dob"></form:input></td> <td align="left"><form:errors path="dob" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Gender</td> <td> <form:select path="gender"><form:option value="M" label="Male"><form:option value="F" label="Female"></form:option></form:option></form:select></td> <td> </td> </tr> <tr> <td width="100" align="right">Address</td> <td><form:input path="address"></form:input></td> <td align="left"> <form:errors path="address" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Email</td> <td><form:input path="email"></form:input></td> <td align="left"><form:errors path="email" cssstyle="color:red"></form:errors></td> </tr> <tr> <td width="100" align="right">Mobile</td> <td><form:input path="mobile"></form:input></td> <td align="left"> <form:errors path="mobile" cssstyle="color:red"></form:errors></td> </tr> <tr valign="bottom"> <td colspan="3" align="center"> <input value="Delete" onclick="javascript:deleteContact('deleteContact.do?id=${editContact.id}');" type="button"> <input name="" value="Save" type="submit"> <input value="Back" onclick="javascript:go('viewAllContacts.do');" type="button"> </td> </tr> </tbody></table></form:form></td> </tr> </tbody></table></body> </html>
function go(url) { window.location = url; } function deleteContact(url) { var isOK = confirm("Are you sure to delete?"); if(isOK) { go(url); } }
<% response.sendRedirect("viewAllContacts.do"); %>