Jim Majure's Blog
CRUD Applications in Spring MVC
This blog describes the approach that I took in a recent project to implement simple CRUD functionality using Spring MVC. I had the following goals for this project:
- Allow basic CRUD functionality for a set of Hibernate-persisted objects.
- Maintain a clear separation between the Spring MVC-dependent code and the application code, and produce as little Spring MVC-dependent code as possible.
- Allow additional objects to be added with as little work as possible.
Basic Functionality
The basic functionality required is simple:
- Present a list of existing domain objects
- Allow a single instance in the list to be selected and edited
- Allow a new domain object instance to be created and populated
- Allow one or more domain object instances to be selected and deleted
Sample Domain Objects
To motivate the discussion, consider the following diagram showing the domain objects being managed. The domain objects include: Application, Company, and PropertySet.
Things to note in the diagram include:
- The
Applicationclass contains aPropertySetclass, which implies that saves and deletes are cascaded from anApplicationobject to its containedPropertySetobject. This is implemented with the Hibernate cascade capabilities. - The
Applicationclass refers to aCompanyclass, which implies that saves and deletes are not cascaded from anApplicationobject to its referencedCompanyobject.Companyobjects are maintained separately fromApplicationobjects.
Basic Object Structure
To support the functionality, I used the following basic object structure:
Things to note in the diagram include:
- There are 2 MVC controller classes:
ManageDomainObjectControllerandEditDomainObjectController - The
ManageDomainObjectControllerextendsMultiActionControllerand is used to manage the list view of the domain object - The
EditDomainObjectControllerextendsSimpleFormControllerand is used to edit a single instance of the domain object - Both controller classes hold an instance of the
AbstractManageDomainObjectsFormclass. This class is a POJO that maintains a user's state for a particular type of domain object, and provides an interface for the CRUD actions on that object type. - The
ManageApplicationsFormclass inherits fromAbstractManageDomainObjectsFormand holds a reference to the service object that it uses to conduct CRUD operations on the domain object
The AbstractManageDomainObjectsForm class plays an important role. It is shown in the following figure.
This class provides a public API that the controller objects can use to do the following:
- Get the list of domain objects to display
- Save a domain object that has been modified
- Delete one or more domain objects
- Create a new instance of the domain object
- Filter the domain object list
Abstract methods (the "do" methods) are defined that must be implemented for each concrete implementation. These are the methods that are implemented for concrete classes to interact with the database to perform CRUD operations. (Note that the service objects could be similarly abstracted using Generics that would make these abstract methods unnecessary.)
Sample Interactions
The following interaction shows how the list view is shown.
In this interaction, the request is delegated to the controller, which calls the getModel method. This method delegates to the doRefreshDomainObjects implementation and returns a Map that contains the list of domain objects to display and (optionally) the currently selected object, plus a few other things. The controller returns a ModelAndView that forwards to the configured list view (e.g., a JSP)
The following interaction shows how the delete operation is done.
In this interaction, the request is delegated to the controller, which calls the deleteDomainObjects method. This method delegates to the doDeleteDomainObjects implementation which deletes the specified domain objects. The controller returns a ModelAndView that redirects to the configured list url. This effectively runs the previous interaction, showing the list minus the deleted objects.
Adding Support for a New Object Type
To add support for a new object type, the following steps must be taken:
- Create an implementation of the
AbstractManageDomainObjectsfor the new object and configure it in the Spring configuration files as a session-scoped bean - Create a JSP for the list view and a JSP for the edit view
- Configure an instance of the
ManageDomainObjectControllerandEditDomainObjectControllerin the Spring configuration files
Typical configuration of the objects in Spring looks like this:
<bean id="manageApplicationsForm" class="com.bts.print.app.config.core.ManageApplicationsForm" scope="session">
<aop:scoped-proxy />
<property name="documentConfigurationService" ref="documentConfigurationService"/>
</bean>
<bean name="/manageapplications/*.htm" class="com.bts.print.app.util.mvc.ManageDomainObjectsController">
<property name="manageConfigsForm" ref="manageApplicationsForm" />
<property name="listViewName" value="manageApplications"/>
<property name="redirectToList" value="redirect:/manageapplications/show.htm"/>
<property name="redirectToEdit" value="redirect:/editapplication.htm"/>
</bean>
<bean name="/editapplication.htm" class="com.bts.print.app.util.mvc.EditDomainObjectController">
<property name="formView" value="editApplication" />
<property name="successView" value="redirect:/manageapplications/show.htm" />
<property name="commandName" value="app" />
<property name="commandClass" value="com.bts.print.domain.config.Application" />
<property name="manageConfigsForm" ref="manageApplicationsForm"/>
<property name="validator">
<bean class="com.bts.print.app.config.mvc.ApplicationValidator"/>
</property>
<property name="requiredFields">
<list>
<value>applicationName</value>
<value>priority</value>
</list>
</property>
</bean>
Notice that the ManageApplicationsForm bean is defined as scope="session" and includes the tag: "<aop:scoped-proxy />". This means that when this bean is injected into another bean, Spring actually injects a proxy that retrieves the appropriate instance from the current user's session.
Summary
This blog entry shows one way that you can create an editing framework that cleanly separates application code from framework code and allows support for new object types to be added quickly and easily.
Posted at 12:27PM Nov 18, 2007 by jim in Java | Comments[6]
Hello Sir,
I am new to spring and hibernate and I have to use it for my project.Could you please send me the sample source code for this CRUD application.Thanks in advance
Posted by sikta on February 07, 2009 at 12:39 AM CST #
Cud u pls send me the source code for this applicaton and the uml diagrams
thanks & regds
remi
Posted by remi on March 27, 2009 at 06:46 AM CDT #
Could you send me (or post) an example of the source code?
Posted by Turco on April 06, 2009 at 01:35 PM CDT #
Hi, I am from Peru
Could you send me your example of the source code for this CRUD application?
Thank you.
Posted by wroque on April 23, 2009 at 03:58 PM CDT #
vdvfd
Posted by 62.150.55.177 on June 02, 2009 at 03:42 AM CDT #
Hello sir. I have landed a job that I am clearly not qualified for. Rather than learn software development or apply any engineering to this assignment that is clearly over my head I want to ask you if you will send me the source code of your application and any UML diagrams you have created. With luck I can modify them with code cut and pasted from other blogs, allowing the kind sirs that hired me to bill their clients for thousands of hours for more software that doesn't come close to meeting their requirements. Also, build scripts and database schemas would be appreciated. If you could provide any deployment documentation, then my job will truly be done.
I appreciate your recognition of my entitlement to your hard work.
Posted by Chris on June 23, 2009 at 09:35 PM CDT #