At line 1 added 101 lines |
!!! Porting the Shipping Rate SWF sample to RSF with SWF |
|
This page documents my efforts to port the [Shipping Rate - An Ajax-enabled Spring Web Flow Sample|http://spring.ervacon.com/swf-shippingrate/] [Spring Web Flow (SWF)|SpringWebFlow] app to using the [RSF/SWF integration|RSFSpringWebFlow].\\ |
This conversion took approximately 6 hours to complete (including documenting the process). Breakdown is as follows: approximately 1 hour to make the original app work with Maven2, 1 hour to understand the structure of the sample app, 1 hour for initial structure setup and cleanup, 1 hour to convert the JSPs to html templates with rsf:ids, 1 hour to write the RSF producers, 1 hour to for miscellaneous changes (updates to .xml, .properties).\\ |
I would estimate that a real app conversion for an app this size would take only 3 hours since documenting the process and understanding the app would not be required. You could probably save almost another hour if the app was already using maven2.\\ |
Feel free to send me ([Aaron Zeckoski|People]) questions or comments (or using the [mailing list|EmailLists]). |
|
|| __Sample Code (SVN):__ | [original code (with maven2 build)|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/orig] | [RSF SWF version|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/RSFSWF] |
[Try out Shipping Rate RSF SWF on our server|http://ponder.org.uk/SWFShippingRate-RSFSWF/faces] |
|
!! My development environment |
* Java 1.5 |
* Tomcat 5.5.12 |
* Maven2 |
* Eclipse 3.2 |
* Windows XP ''(any OS should be fine)'' |
__NOTE:__ Want [instructions setting up a similar development environment|ContainerSetupGuide]? |
|
!! Getting started |
First thing I had to do was get the SWF sample code up and running on my machine. |
# Went to the [Spring Download page|http://www.springframework.org/download] and grabbed version 1.0.4 of SWF (this just goes over to sourceforge for the [spring-webflow-1.0.4.zip|http://downloads.sourceforge.net/springframework/spring-webflow-1.0.4.zip?modtime=1182395228&big_mirror=0]) |
# Extracted the package and grabbed the shippingrate app (spring-webflow-1.0.4\projects\spring-webflow-samples\shippingrate) and copied it over to my desktop |
# Imported the sample app in eclipse and added a maven2 [pom.xml file|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/orig/pom.xml] (also adjusted the [.classpath file|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/orig/.classpath] to all required jars to use M2_REPO variable). |
#* __TIP:__ Look at the {{ivy.xml}} file to get the required dependency list and versions |
#* __TIP:__ Don't forget to define a ''M2_REPO'' classpath variable in eclipse which points to your local maven2 repository |
# Built the project using maven2 by running {{mvn install}} |
# Started up tomcat and accessed the app at: ''[http://localhost:8080/SWFShippingRate-orig-1.0/]'' |
# Checked in the [code for the original version|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/orig] to the CARET SVN |
|
!! Creating the RSF version |
|
! Initial structure setup and cleanup |
|
# Branched the [original code|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/orig] to create the [RSFSWF version|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/RSFSWF]. |
# Adjusted the maven2 {{pom.xml}} to remove unneeded dependencies (webmvc, web, etc.) and added in the rsf-util and spring-aop dependencies. |
#* Also changed the Spring version to 2.0.4 to make it easier for maven2 to sync and require less specified dependencies in the {{pom.xml}} |
# Added rsf-swf and rsfutil jars to the eclipse classpath (using the M2_REPO variable) |
# Added in an RSF standard {{content}} directory under {{/src/main/webapp}} |
# Added in RSF standard {{content/templates}}, {{content/css}}, and {{content/images}} directories |
# Moved *.jsp files to {{content/templates}} and renamed all files to .html |
#* Removed the old {{jsp}} directory |
# Updated the headers of all .html files to remove taglibs and added in standard RSF headers (also removed meta tag) |
# Moved *.jpg to {{content/images}} and removed old {{/src/main/webapp/images}} directory |
# Copied in the rsf logo and fixed the relative path to all images in the templates |
#* Added logos to the front page, they were not used in the original app |
# Moved {{/src/main/webapp/style.css}} file to {{content/css}} |
# Added the css to the index header |
#* Adjusted css since body font size was too small to read on high definition screens |
# Added {{/src/main/webapp/WEB-INF/messages/messages_en.properties}} file for internationalized messages |
# Created an {{rsf}} package in {{org.springframework.webflow.samples.shippingrate}} |
# Added {{params}} and {{producers}} packages to the {{rsf}} package |
|
! Actual real conversion work |
# Updated the {{/src/main/webapp/WEB-INF/web.xml}} file to include the RSF standard contexts and servlets |
#* This basically means completely overwriting what is there except you can keep the {{classpath:org/springframework/webflow/samples/shippingrate/domain/services.xml}} |
#* Here is a link to the [new web.xml file|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/RSFSWF/src/main/webapp/WEB-INF/web.xml] for easy reference |
# Create an {{applicationContext.xml}} and {{requestContext.xml}} file in {{/src/main/webapp/WEB-INF}} |
#* Here are links to each for easy reference: [applicationContext.xml|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/RSFSWF/src/main/webapp/WEB-INF/applicationContext.xm], [requestContext.xml|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/SWFShippingRate/RSFSWF/src/main/webapp/WEB-INF/requestContext.xm] |
#* ''OPTIONAL:'' added an RSF config set under [SpringIDE|http://springide.org/blog/] which includes all spring files |
# Removed the {{/src/main/webapp/WEB-INF/shippingrate-servlet.xml}} (it mostly has webmvc beans which we do not need) |
#* Copied over the 3 flow bean definitions from within this file ({{flowExecutor}}, {{flowRegistry}}, and {{formAction}}) to the {{applicationContext.xml}} |
#* Updated the header of the {{applicationContext}} to include the flow xmlns {{xmlns:flow="http://www.springframework.org/schema/webflow-config"}} |
# Went through each .html template and removed the JSP code and replaced it with ''rsf:ids'' |
#* This mostly involved the removal of non-standard html tags like {{<c:...}} and {{<spring:...}} |
#* This also involved some moving around of tags to improve the xhtml |
#* Also removed hidden input fields which were carrying along the flow id |
# Created [producers|ComponentProducer] for each of the html files in the producers package |
#* This is the ''best practice'' way to create RSF view producers |
## Create a class named <template>Producer which implements {{ViewComponentProducer}} |
## Create a {{public final static String VIEW_ID = "<template>";}} which is set to the template without .html |
## Make the {{getViewID}} method return the VIEW_ID variable |
# Added all producer bean definitions to the {{requestContext.xml}} file |
# Made the IndexProducer implement {{DefaultView}} so it is the starting page for the app |
# Added real code to the {{IndexProducer}} to create the links to initiate the flow inside a form so we can start it using an ajax call |
#* Added in special form tag to allow us to get the flow start url \\{{<form rsf:id="rate_flow_link_form" action="selectCustomer.html" />}} |
#* Create the form: {{UIForm form = UIForm.make(tofill, "rate_flow_link_form");}} |
#* Create a link to start a flow and put it in a form: {{form.viewparams = new SWFLaunchViewParams("getRate-flow");}} |
# Added real code to the {{SelectCustomerProducer}} to connect data to the form and associate the submit with the flow |
#* Use the RSF convention of {{SWFBindingBean}} to proxy data to the flow formObject, this points to the {{org.springframework.webflow.samples.shippingrate.domain.RateCriteria.java}} object (defined by the ''formObjectClass'' in the ''formAction'' bean) which has fields on it like {{.residential}}, \\For example: {{UISelect choices = UISelect.make(form, "customer_choices", customerOptions, customerLabels, "SWFBindingBean.residential");}} |
#** __NOTE:__ Here we are putting data into the ''rateCriteria'' bean (defined by the ''formObjectClass'' in the ''formAction'' bean) |
#* Use the RSF convention of {{SWFEventBean}} to continue the flow, this ties to the {{view-state}} in the flow \\({{/src/main/webapp/WEB-INF/flows/getRate-flow.xml}}) and the related ''transition'' which will have an ''on'', \\For example: {{<transition on="submit" to="selectSender">}} for __view-state id=selectCustomerType__ |
# Added the injection for the {{RateService}} to the remaining producers |
#* it is used in every view except {{IndexProducer}} and {{SelectCustomerProducer}} |
# Added functional code to the remaining producers (this is basic Java and RSF code so I will not go into detail here) |
#* This did involve injecting the {{RateCriteria}} bean into the final view so that we could send it to the {{RateService}} |
# Added the validation messages from {{/src/main/java/org/springframework/webflow/samples/shippingrate/domain/RateCriteriaValidator.java}} to the {{/src/main/webapp/WEB-INF/messages/messages_en.properties}} |
#* This is because RSF only allows internationalized messages |
#* We had to add one additional validation message because of an internal Spring exception message which RSF does not have access to |
# Committed the changed code to the [CARET SVN repository RSF samples trunk|https://saffron.caret.cam.ac.uk/svn/projects/RSFSamples/trunk/] |
|
! Running the sample app |
# Built and deployed the project using maven2 by running {{mvn install cargo:deploy}} from the main directory |
# Started up tomcat and accessed the app at: ''[http://localhost:8080/SWFShippingRate-SWFRSF-1.0/faces/]'' |
# Tested the various flows |
|
! Differences in app function |
|
! Summary of needed changes |
* No flows were changed and the logic for the application was not touched |
* The "views" (JSPs) were transformed into RSF views (producers and templates) and various RSF bits were added (contexts) |
* A few other RSFisms like internationalized messages and the web.xml had to be updated or added |