Introduction
Most of the webapplications are implemented by Model-View-Controller(MVC) pattern. There are plenty of good frameworks use
the MVC paradigm. Obviously, MVC becomes defacto standard for a webapplication because of it's maintainability
and clear seperation of presentation layer and the business layer. Spring is one amoung the group, a lightweight
container used in the enterprise development, also it provides
a good implementation of MVC for its presentation layer. In realtime most of the applications and companies already made
a huge investment on Struts and other popular frameworks. They want to stick with the old frameworks and also want to enjoy
the features of Spring framework. Spring is more flexible than any other framework, spring provides abstract layer
for every framework to integrated into the them. In this article, i will explain you the way how you can integrate
few of the popular frameworks in web development, When you read the whole article, you will be more familiar with
various integration methods on each framework and i will explain spring webflow which is a subproject in the Spring community.
let's start with integrating Struts into Spring.
Working with Struts
When talk about the Mode View Controller(MVC), Struts is still leading the industry. Struts become defacto for the MVC
implementation. Struts project is started in the 2000 by McClann from Apache Foundation,
it is the first Open Source project to implement the MVC and become more pupular in the web development.
There after lots of projects come up with MVC, but nothing can sack the Struts dominance because of it's
simplicity and easy to understand. In this section, we will look into how to integrate Struts with Spring framework.
There are two ways for integrating spring and Struts together.
- Struts actions that extend Spring aware base class
- Delegating requests to Struts actions that are managed as Spring beans
1. Register with Struts plug-in
In order for Struts to access the Spring beans, you will have to register Spring application context into the Struts plug-in.
Add the following code in your Struts-config.xml:
<plug-in className="org.springframework.web.Struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/servlet.xml"/>
</plug-in>
2. Write spring aware Struts actions
One way to integrate Struts and Spring is to write Spring aware Struts
actions. In order to achieve that, your Struts action class will extend
ActionSupport instead of traditional Struts Action. We need not write
ActionSupport, it is implementaed by Spring framework. By extending ActionSupport,
the Spring beans configured in the spring application context will available in the Struts action.
I wrote a very simple example program to demonstrate the two ways to
integrate Struts with Spring, when the form is rendered it gets book id
from the user and tells whether the book is availble in the BookStore
or not. For the program purpose, I stored the list of book id and book
names in a HashMap. When user enters book id, it checks with the book
store for its availability.
We are extending ActionSupport class which is provided by
Spring framework for Struts abstract layer. By extending this class we
can use getWebApplicationContext() to get the Spring
application context. Once, we have the application context, use
getBean() method to get the spring managed beans. Spring managed beans
are loaded at the server startup from configuration files. See the
action class example:
public class ActionSupportAction extends ActionSupport{
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response){
DynaActionForm searchForm = (DynaActionForm) form;
try{
String bookId = (String)searchForm.get("bookName");
ApplicationContext appContext = getWebApplicationContext();
BookStore bookService = (BookStore) appContext.getBean("bookService");
HashMap books = (HashMap)bookService.getBookNames();
String bookName = (String)books.get(bookId);
if (bookName != null){
request.setAttribute("BOOK_NAME",bookName);
request.setAttribute("BOOK_ID",bookId);
request.setAttribute("STATUS","AVAILABLE");
}else{
request.setAttribute("BOOK_ID",bookId);
request.setAttribute("STATUS","NOTAVAILABLE");
}
}catch (Exception e){
e.printStackTrace();
}
return mapping.findForward("success");
}
}
This technique is simple and
easy to understand. But, tightly couples Struts action with the spring framework. If you want to replace the spring,
you will have to rewrite the code. In most cases this is not a desirable solution.
3. Delegate to Struts actions
Another approach to Spring and Struts integration is delegating all the
request to the Struts action class and wiring Spring beans into the
Struts action class. Noramlly, you would register Struts action in
Struts-config.xml, but instead we are going to register the proxy
action org.springframework.web.Struts.DelegatingActionProxy. Spring provides the proxy action class for you. Add the following entry in Struts-config.xml
for action class:
<action path="login" type="org.springframework.web.Struts.DelegatingActionProxy"/>
public class DelegateToSpringAction extends Action{
private BookStore bookService;
public ActionForward execute(ActionMapping mapping, ActionForm actionForm,
HttpServletRequest request, HttpServletResponse response){
try{
DynaActionForm delegateForm = (DynaActionForm)actionForm;
String bookId = (String)delegateForm.get("bookName");
HashMap books = (HashMap)bookService.getBookNames();
String bookName = (String)books.get(bookId);
if (bookName != null){
request.setAttribute("BOOK_NAME",bookName);
request.setAttribute("BOOK_ID",bookId);
request.setAttribute("STATUS","AVAILABLE");
}else{
request.setAttribute("BOOK_ID",bookId);
request.setAttribute("STATUS","NOTAVAILABLE");
}
}catch (Exception e){
e.printStackTrace();
}
return mapping.findForward("success");
}
public BookStore getBookService() {
return bookService;
}
public void setBookService(BookStore bookService) {
this.bookService = bookService;
}
}
In the above example, setBookService() is used by the spring managed beans to inject the BookStore referance to the
Action class. This is much better solution than the previous one. The main advantage of this solution is Struts
doesn't know anything about spring. If you want to modify anything in spring, it will not affect the Struts layer.
One drawback in this approach is, when someone sees Struts-config.xml all the configuration will be mapped to the same action class.
It may leads to confustion.
Spring Web Flow(SWF)
In the traditional web applications
defining web flow is not trivial. Frameworks like Struts and Spring use
Model-Videw-Controller(MVC) pattern to split the a applications into
three different layers as Model for the business operations like
database access, View for the presentation layer(jsp,etc) and
controller is written for handling all the incoming requests. Each URL
is mapped to a particular view that is configured in the configuration
XML file. Based on the information configured in the XML files the
display is rendered. The problem in this technique is we cannot define
a flow of requests. Each request is considered as an individual part
and will be lost when next request is served. We need a better solution
to come across this restriction.
At this time, Spring framework developers started a subproject called Spring Web Flow(SWF) to solve this issue.
Unlike traditional applications, we can define a web flow with number of requests chained and declare a name
for that webflow. It canbe reused in other places of the application. Here i will explain how to configure
an webflow within your application.
Any simple application must follow the following steps to define a SWF :
- Flow design
- Create webflow configuration file
- Write Action implementation
- Create Views
- Deploy the flow
To use spring webflow in your application, you must include spring-webflow.jar and spring-binding.jar into
your classpath. We will take a very simple example and follow the above steps to complete a webflow. In this
section i will explain how to write SWF for simple form submision.
1. Now, you must define a flow for your application. In our example the flow should be:
- Render a from with input fields to the browser
- When you submit the form, the result view is choosen upon the condition
2. Next, design your configuration file for webflow definition.
This configuration file will be mapped through
Spring application context configuration file.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE webflow PUBLIC "-//SPRING//DTD WEBFLOW //EN"
"http://www.springframework.org/dtd/spring-webflow.dtd">
<webflow id="simpleFlow" start-state="viewForm">
<view-state id="viewForm" view="form">
<transition on="submit" to="processSubmit"/>
</view-state>
<action-state id="processSubmit">
<action bean="testFlowAction"/>
<transition on="success" to="finish"/>
</action-state>
<end-state id="finish" view="success"/>
</webflow>
The configuration file uses two different states: view state and action state. These two states are used for defining the
views and actions respectively. View state triggers the rendering of a view resource(jsp, etc.) when entered. The web flow
system expects its logical view name to be mapped to a physical view source by calling front controller. Its handeled
by the ViewResolver in Spring MVC.
An action state excutes one or more implementations of the Action
interface when entered. Typicaly, the action class delegate down to the
service-layer to perform business operations. Action act as the
interface between the web-tier and the service layer. When an Action
completes execution, it signals a logical result outcome. The result is
treated used for a state transition in the callin g ActionState. Action
can also be chained together with ease, either by configuaring multiple
Actions for a single Action or execute in order.
3. Next, Create your flow action.
Next step is to write a action class for webflow. This class will have all the methods to handle the different
events triggered from the user. In our example we have written processSubmit() method to handle the
form submission.
public class TestFlowAction extends Form Action{
public TestFlowAction(){
setFormObjectName("myFormObject");
setFormObjectClass(MyFormObject.class);
}
public Event processSubmit(RequestContext context) throws Exception{
return success();
}
}
4. Next, Configure Spring application context.
We must include the declartion for Spring web flow configuration file and Action class implementations into the Spring
application context file configuration. This file is the heart of Spring framework, all the beans are declared in this file.
Another important entry to the same file is FlowController mapping to the form.
<bean id="myFlow" class="org.springframework.webflow.config.XmlFlowFactoryBean">
<property name="location">
<value>
/WEB-INF/myFlow.xml
</value>
</property>
<bean id="myFlowAction" class="org.swf.TestFlowAction"/>
<bean name="swf.html" class="org.springframework.webflow.mvc.FlowController"/>
5. Create views
When you
finish your configuration files and Action class implementation, you
have to create the views for presentation layer. In this article, we
created a form.jsp as the initial dispaly page for our sample. This
page contains one text field and a submit button, upon submiting the
form the process will be taken care by the spring web flow.
<html>
<head>
<title>Spring Web Flow - Test Program</title>
</head>
</body>
<form action="swf.html">
<table>
<tr>
<td>
<input type="text" name="bookName">
</td>
<td>
<input type="submit" name="_event_Id_submit" >
<input type="hidden" name="_flowExecutionId" value="${flowExecutionId}" >
</td>
</tr>
</table>
<form>
<body>
</html>
6. Test the flow.
When you
completed all the steps, lastly you access the flow simply
swf.html?flow_id=myFlow. After this URL is typed in the browser, the
flow is created in the server side and initial form is rendered. When
you submit the form, processSubmit() is
called on the server side. End of the flow it returns success and returns the final view to the client.
|