Skip to main content

skip to main content

developerWorks  >  WebSphere  >

Developing a Spring Portlet MVC Framework application for use inside IBM WebSphere Portal: Handling form submissions

developerWorks
Document options

Document options requiring JavaScript are not displayed

Discuss

Sample code


Rate this page

Help us improve this content


Level: Advanced

Sunil Patil (spatil@atech.com), Senior Consultant, Ascendant Technology LLC

12 Feb 2008
Updated 20 Feb 2008

In this article, learn how you can handle form submission and generate dynamic content based on data submitted by users in a Spring Portlet MVC Framework portlet. Learn more about how Spring Portlet MVC Framework handles form submissions.

This article is the second in a three-part article series, "Developing a Spring Portlet MVC Framework application for use inside IBM WebSphere Portal." This is an advanced article; you should be familiar with the basics of developing JSR-168 portlets and have a basic understanding of Spring Framework although no advanced knowledge is required.

In the first article of this series, "Introduction to Spring Portlet MVC Framework," we talked about how you can develop a simple HelloWorld portlet using Spring Portlet MVC Framework. In this article, we cover how you can handle form submission and how to generate dynamic content, which is a common requirement in most real-world portlet applications.

IAs an example, develop a sample contact management application that allows you to create, retrieve, update, and delete (CRUD) contacts in the underlying data source. We also take a look at the sequence of events that happens when Spring Portlet MVC Framework receives a form submission request.

Handling form submission

The HelloWorld portlet that you developed in first part of this series has one important limitation: It does not support action processing, which is a basic requirement for most real-world portlet applications. Here, we develop a sample contact management application that allows a user to list, add, update, and delete contacts. To keep the development environment simple, we store the contact information in Hashmap, instead of in CONTACT table in the underlying database. Follow these steps for building the contact management application.

The first step is to create ContactManagPortlet as a dynamic Web application in IBM Rational Application Developer for WebSphere Software. Use /src/main/java as your Java source directory and /src/main/webapp as your Web content directory.

Then copy the pom.xml build script from the sample code for this article to the root directory of your new project. After you copy the build script, execute the mvn integration-test command, which downloads all the required dependencies for ContactManagPortlet.

After all the dependencies are downloaded, execute the mvn eclipse:eclipse command to add all the dependency JAR files in the classpath file for your project. When you right-click the ContactManagPortlet project and refresh it, you see all the dependency JAR files added in your project's build path.

Developing ContactDAO.java

On the development side, the first step is to define all the data access operations for the contact management application. Create the ContactDAO.java interface as shown in listing 1.


Listing 1. Code listing for ContactDAO.java
                

public interface ContactDAO {
	public ArrayList getContactList();
	public Contact getContact(String contactId);
	public int insertContact(Contact contact);
	public int updateContact(Contact contact);
	public int deleteContact(String contactId);
}

As you can see, the ContactDAO interface defines the create, retrieve, delete, and update (CRUD) operations for the contact management application.

Developing Contact.java

Next, create the Contact class, which is the DTO object used for carrying data between the Web part and the data access layer as shown in listing 2.


Listing 2. Code listing for Contact.java
                

public class Contact {
	private String contactId;
	private String firstName;
	private String lastName;
	private String email;
	private String phoneNumber;
	
public String getContactId() {
		return contactId;
	}
	public void setContactId(String contactId) {
		this.contactId = contactId;
	}
}

In the sample application, every contact record has five fields: contactId, firstName, lastName, phoneNumber, and email. Add getter and setter methods for all other fields, or copy Contact.java directly from the sample code of this article.

Next, copy com.ibm.developerworks.contact.service.HashmapContact.java and com.ibm.developerworks.contact.service.ContactDAOImpl.java from the sample code included in the Download section of this article. The ContactDAOImpl class implements the ContactDAO interface, and it delegates control to the HashmapContact object for the actual storage of the Contact records. The HashmapContact object stores the contact information in Hashmap, so your contact information is lost when the application restarts. You can create the ContactDAORDBMS.java class to store the contact information in the actual database.

Developing applicationContext.xml

Your next step is to create the applicationContext.xml file in the /WEB-INF/ folder as shown in listing 3.


Listing 3. Code listing for changes in applicationContext.xml
                

<bean id="contactDAO"
	class="com.ibm.developerworks.contact.service.ContactDAOImpl">
	<property name="hashMapContact" ref="hashMapContact"/>
</bean>
<bean id="hashMapContact"
	class="com.ibm.developerworks.contact.service.HashmapContact" />

