Introduction
Most of the web applications 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 web application because of it’s maintainability and clear separation of presentation layer and the business layer. Spring is one among 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.
also read:
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:
<br /><plug-in className="org.springframework.web.Struts.ContextLoaderPlugIn"><br /><%%KEEPWHITESPACE%%> <set-property property="contextConfigLocation" value="/WEB-INF/servlet.xml"/><br /><%%KEEPWHITESPACE%%> </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 StrutsAction
. We need not writeActionSupport
, it is implementaed by Spring framework. By extendingActionSupport
, 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:<br />public class ActionSupportAction extends ActionSupport{<br /><%%KEEPWHITESPACE%%> public ActionForward execute(ActionMapping mapping,<br /><%%KEEPWHITESPACE%%> ActionForm form,<br /><%%KEEPWHITESPACE%%> HttpServletRequest request,<br /><%%KEEPWHITESPACE%%> HttpServletResponse response){<br /><%%KEEPWHITESPACE%%> DynaActionForm searchForm = (DynaActionForm) form;<br /><%%KEEPWHITESPACE%%> try{<br /><%%KEEPWHITESPACE%%> String bookId = (String)searchForm.get("bookName");<br /><%%KEEPWHITESPACE%%> ApplicationContext appContext = getWebApplicationContext();<br /><%%KEEPWHITESPACE%%> BookStore bookService = (BookStore) appContext.getBean("bookService");<br /><%%KEEPWHITESPACE%%> HashMap books = (HashMap)bookService.getBookNames();<br /><%%KEEPWHITESPACE%%> String bookName = (String)books.get(bookId);<br /><%%KEEPWHITESPACE%%> if (bookName != null){<br /><%%KEEPWHITESPACE%%> request.setAttribute("BOOK_NAME",bookName);<br /><%%KEEPWHITESPACE%%> request.setAttribute("BOOK_ID",bookId);<br /><%%KEEPWHITESPACE%%> request.setAttribute("STATUS","AVAILABLE");<br /><%%KEEPWHITESPACE%%> }else{<br /><%%KEEPWHITESPACE%%> request.setAttribute("BOOK_ID",bookId);<br /><%%KEEPWHITESPACE%%> request.setAttribute("STATUS","NOTAVAILABLE");<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }catch (Exception e){<br /><%%KEEPWHITESPACE%%> e.printStackTrace();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> return mapping.findForward("success");<br /><%%KEEPWHITESPACE%%> }<br />}<br />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:<br /><action path="login" type="org.springframework.web.Struts.DelegatingActionProxy"/><br />
<br />public class DelegateToSpringAction extends Action{<br /><%%KEEPWHITESPACE%%> private BookStore bookService;<br /><%%KEEPWHITESPACE%%> public ActionForward execute(ActionMapping mapping, ActionForm actionForm,<br /><%%KEEPWHITESPACE%%> HttpServletRequest request, HttpServletResponse response){<br /><%%KEEPWHITESPACE%%> try{<br /><%%KEEPWHITESPACE%%> DynaActionForm delegateForm = (DynaActionForm)actionForm;<br /><%%KEEPWHITESPACE%%> String bookId = (String)delegateForm.get("bookName");<br /><%%KEEPWHITESPACE%%> HashMap books = (HashMap)bookService.getBookNames();<br /><%%KEEPWHITESPACE%%> String bookName = (String)books.get(bookId);<br /><%%KEEPWHITESPACE%%> if (bookName != null){<br /><%%KEEPWHITESPACE%%> request.setAttribute("BOOK_NAME",bookName);<br /><%%KEEPWHITESPACE%%> request.setAttribute("BOOK_ID",bookId);<br /><%%KEEPWHITESPACE%%> request.setAttribute("STATUS","AVAILABLE");<br /><%%KEEPWHITESPACE%%> }else{<br /><%%KEEPWHITESPACE%%> request.setAttribute("BOOK_ID",bookId);<br /><%%KEEPWHITESPACE%%> request.setAttribute("STATUS","NOTAVAILABLE");<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }catch (Exception e){<br /><%%KEEPWHITESPACE%%> e.printStackTrace();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> return mapping.findForward("success");<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> public BookStore getBookService() {<br /><%%KEEPWHITESPACE%%> return bookService;<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> public void setBookService(BookStore bookService) {<br /><%%KEEPWHITESPACE%%> this.bookService = bookService;<br /><%%KEEPWHITESPACE%%> }<br />}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.
<br /><?xml version="1.0" encoding="UTF-8"?><br /><%%KEEPWHITESPACE%%> <!DOCTYPE webflow PUBLIC "-//SPRING//DTD WEBFLOW //EN"<br /><%%KEEPWHITESPACE%%> "http://www.springframework.org/dtd/spring-webflow.dtd"><br /><br /><%%KEEPWHITESPACE%%> <webflow id="simpleFlow" start-state="viewForm"><br /><%%KEEPWHITESPACE%%> <view-state id="viewForm" view="form"><br /><%%KEEPWHITESPACE%%> <transition on="submit" to="processSubmit"/><br /><%%KEEPWHITESPACE%%> </view-state><br /><%%KEEPWHITESPACE%%> <action-state id="processSubmit"><br /><%%KEEPWHITESPACE%%> <action bean="testFlowAction"/><br /><%%KEEPWHITESPACE%%> <transition on="success" to="finish"/><br /><%%KEEPWHITESPACE%%> </action-state><br /><%%KEEPWHITESPACE%%> <end-state id="finish" view="success"/><br /><%%KEEPWHITESPACE%%> </webflow><br />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.<br />public class TestFlowAction extends Form Action{<br /><%%KEEPWHITESPACE%%> public TestFlowAction(){<br /><%%KEEPWHITESPACE%%> setFormObjectName("myFormObject");<br /><%%KEEPWHITESPACE%%> setFormObjectClass(MyFormObject.class);<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> public Event processSubmit(RequestContext context) throws Exception{<br /><%%KEEPWHITESPACE%%> return success();<br /><%%KEEPWHITESPACE%%> }<br /><%%KEEPWHITESPACE%%> }<br /><br />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.
<br /><bean id="myFlow" class="org.springframework.webflow.config.XmlFlowFactoryBean"><br /><%%KEEPWHITESPACE%%> <property name="location"><br /><%%KEEPWHITESPACE%%> <value><br /><%%KEEPWHITESPACE%%> /WEB-INF/myFlow.xml<br /><%%KEEPWHITESPACE%%> </value><br /><%%KEEPWHITESPACE%%> </property><br /><br /><%%KEEPWHITESPACE%%> <bean id="myFlowAction" class="org.swf.TestFlowAction"/><br /><br /><%%KEEPWHITESPACE%%> <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.
<br /><html><br /><%%KEEPWHITESPACE%%> <head><br /><%%KEEPWHITESPACE%%> <title>Spring Web Flow - Test Program</title><br /><%%KEEPWHITESPACE%%> </head><br /><%%KEEPWHITESPACE%%> </body><br /><%%KEEPWHITESPACE%%> <form action="swf.html"><br /><%%KEEPWHITESPACE%%> <table><br /><%%KEEPWHITESPACE%%> <tr><br /><%%KEEPWHITESPACE%%> <td><br /><%%KEEPWHITESPACE%%> <input type="text" name="bookName"><br /><%%KEEPWHITESPACE%%> </td><br /><%%KEEPWHITESPACE%%> <td><br /><%%KEEPWHITESPACE%%> <input type="submit" name="_event_Id_submit" ><br /><%%KEEPWHITESPACE%%> <input type="hidden" name="_flowExecutionId" value="${flowExecutionId}" ><br /><%%KEEPWHITESPACE%%> </td><br /><%%KEEPWHITESPACE%%> </tr><br /><%%KEEPWHITESPACE%%> </table><br /><%%KEEPWHITESPACE%%> <form><br /><%%KEEPWHITESPACE%%> <body><br /><%%KEEPWHITESPACE%%> </html>6. Test the flow.
also read:
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.