620 likes | 751 Views
Struts:The good, the bad, the ugly. A detailed evaluation of Struts 1.1 and Enterprise Web Applications. By Paul Smith Ancept, Inc. ( www.ancept.com ) psmith@ancept.com. Presentation Overview. Themes Struts Overview (Basic Features) Development Challenges in 1.0 Problem Description
E N D
Struts:The good, the bad, the ugly A detailed evaluation of Struts 1.1 and Enterprise Web Applications. By Paul Smith Ancept, Inc. (www.ancept.com) psmith@ancept.com
Presentation Overview • Themes • Struts Overview (Basic Features) • Development Challenges in 1.0 • Problem Description • Solution in 1.1 • Example • Architectural Challenges Struts Applications • Problem Description • Possible Solution • Q & A
Themes • Struts 1.1 provides small to medium sized applications all the functionality they should need “out of the box” • A large project team should be aware of limitations of Struts 1.1 which may require customized solutions • Large architecture teams may need a custom implementation of Struts 1.1 to enterprise class architectures
Supporting the Themes • To illustrate the themes: • Section 1 describes Struts basic features • Section 2 describes the new features of Struts 1.1 and why they exist • Section 3 describes architectural challenges in large projects and possible solutions
Section 1-Basic Features • Why Use A Framework • Struts Overview
Why Use the Struts Framework • A pre-built framework is better than roll-your-own • Increased productivity in JSP production • Cleaner design • More time on business logic
Easier than building your own • Probably very similar to what you would end up building anyway • Strong industry support instead of your own custom framework • The Struts framework is configurable so it will probably work for your project without building your own • Customizing open-source is simpler than building from scratch
JSP Productivity • Writing pages in Struts is roughly 40-60% faster than without struts because you use tags NOT java code • The custom tags, form object, messages architecture makes data display easy (for medium sized apps) • Tiles development helps manage page complexity
Cleaner Design • Struts applications are easier to develop and maintain because the design concepts are elegant • Non-technical staff better understands layout and design • Since code is targeted at specific business problems, the team communicates better • Design is easier to expand for very large application architectures
More Time on Business Logic • Less coding of web infrastructure means more time for business logic: • Page flow design • Action execution synchronization • Page model objects • Validation • Page templates • Focus on re-usable custom frameworks to use with Struts (J2EE integration, Web services)
Struts Overview • Struts Description • Common Infrastructure Tasks • Struts Solutions to Infrastructure Tasks • How does Struts works • The Struts Configuration File • Where does it fit in J2EE applications • Case Study
Struts Description • Struts is a Web Application Framework (custom tag libraries, servlet, xml control files) which increase the productivity of web developers • Struts was invented by Craig McClanahan in 2000 • Struts solves common problems with web application development by abstracting common infrastructure tasks
Common Infrastructure Tasks • Page flow design and control • Code execution framework (Command Pattern) • Automated data objects (MVC Pattern) • Easy to use custom tags for display • Validation • Page templates & layout • Re-usable text messages • Much more…
Struts Solutions to Infrastructure • Forwards: Page flow design and control • Actions: Code execution framework (Command Pattern) • Forms: Automated data objects (MVC Pattern) • Struts Tags: Easy to use custom tags for display • Validator: Validation • Tiles: Page templates & layout • Message Resources: Handles re-usable text messages in multiple languages
Struts Configuration • Struts is controlled by a Configuration file • Struts Configuration contains: • Form Definitions: Data objects for JSP pages • Forward Definitions: Abstract pages for page flow control • Action Definitions: maps requests to Command class • Message Resources: Storage of common text messages • Plug-In Definitions: Startup classes used for initializing custom functionality
Case Study • Department of Transportation created an aircraft registration application for internal staff (J2EE with a 2nd Generation Framework) • 100 JSPs • 13.5 k lines of code in the web tier (no business logic). • 20,000 lines of code for business logic. • 8 months of development with a team of 5
Section 1 Conclusion • Struts base feature-set include significant functionality for small to medium applications • Small applications should not need to customize Struts significantly: • Form objects and Action classes provide MVC design • Action classes house functional code • Forwards abstract page flow control • Form objects and Struts tags provide page display • Tiles provides flexible page layout • Validator provides flexible form/page level validation • Message Resources provide re-usable text
Development Challenges in 1.0 • Large Numbers of Form Classes • Large teams and Resources • Handling Errors More Flexibly • Problems with Page Layout • Validating Pages and Forms • Initializing Custom Functionality
Lots of Form Classes • In Struts 1.0 developers had to write a custom class for every form (generally 1 per JSP form) • Form classes are generally very simple • Task assigned to junior programmers (drudge work) • Form classes sometimes not consistent
1.1 Solution Dynamic Form Objects • Declare Forms in the struts-config.xml file • Form objects are created when the action executes and stored in the session or request scope • Form fields are set and retrieved using the PropertyUtils.setSimpleProperty(…) method or treated as HashMap
Dynamic Form Example Declaration <form> <form-property name=“” type=“” value=“”/> </form> Java Use Public void execute(mapping, form, …){ String testProp = (String)PropertyUtils.getSimpleProperty(form, “testProp”); PropertyUtils.setSimpleProperty(form, “testProp”, value); }
Large Teams and Resources • It has been difficult to co-ordinate the struts-config file and other resources with large teams and projects • Resources declared in config file might need to be different for portions of the application (shippingForm) • Partitioning development teams has been somewhat difficult
1.1 Solution: Modules • Separate, independent applications (uses different configuration file) under “default” application • Modules are based on paths (xyz.com/app/sub-app) and web.xml entries • Created to modularize large applications • Break modules up according to team • Unable to share resources between modules
Module Example Jakarta Struts 1.1: Ready for Prime Time (PDF) by Chuck Cavaness.
Handling Errors • Struts 1.0 applications had to do all of their error handling inside the Action classes • This could mean a significant amount duplication of error handling code • Some large apps had to customize the framework to do flexible error handling
1.1 Solution: Declarative Error Handling • Provides global and per Action handling of errors • Declare errors by Exception class • Create custom error handlers by implementing interface
Error Handling Example Declaration <global-exceptions> <exception handler="CustomHandler" key="error.message" path="/error.jsp" scope="request" type="java.lang.Exception"/> </global-exceptions> Java Use public ActionForward execute( Exception ex, ExceptionConfig exConfig, ActionMapping mapping, ActionForm formInstance, HttpServletRequest request, HttpServletResponse response ) throws ServletException { handle error… return mapping.findForward(“errorPage”); }
Problems with Page Layout • Struts 1.0 provided some page layout mechanism • Large application pages can get very complicated without a better layout mechanism • 1.0 version could not change based on Locale • 1.0 version did not have significant re-use functionality
1.1 Solution:Tiles Integration • Tiles code has been integrated into core Struts • Tiles provides flexible page layout and re-use mechanism • Provides support for Locales • Tiles can be nested • Tiles can be used as Struts Forwards by tile name
Tiles Example Tiles-Config.xml <definitions> <definition name=“home.default” path=“/index.jsp”/> <put name=“header” value=“header.jsp”/> </definition> <definition name=“home.default” extends=“home.default”/> <put name=“header” value=“other.jsp”/> </definition> </definitions> Index.jsp <%@ taglib URI=“WEB-INF/tiles.tld” name=“tiles%> <html:html> <body> <tiles:insert attribute=“header”/> <tiles:insert attribute=“body”/> <tiles:insert attribute=“footer”/> …
Validating Pages and Forms • Struts 1.0 only provided automatic support for validating form objects (by calling the validate method) • Programmers had to implement validation code inside of the class (ex. making sure phone was really a number) by hand • Client-side validation had to be implemented by hand
1.1 Solution: Validator Integration • Validator integrated into core code base • Use a xml file to declaratively validate form objects • Validators are keyed against the form by name • Comes with many pre-built validators (e-mail, date, etc) • Supports client-side (JavaScript) and server-side validation
Validator Config Example Struts-Config.xml <form name=“shippingForm”> <form-property name=“address” type=“java.lang.String” /> </form> Validator.xml <form name=“shippingForm”> <field property=“address” depends=“required, mask”/> <arg0 key=“label.address”/> <var> <var-name>mask</var-name> <var-value>^\w+$</var-value> </var> </field> …
Validator JSP Example Index.jsp <%@ taglib URI=“WEB-INF/tiles.tld” name=“tiles%> <html:html> <body> <html:form action=“logonSubmit” onsubmit=“validateLogonForm(this)”> (this makes the form call the validation JavaScript onSubmit) <table> …etc. </table> <validator:javascript formName=“logonForm”/> (This inserts the javascript which executes the validation) …
Initializing Custom Functionality • Often custom applications need to initialize information when the application starts up • Since Struts runs off of a servlet this was very difficult
1.1 Solution: Plug-Ins • Plug-Ins provide a means for initializing components on application startup • Provide means for Factory functionality or customization • Init-parameters let you pass information into plug-in
Plug-in Example Struts-Config.xml <plug-in classname=“TestPlugin”> <set-property property=“datasource” value=“testData”/> <set-property property=“user” value=“user”/> </plug-in> TestPlugin Code public void init(ActionServlet servlet, ApplicationConfig config) { perform initialization… } Public void destroy() { perform shutdown… }
Section 2 Conclusion • Struts 1.1 has added significant functionality to help medium to large application teams • Even large application teams should be able to use Struts without actually modifying the underlying Struts code: • Plug-ins allow initialization of advanced “patterns” • Declarative error handling allows re-use of error code • Dynamic forms save tremendous effort • Validation saves significant effort • Modules provide large team partitioning
Architectural Challenges • “Contextual” Pages & Declarative Branching • Composable Actions • Re-Use • Event Handling • J2EE Integration • Content Management Integration
Contextual Pages • Sometimes the developer wants to use JSPs in different locations in the page flow • These pages and their associated action classes must then have large if/then blocks • Certain types of context tracking are almost impossible without extending the framework (dynamically modifying actions, etc)
Solutions: Context Subsystem • Create Context object which tracks the “path” the user has traveled • Create ContextualAction super-class which adds the page and action to the context • Make all Action classes subclass ContextualAction and use path history for logic
Composable Actions • Actions are currently made up of only one class file • To partition an Action the developer must use large if/then blocks and Request properties • The developer must put all of this code in one action or write custom JavaScript to call different actions based on the users mouse-click • This is not made easy for the developer and can cause problems if not thought through early on
Solution:Composable Actions • Some amount of “composition” can be achieved using local ActionForwards • Better composition can be achieved with the Struts Action Plug-in Extension 1.0.2 by ASQdotCOM • Struts 2.0 should have a “workflow” component to compose actions from re-usable steps
Solution:Composable Actions • Step 1:Write a Java class that implements the ActionPlugIn interface, to create an action plug-in. • Step 2:Declare (and configure) the action plug-in that you created in step 1 in the action-plug-in-config.xml configuration file. • Step 3:Add a Struts <plug-in> tag to the struts-config.xml configuration file to get the action plug-in chain initialized on application start-up. • Step 4:Make sure that there is a <controller> tag specified in the struts-config.xml configuration file, that has its processClass attribute set to be.ff.web.struts.action.ActionPlugInRequestProcessor.
Solution:Composable Actions Declaration <action-plug-in-config> <action-plug-in> <class>ActionPlugIn</class> <init-params> <init-params> <disabled-for> /logon </disabled-for> </action-plug-in> <action-plug-in> <class>WorkflowActionPlugIn</class> </action-plug-in> Java Use public ActionForward execute() throws ActionPlugInException {UserAccount account = (UserAccount) session.getAttribute(accountSessionKey); if (account == null) { return mapping.findForward("logon"); } else { return chain.execute(mapping, form, request, response); }