NOTE: This is a partial listing of the applicationContext.xml file. Take a look at the sample code for the complete listing. We have added these two bean definitions to applicationContext.xml:

  • contactDAO. The contactDAO is the object of the ContactDAOImpl class and has the hashMapContact property.
  • hashMapContact. The hashMapContact bean is the object of the HashmapContact class. This is the Hashmap-based implementation of the contact table.

Spring Framework loads the applicationContext.xml file into the application context object. Note that Spring Framework creates a hierarchy of application contexts in which the child object can look at the parent, but the parent cannot look at the child object. The beans defined in the applicationContext.xml file are created at the portlet application level, and the bean in the portlet context can access the bean defined at the portlet application context level. The bean defined at the portlet application context level, though, cannot access the bean in the portlet context. In the sample code, contactDAO and hashMapContact beans are accessible at the portlet application level.

Developing InsertController.java

In Spring Portlet MVC Framework, to handle form submissions, you derive your Controller class from either AbstractFormController or its subclass. SimpleFormController is one of the concrete implementations of AbstractFormController, which provides a simple workflow for handling form submissions. Whenever SimpleFormController gets a request, it checks to determine if you are accessing a form page or submitting a form.

  • If you are accessing a form page, then it returns a formView page.
  • If you are submitting a form, then it reads the value of commandClass for this Controller, creates an object of commandClass, and populates its properties with the values submitted by the user on the form. Then it allows you to perform some business logic; after that, it displays the successView page to the user.

We cover this information in detail later in the article.

In the contact management application, you want to use InsertController both to display the new contact page to the user and to handle the page submission, so you create InsertController.java as shown in listing 4.


Listing 4. Code listing for InsertController.java
                


public class InsertController extends SimpleFormController{
	private ContactDAO contactDAO;
	public ContactDAO getContactDAO() {
		return contactDAO;
	}
	public void setContactDAO(ContactDAO contactDAO) {
		this.contactDAO = contactDAO;
	}
	
protected void onSubmitAction(ActionRequest request, ActionResponse response, 
Object command, BindException errors) throws Exception {
		contactDAO.insertContact((Contact)command);
		response.setRenderParameter("action", "list");
	}
}

As you can see, the implementation of InsertController is very simple. First, we have defined contactDAO as the property for this bean with the corresponding getter and setter methods. We decided to override the onSubmitAction() method of SimpleFormController. Inside the onSubmitAction() method, first we call the contactDAO.insertContact(contact) method, which inserts the new contact record in the underlying data source. Next, we set action as the render parameter with a value equal to "insert."

NOTE: SimpleFormController also defines the doSubmitAction(command) method, which is good enough for implementing your business logic. In our case, though, we want to redirect the user to the contact spreadsheet after adding the new contact. To do that, we pass control to SelectController during the rendering phase. Setting the action render parameter takes care of that.

Bean definition for insertController

How does Spring Portlet MVC Framework know which JSP file to use to display the Insert new contact page? How does it know that you want to use com.ibm.developerworks.contact.domain.Contact as the command class for InsertController? That's where the insertController bean definition becomes significant. Create SpringContactManag-portlet.xml in the /WEB-INF/ folder of your application and add the insertController bean definition as shown in listing 5.

Keep in mind that InsertController is the name of the Java class, and insertController is the name of the bean defined in the Spring context file. Normally, the first letter of the Java class name is capitalized. In the name of the bean defined in the Spring context file, the first letter of the name is lowercase.


Listing 5. Code listing for insertController bean definition in ContactManagPortlet-portlet.xml
                

<bean id="insertController" 
class="com.ibm.developerworks.contact.controller.InsertController">
	<property name="contactDAO" ref="contactDAO"></property>
	<property name="commandName" value="contact"/>
<property name="commandClass" value="com.ibm.developerworks.contact.domain.Contact" />
	<property name="formView" value="insert"></property>
	<property name="successView" value="list"></property>
</bean>l

In the sample code, we set values for the following insertController bean properties:

  • contactDAO. We pass the reference to the contactDAO bean, which is a service class that is responsible for the actual contact insertion. Remember that we declared the contactDAO bean in the applicationContext.xml file.
  • commandClass. In the sample code, we use the Contact class as the command class that is populated with values submitted by the user on the form.
  • commandName. The value of the commandName is used when you set the commandClass object in the model for this form.
  • formView. The value of the formView parameter is used to determine which view should be displayed to the user for taking input. In our sample code, when the user clicks the Add Contact link, we want to display the insert.jsp page, so the value of the formView property is insert. (We use InternalResourceViewResolver for ViewResolution, and it maps insert value to /WEB-INF/jsp/insert.jsp file.)
  • successView. The value of the successView parameter is used to determine the view to display to the user if the addition of the new contact is successful. In this case, we want to display the list.jsp file if the addition is successful, so the value of this property is list.

