Light Year Studio

Download Report

Transcript Light Year Studio

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)
[email protected]
Presentation Overview



Themes
Struts Overview (Basic Features)
Development Challenges in 1.0
–
–
–

Architectural Challenges Struts Applications
–
–

Problem Description
Solution in 1.1
Example
Problem Description
Possible Solution
Q&A
Themes
1.
2.
3.
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 rollyour-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
How Struts Works
Web Container
JSP
Browser - HTML
HTML Form
4 Response
Struts Tags
HTML Text Box
HTML List Box
HTML Submit
Button
3
Forward
2
Execute
Action Classes
Struts Controller Servlet
Browser - HTML
HTML Form
HTML Submit
Button
1 Request
1
Struts Config XML file
-Forms
-Forwards
-Actions
-Messages
-Plug-ins
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
Where does Struts fit into J2EE
Web Container
Java Application Server
Session
Beans
Browser
HTTP
JSP
Controller
Servlet
Custom
Tags
Message
Beans
Entity Beans
CMP
RMI(IIOP)
BMP
Scripting
Struts
Config
Files
Persistence
Manager
Web Srvc
JCA
JMS
DB
Case Study

Web Pages
100 pages
(display)
Still a significant
amount of effort
Custom Control Logic
13,500 code lines
(data, validation,
business logic calls)




Application
Business
Logic
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
Java Use
<form>
<form-property name=“”
type=“” value=“”/>
</form>
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/subapp) 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="CustomHandl
er"
key="error.message"
path="/error.jsp"
scope="request"
type="java.lang.Excepti
on"/>
</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 reuse 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 (email, date, etc)
 Supports client-side (JavaScript) and
server-side validation

Validator Config Example
Struts-Config.xml
Validator.xml
<form name=“shippingForm”>
<form-property
name=“address”
type=“java.lang.String” />
</form>
<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
TestPlugin Code
<plug-in
classname=“TestPlugin”>
<set-property
property=“datasource”
value=“testData”/>
<set-property property=“user”
value=“user”/>
</plug-in>
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)

Contextual Pages
Search
Results
View
Result
Action=View
Start
Action=Save Action=Edit
Login
Index
Action=Search
Action=Save
Another Page
Edit Result
Action=Edit
Declarative Branching
Start
Cart
Action=Checkout
Basic Information
Payment
Information
Action=Next
Action=Finish
If this is a company user go
to the PO Wizard
Action=Finish
PO
Info 1
Action=Next
PO
Info 2
Confirmation
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
Composable Actions
Cart Page
Action=Finish
Finish Action
Action
Step 1
Action=Checkout
Forward
Checkout Action
Action
Step 1
Final Page
Action
Step 2
Forward
Checkout
Page
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 reusable 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 strutsconfig.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</cl
ass>
<init-params>
<init-params>
<disabled-for> /logon
</disabled-for>
</action-plug-in>
<action-plug-in>
<class>WorkflowActionP
lugIn</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);
}
Re-Use
There are two possibilities for re-use in Struts,
pages and actions
 Re-use of actions is very difficult because:

– the granularity of the actions is too high (one action
per page)
– The actions cannot be chained together or segmented

Re-use of pages in struts is very difficult
because:
– There is no context object tracking location, etc.
– There is no way of overriding a page/form declaration
within a context
Action Re-use
Finish Action
Cart Page
Action
Step 1
Checkout Action
Action
Step 1
Action Re-use
Action
Step 2
J2EE Integration
Struts does not provide any out of the box
functionality for J2EE integration (EJBs,
JDO, JDBC, JMS, JavaMail)
 Each project/development team must
decide ahead of time on a mechanism to
do J2EE integration
 Developers must build their own
frameworks for J2EE integration even in
very simple applications

Solution: J2EE Integration
Create Declarative support for long-lived
model objects (beyond forms)
 Create Struts J2EE integration (session
and entity beans) using dynamic value
objects and session bean proxies
 Create Struts JDO integration

Solution: J2EE Integration
Java Application Server
Session
Beans
Web Container
Struts
Controller
Logic
Struts
Custom
Tags
Entity Beans
J2EE
Model
Objects
JDO/JDBC
Model
Objects
Message
Beans
CMP
Web Srvc
Persistence
Manager
BMP
DB Pools
JCA
JMS
DB
Events
Struts provides no mechanism for event
based functionality
 Though not strictly required, it is often
much easier to write some function using
an event
 For example, if you want to run some
function every time the user goes to the
edit page, but the edit page can be
reached by 10 different actions…

Solution: Event Subsystem
Create an Event Multicaster/Controller to
manage event listeners and publish
specific events
 Most useful events are Navigation, Action,
Form events
 Create Action Superclass which fires
navigation and action events
 Create Dynamic form superclass which
fires form events

Solution: Event Subsystem
Cart Page
Fire Action
Event
Checkout Action
Fire Navigate
Event
Action
Step 1
Action
Step 2
Page
Content Integration
Struts provides very little in terms of
content management integration.
 If your team uses custom content
management systems, you will have to
customize the own framework
 The message framework in Struts is only
acceptable for small to medium
applications

Solution: Content Integration
Customize Message Resources classes to
handle more advanced input
 Customize Validator framework to handle
more advanced input
 Possible input mechanisms:

– Xml files
– Content Management Systems
– DBMS
Section 3 Conclusion
While Struts 1.1 provides excellent features for
web applications it may be deficient for
Enterprise class architectures
 Large Application Teams may need to create a
custom Struts implementation to accomplish:

–
–
–
–
–
–
Contextual Page Handling
Dynamic Action Branching and page flow
Composable Actions for Re-Use
Significant J2EE integration
Event Handling
Content Management Integration
Resources




Struts website: http://jakarta.apache.org/struts
Struts Action Plug-in Extension 1.0.2:
http://www.asqdotcom.be/struts/
Struts workflow proposal:
http://jakarta.apache.org/struts/proposals/workflow.html
Struts Resources:
http://jakarta.apache.org/struts/resources/index.html