Introduction
SincethereleaseofStruts1.0,StrutshasgraduallybecomeadefactostandardforMVC(a.k.a.Model-2)implementationfordevelopingmedium-to-largescaleweb-basedapplicationsontheJavaplatform.StrutsfitsnicelyintheJ2EEtechnologystackandfillsthegapwhichisnotaddressedneitherbytheServlet/JSPstandardortheEJBstandard.GiantslikeIBMandOraclehavestartedembracingandsupportingStrutsintheirproductset.
BuiltonthesuccessofStruts1.0,Struts1.1betawasreleasedinMarchthisyearandshowcasedatJavaOne2002andthelatestStruts1.1beta-2wasreleasedjusttwoweeksago.TheimmediatequestionexistingStrutsusersorevaluatorswillhaveis"ShouldInowconsidertomigratemyexistingapplicationstoStruts1.1andstarttodevelopmynewprojectonStruts1.1?"
Toanswerthisquestion,weneedtoconsiderwhatimportantnewfeaturesareofferedin1.1andexaminewhatimpactsthereareonexistingprojectstomigratefrom1.0to1.1.
NewFeatures
Insteadofoverwhelmingyouwiththefulllistofallthenewfeatures,IwillgothroughthemostsignificantenhancementsinStruts1.1inthissection.
MultipleSub-applications
OneoftheshortcomingsinStruts1.0ismanageabilityoftheconfigurationfile(commonlyknownasStruts-config.xml)whenthedevelopmentoftheapplicationinvolvesasizableteam.ThisproblemarisesbecauseaStruts-basedapplicationmustrununderonecontrollerservlet,theActionServlet,andtheActionServletcanuseonlyoneStruts-config.xml.Itisnotanissuewhentheprojectisrelativelysmallandtheteamconsistsofacoupleofdevelopers;however,whentheprojectsizebecomessignificantandtheprojectinvolvesalargenumberofdevelopers,maintainingallthemappinginformationinasinglefilebecomesincreasinglyproblematic.
Struts1.1solvesthisproblemnicelybyintroducingmultiplesub-applications.InStruts1.1,eachsub-applicationhasitsownStruts-config.xmlfile.AlargeStruts-basedapplicationcanthusbeeasilypartitionedintolargelyindependentmodules,i.e.sub-applications,andeachsub-teamcanmaintaintheirStruts-config.xmlindependently.
Thesub-applicationschemeisanaturalextensionoftheservletcontextmappingschemeoftheURIpathsusedbyservletcontainers.AccordingtotheServletstandard,whentheservletcontainerreceivesarequestwithaURL,theservletcontainerwilltrytomatchtheprefixoftheURIpathtoadeployedweb-applicationinthecontainer.WhatStruts1.1doesisitmapsthesecondprefixofthepathtoasub-application.Ineffect,thisprefixmappingschemecreatesanotherlevelofnamespaceforeachsub-application.Forexample,fortheURI,
http://some-host.com/myApp/module2/editSubscription.do
/myAppisthecontextpathforaweb-applicationcalled"myApp"and/module2isthesub-appprefixforaStrutssub-applicationcalled"module2".
DynaBeanandBeanUtils
AnothermajorcomplaintusuallyheardamongstStruts1.0usersistheextensiveeffortinvolvedinwritingtheFormBean(a.k.a.ActionForm)classes.
Strutsprovidestwo-wayautomaticpopulationbetweenHTMLformsandJavaobjects,theFormBeans.Totakeadvantageofthishowever,youhavetowriteoneFormBeanperHTMLform.(Insomeusecases,aFormBeancanactuallybesharedbetweenmultipleHTMLforms.Butthosearespecificcases.)Struts'FormBeanstandardfollowsfaithfullytheverboseJavaBeanstandardtodefineandaccessproperties.Besides,toencourageamaintainablearchitecture,Strutsenforcesapatternsuchthatitisverydifficultto'reuse'amodel-layerobject(e.g.aValueObjectfromtheEJBtier)asaFormBean.Combiningallthesefactors,adeveloperhastospendasignificantamountoftimetowritetediousgetters/settersforalltheFormBeanclasses.
Struts1.1offersanalternative,DynamicActionForms,whicharebasedonDynaBeans.Simplyput,DynaBeansaretype-safename-valuepairs(thinkHashMaps)butbehavelikenormalJavaBeanswiththehelpoftheBeanUtilslibrary.(BoththeDynaBeansandtheBeanUtilslibrarywerefoundtobeusefulandgenericenoughthattheyhavebeen'promoted'intoJakarta'sCommonsproject.)WithDynamicActionForms,insteadofcodingthetedioussetters/getters,developerscandeclaretherequiredpropertiesintheStruts-config.xmlfiles.StrutswillinstantiateandinitializeDynamicActionFormobjectswiththeappropriatemetadata.Fromthenonwards,TheDynamicActionForminstanceistreatedasifitisanordinaryJavaBeanbyStrutsandtheBeanUtilslibrary.
DeclarativeExceptionHandling
Ifyouhavedevelopedwebapplicationslongenough,youwillrealizearecurringpatternemerges:whenthebackend(e.g.theEJBtier)throwsyouanexception,younearlyalwaysneedtodisplayanerrorpagecorrespondingtothetypeofthatexception.Soonerorlater,youwillcomeupwithamechanismtousealookuptable(e.g.anHashMap)tolookupanerrorpagefromtheexceptionclass.
Struts1.1nowprovidesasimilarbutmorepowerfulmechanismtodeclareexceptionhandling.InStruts1.1,youcandeclareintheStruts-config.xmltheassociationsbetweenanexceptionclassandanexceptionhandler.UsingthedefaultexceptionhandlerincludedinStruts,youcanalsospecifythepathoftheerrorpages.Withthisinformation,StrutswillautomaticallyforwardtothespecifiedpageswhenanuncaughtexceptionisthrownfromanAction.
LikeotherfacilitiesinStruts,theexceptionhandlersarepluggable.Youcanwriteanddefineyourownhandlerclassesifneeded.
Validator
TheValidatorisnotexactlyanewfeature.TheValidatorhasbeeninthecontribpackageinthedistributionsinceStruts1.0.1.Sincethen,partofithasnowbeenrefactoredandmovedintotheJakarta-CommonssubprojectandrenamedtheCommons-ValidatorandtheStrutsspecificportionisnowcalledtheStruts-Validator.However,sinceitisinthecontribpackage,peoplemayoverlookitanditisworthwhiletomentionithere.
TheValidatorprovidesanextensibleframeworktodefinevalidationrulestovalidateuserinputsinforms.WhatisappealingintheValidatoristhatitgeneratesboththeserver-sidevalidationcodeandtheclient-sidevalidationcode(i.e.Javascript)fromthesamesetofvalidationrulesdefinedinanXMLconfigurationfile.TheValidatorperformsthevalidationbasedonregular-expressionpatternmatching.Whileahandfulofcommonlyusedvalidatorsareshippedwiththeframework(e.g.datevalidator,rangevalidator),youcanalwaysdefineyourownonestosuityourneed.
Impact
Havinggonethroughthelistofexcitingnewfeatures,itistimetoexaminethepotentiallynegativeimpactoftheseenchacements.OneofthehighestprioritiesoftheStruts'developercommunitywhendevelopingStruts1.1hasbeentoachievemaximumbackwardcompatibilitywith1.0.Struts'developershavedefinitelydoneagoodjobinthisregard;however,therearestillsomeissuesyouneedtobeawareof.
DefaultSub-application
Tomaintainbackwardcompatibility,Struts1.1allowsonedefaultsub-applicationperapplication.TheURIoftheresources(i.e.JSPs,HTMLs,etc)inthedefaultsub-applicationwillhaveanemptysub-appprefix.Thismeanswhenanexisting1.0applicationis"dropped"intoStruts1.1,theoretically,itwillautomaticallybecomethedefaultsub-application.
DirectRequeststoJSPs
Totakethefulladvantageofsub-applicationsupport,Struts1.1stipulatestherequirementthatallrequestsmustflowthroughthecontrollerservlet,i.e.theActionServlet.Effectively,thismeansallJSPsmustbefrontedbyActions.InsteadofallowingdirectrequeststoanyoftheJSPs,allrequestsmustgothroughanActionandlettheActionforwardtotheappropriateJSP.
ThisisperhapsthebiggestimpactofmigrationtoStruts1.1ifyouhavenotfollowedthisidiominyourapplications.ThisrestrictionisrequiredbecausewithoutgoingthroughtheActionServlet,Strutsnavigationtaglibs(e.g. and )usedintheJSPswillnothavethecorrectsub-appcontexttoworkwith.
ActionServletConfigurations
Withtheintroductionofsub-applications,amoreflexiblewayisintroducedtoconfigureeachsub-applicationindependently.Manyoftheconfigurationentries(e.g.resourcebundlelocation,maximumuploadfilesize,etc)thatusedtobedefinedinweb.xmlhavenowbeenmovedtoStruts-config.xml.Theoriginalentriesinweb.xmlaredeprecatedbutwillstillbeeffective.
Path-mappedActions
Bothextension-mapped(e.g.*.do)andpath-mapped(e.g./do/*)ActionsaresupportedinStruts1.0.However,atthetimeofwriting(August2002),mulitplesub-applicationswillnotworkwithpath-mappedActions.ItislikelythisissuewillberesolvedinthefinalreleaseofStruts1.1.
Action.execute()andAction.getResources()
InStruts1.0,requesthandlinglogiciscodedinAction.perform();however,Action.perform()throwsonlyIOExceptionandSevletException.Tofacilitatethenewdeclarativeexceptionhandling,therequesthandlingmethodneedstothrowException,thesuperclassofallthecheckedexceptions.Therefore,tobothmaintainbackwardcompatibilityandfacilitatedeclarativeexceptionhandling,Action.perform()isnowdeprecatedinfavourofAction.execute().
YoualsohavetobecarefulifyouuseDispatchActioninyourexistingapplications.Atthetimeofwriting,theDispatchActioninStruts1.1betahasnotyetbeenupdatedtouseexecute().(AbugreporthasbeenfiledinStruts'bugdatabase.)Therefore,withoutmodifyingtheDispatchActionclassyourself,declarativeexceptionhandlingwillnotworkwithDispatchActionsubclasses.
Inaddition,Action.getResources()isnowdeprecated.Instead,youshouldcallAction.getResources(HttpServletRequest)instead.ThisallowsStrutstoreturntoyouthesub-applicationspecificmessageresources.Otherwise,themessageresourcesforthedefaultsub-appwillbeused.
LibraryDependency
Struts1.1nowdependsonahandfuloflibrariesfromotherJakartasubprojects(e.g.Commons-Logging,Commons-Collections,etc.).Someoftheselibrariesmaycauseclassloadingconflictsinsomeservletcontainers.Sofar,peoplehavereportedinthemailinglisttheclassloadingproblemofcommons-digester/jaxp1.1,andcommons-loggingcausingdeploymentdifficultiesinStruts1.1applicationsrunningonWeblogic6.0.(TheproblemshavebeencorrectedinWeblogic6.1and7.0.)
ResourcesunderWEB-INF
AccordingtotheServletspecification,resources(e.g.JSPfiles)storedunderWEB-INFareprotectedandcannotbeaccesseddirectlybythebrowsers.OnedesignidiomforStruts1.0istoputalltheJSPfilesunderWEB-INFandfrontthembyActionssothatclientscannotillegallyaccesstheJSPs.
Withtheintroductionofsub-applicationprefixesinStruts1.1,mappingresourcesunderWEB-INFgetscomplicated.ExtraconfigurationstepsutilizingthepagePatternandforwardPatternattributesofthe elementin Struts-config.xmlisrequiredtoinform Strutstoconstructthepathscorrectly.Morespecifically,youneedtosettheseattributestothepattern"/WEB-INF/$A$P".
Miscellenousissuesforadvancedusers
ThefollowingissuesarerelevanttoyouifyouareapowerStrutsuserandmakeuseofsomeadvancedfeaturesinStruts:
*IfyourapplicationdependsontheActionFormBeans,ActionForwardsorActionMappingsservletcontextattributes,youhavetogettheinformationtheyneedfromtheApplicationConfigobjectinstead.
*IfyousubclassActionServlet,youmayhavetoretrofititbacktothatofStruts1.1orthenewRequestProcessorclassasActionServlethasbeenrefactored.
Conclusion
So,"ShouldIconsiderupgradingtoStruts1.1?"Herearemyrecommendations.
ForExistingSmallProjects
IfyouhavearelativelysmallprojectandarehappywithwhatStruts1.0currentlyoffers,itmakessensetostaywithStruts1.0.
ForExistingMedium-to-LargeProjects
Ifyouhavealargeproject,themultiplesub-applicationfeatureisdefinitelytheoverridingfactorininfluencingyourdecision.Thelitmustestistoaskyourselfthisquestion:"IstheexistingStruts-config.xmlfilegettingverydifficulttomanageduetoitssheerfilesize?"Iftheanswerisyes,youshouldconsiderdoingapilottrialtoreplaceStruts1.0withStruts1.1inyourdevelopmentenvironmentwithoutpartitioningyourapplicationintosub-applicationsfirst.
SinceStruts1.1cantreatyourexistingapplicationsimplyasthedefaultsub-application,thereplacementshouldbestraightforward.However,totestifyourapplicationisactuallyStruts1.1compliant,youshouldconfigureitasasub-applicationwithanon-emptyprefixandgothroughsomerepresentativeusecasestotestandseeiftheapplicationworksasitusedtobe.Beforeyouembarkontothepilottrial,youhavetomakesureallofyourdevelopersareawareoftheissueslistedintheprevioussection,particularlytherequirementthatallrequestsmustgothroughthecontrollerservletasitisquitelikelythatthatmaynotthecaseinyourapplication.Youneedtheirinputtodecideifthemigrationisfeasibleornot.
OncethepilottrialissuccessfulandyoudecidetomigratetoStruts1.1,youcanstarttoworkouthowtopartitiontheapplicationintosub-applicationswithadequategranularity.Beingabletopartitiontheapplicationintosub-applications,youmayalsowanttoconsiderreorganizingyourteamstructureandtheprojectstructureofyoursourcecodecontroltoalignwiththepartitioning.
ForNewProjects
Ifyourprojectisanewone,thedecisiontouseStruts1.1mainlydependsontheamountofriskyourprojectcantake.Struts1.0isaproventechnologybutStruts1.1isstillinbeta.Besides,migratingbackwardsisalwaysmoredifficultthanmigratingforwards.OnceyoustartwithStruts1.1,itwillinvolvealotofhardworktogobacktoStruts1.0.WhiletheextrariskinusingStruts1.1isgenerallyverylow(asthequalityofworkfromApache'sdevelopercommunityhasbeenconsistentlyverygood),itisstillanon-negligiblefactoryouhavetoc
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>