Developing insert.jsp

While defining the insertController bean, we configured insert.jsp as the value of the formView property. Spring Portlet MVC Framework tries to find the /WEB-INF/jsp/insert.jsp page when you click the Add Contact link on the contact spreadsheet. The next step is to create the insert.jsp page in /WEB-INF/jsp/insert.jsp as shown in listing 6.


Listing 6. Code listing for insert.jsp
                

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

<portlet:actionURL var="formAction">
	<portlet:param name="action" value="insert"/>
</portlet:actionURL>
<h3>Add New Contact</h3>
<form:form commandName="contact" method="post" action="${formAction}">
	<table cellpadding="4">
		<tr>
			<td>Contact Id</td>
<td><form:input path="contactId" size="30" maxlength="80"/></td>
		</tr>
		<tr>
<td><input type="submit" name="_finish" value="Save"/></td>
<td><input type="submit" name="_cancel" value="Cancel"/></td>
		</tr>
	</table>
</form:form>

The insert.jsp page has three tag library declarations. You are already familiar with two of them, the jstl tag library and the portlet tag library. In addition, we also define the form tag library. Starting with version 2.0, Spring Framework provides the form tag library, which can be used by JSP files that are included from either Web MVC Framework or Portlet MVC Framework application code.

The form tag library is integrated with Spring Portlet MVC Framework and gives access to the command object. In the insert.jsp file, <form:form> is the first tag that you use to generate the HTML <form> tag in the final markup. This tag also reads the command object and sets it in the pageContext of your JSP file. In the sample code, commandName is the contact so the value of the commandName attribute for the <form> tag is contact.

NOTE: All other tags in the form tag library are nested tags for the <form> tag. The next form tag library tag that we use is <input>, which is used to generate the <input type="text"> element in the final markup. In the sample code, we want to bind the contactId input to the contactId property in the Contact object, and for that we have added a path attribute with its value equal to contactId. Note that this is a partial code listing for insert.jsp; the complete listing is in the sample code listed in the Download section of this article.

Developing SpringContactManagPortlet-portlet.xml

Your next step is to add a couple of bean definitions in SpringContactManagPortlet-portlet.xml as shown in listing 7.


Listing 7. Code listing for changes in SpringContactManagPortlet-portlet.xml
                

<bean id="parameterMappingInterceptor" 
class= "org.springframework.web.portlet.handler.ParameterMappingInterceptor" />
<bean id="portletModeParameterHandlerMapping" 
class= "org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping">
	<property name="interceptors">
		<list>
			<ref bean="parameterMappingInterceptor" />
		</list>
	</property>
	<property name="portletModeParameterMap">
		<map>
			<entry key="view">
				<map>
					<entry key="select">
						<ref bean="selectController" />
					</entry>
					<entry key="insert">
						<ref bean="insertController" />
					</entry>
				</map>
			</entry>
		</map>
	</property>
</bean>

As you can see, we have defined two more bean definitions in the SpringContactManagPortlet-portlet.xml file.

  • parameterMappingInterceptor. The parameterMappingInterceptor is used to forward the value of the action request parameter from ActionRequest to RenderRequest, so that Spring Portlet MVC Framework uses the same controller for handling both the action request and the render request. We talk more about this later in this article.
  • portletModeParameterHandlerMapping. portletModeParameterHandlerMapping is an advanced implementation of HandlerMapping that uses the portlet mode as well as the value of the action request parameter to resolve the handler for the request. In the sample code, we have more than one handler in View mode so we use portletModeParameterHandlerMapping. The portletModeParameterHandlerMapping bean has the portletModeParameterMap property, which is a map of all the portlet modes that your portlet supports. This map takes key value pairs with the name of the portlet mode as the key. Value is another map that takes the value of the action request parameter as the key and the reference to the controller that handles its request as its value.

In the sample code, you want to support only the View mode so that the top-level map has only one entry. The second-level map, though, has a key equal to insert, and its value refers to the insertController bean. As a result, when this portlet gets a request with the action parameter equal to insert in View mode, it passes control to InsertController for handling it.

The last step in building this sample code is to copy the additional files SelectController.java, UpdateController.java, DeleteController.java, and the corresponding JSP files, list.jsp and update.jsp, from the sample code for this article. After you have copied all the necessary files from the sample code, execute the mvn package command to build your portlet application. When the WAR file is ready, you can test it on IBM WebSphere Portal.



Back to top


How action processing works

Spring Portlet MVC Framework performs many actions in the background; in the long run, after you get comfortable with the software, this can be a big advantage. In the short run, though, that approach may be difficult to understand. In this section, we talk about what happens in the background when DispatcherPortlet gets an action request; see figure 1.


Figure 1. Sequence diagram for the sequence of events that occur when DispatcherPortlet receives an action request
Sequence diagram for the sequence of events that occur when DispatcherPortlet receives an  action request

The following sequence of events occurs when the DispatcherPortlet gets an insert action request.

  1. DispatcherPortlet checks if multipart request processing is enabled for your portlet. If it is enabled, then DispatcherPortlet checks if the request is multipart; that is, the enctype attribute for your HTML <form> element is set to multipart/form-data. If it is, then it wraps that request in the object of MultipartActionRequest.
  2. DispatcherPortlet goes through the list of all HandlerMappings configured in your portlet application, calling its getHandler() method to get the appropriate handler for the current request. In the sample code, we configured only one HandlerMapping implementation class, PortletModeParameterHandlerMapping. When it gets control, it checks the portlet mode of the current request, which is View mode in this case, and the value of the action request parameter, which is insert. Now while defining the portletModeParameterHandlerMapping bean in SpringContactManagPortlet-portlet.xml, the insert key is mapped to InsertController, so it returns the object of InsertController.
  3. After DispatcherPortlet knows that InsertController is responsible for handling this request, it starts iterating through all the interceptors for this handler, calling their preHandleAction() method. In the sample code, we configured only one interceptor class, ParameterMappingInterceptor, so its preHandleAction() method is called.
  4. The ParameterMappingInterceptor is used to forward the value of the action request parameter from ActionRequest to RenderRequest, so it sets the render parameter with a name equal to action and a value equal to insert.

    NOTE: Spring Portlet MVC Framework tries to resolve Handler for the current request in both action phases as well as the render phase. If you want Spring Portlet MVC Framework to use the same Handler for both the action and render phases, then you use ParameterMappingInterceptor.
  5. DispatcherPortlet calls the handleActionRequest() method of InsertController; this is the place where the actual action processing happens. In the sample code, InsertController extends SimpleFormController so that it follows the action request lifecycle defined by SimpleFormController.
  6. The SimpleFormController first reads the name of the commandClass that is configured for InsertController, which is com.ibm.developerworks.contact.domain.Contact, and creates its object.
  7. After that, SimpleFormController creates the object of PortletRequestDataBinder, which is responsible for populating the Contact object with the values submitted by the user on the form. For example, it reads the value of the firstName request parameter and sets it as the value of the firstName property in the Contact object.
  8. You can override the initBinder() method in your class if you want Spring Portlet MVC Framework to use some custom logic while converting the request parameter value into the command class property value. For example, you can specify how to convert String to Date or MultiPartFile to byte[] array. We show examples of this in later in this article.
  9. After the Contact bean is populated with the values submitted by the user, SimpleFormController iterates through all the Validators in your application calling its validate() method. Here you can write your server-side validation logic. For example, you can check that contact Id is a required field. We talk more about this later in this article.
  10. After performing validation, SimpleFormController checks whether or not any validation errors occurred. If no errors occurred, it calls onSubmitAction()/doSubmitAction() in your InsertController. Normally, we recommend that you override doSubmitAction() in your Controller class. In the sample code, though, we want to redirect control to SelectController for the rendering phase so we override the onSubmitAction() phase.

After the action phase is completed, DispatcherPortlet checks if any validation errors occurred. If errors did occur it reads the value of formView and redirects the user to that page. If there are no validation errors, then it redirects the user to the successView page.



Back to top


Conclusion

In this article, we covered how you can develop a sample contact management application using Spring Portlet MVC Framework. We discussed how you can create a class overriding SimpleFormController that forwards control to the value defined by the formView property when it gets a GET request and forwards control to the value defined by the successView property when it gets a POST request and action processing was successful. We also discussed all the configuration files that you need to create and covered how to use the custom tag library defined by Spring Portlet MVC Framework.

In the last part of this series, we discuss some of the advanced topics in Spring Portlet MVC Framework, such as handling form validation, handling exceptions gracefully, and internationalization. We also demonstrate how you can integrate Apache Tiles Framework with Spring Portlet MVC Framework.




Back to top


Download

NameSizeDownload method
part-2.zip14KBHTTP
Information about download methods


Resources

Learn

Get products and technologies

Discuss


About the author

Sunil Patil is a Senior Consultant working at Ascendant Technologies LLC. He is the author of several IBM developerWorks articles and a book, Java Portlets 101.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top