The purpose of this document is to provide a
detailed analysis of both Barracuda and Struts. We focus on summarizing each architecture,
and then performing a comparison / contrast on key issues.
- Development Landscape
- Framework Summaries
- Barracuda
- Client Capabilities
- Event Model
- Form Mapping & Validation
- XMLC
- Localization
- Component Model
- Struts
- Controller
- Model
- View
- Utilities
- Future Directions
- Comparison / Contrast
- UI Issues
- Separating Presentation from Programming Logic
- Page Design
- Taglibs
- UI Layout
- Localization
- Support for multiple Client Types
- Support for multiple Client Skins
- Client Capabilities
- Client Accessibility
- Flow Control Issues
- Event Handling
- MVC / Model 2
- Workflow
- Server Side Issues
- Form Mapping & Validation
- Error Handling
- Component Models
- Component Reuse
- Scalability
- Throughput
- Volume
- Tools Integration
- Page Tools
- IDEs
Development Landscape - When it
comes to developing webapps, it seems difficult to overstate the level of diversity found
in various approaches. Upon closer inspection, however, we can identify certain elements
of polarization within the current development landscape.
Developer Types - there seem to be two distinct
classes of developers creating web applications today:
Page Authors - tend to view the webapp space primarily
from a page based perspective. These folks are by far the most numerous, tend to gravitate
towards technologies like JSP, ASP, PHP, Cold Fusion, and various other template based
approaches. Often are familiar with scripting languages like JavaScript and VBScript.
Java Developers - tend to view the webapp space more
from an application centric perspective. These folks are more likely to be comfortable
with coding in a strongly typed OO language like Java, C++ or SmallTalk, and are often
building webapps using Servlet technologies.
Development Tools - along similar lines, we can
see two distinct genres of development tools that correspond closely to developer types
given above:
Page Based Tools - these often correspond with visual
page editors like DreamWeaver, UltraDev, and FrontPage.
Traditional IDEs - these would be more along the lines
of applications like JBuilder, NetBeans/Forte, VisualAge, and perhaps VisualCafe.
While these are obvious generalizations (and there is undoubtedly
overlap!), it is valuable to delineate this segmentation, as many web frameworks will
gravitate towards one or the other ends of the spectrum.
Interestingly, none of the development tools that exist today really make
it easy to develop webapps (at least not to the extent that a tool like VB made
it possible for Corporate Developers to easily build applications without a lot of
specialized programming knowledge). Ultimately, we feel these tools are lacking primarily
because a suitable presentation framework infrastructure -- capable of supporting the
challenges of the HTTP Req-Resp paradigm, with its necessary separation of presentation
and business logic -- has not yet emerged. Such a framework will be critical if we ever
hope to see tools that unify the designer roles and developer roles and allow the rapid
assembly of web application and web services from reusable components.
Framework Summaries - We want to
start by taking a high level look at how each of the various frameworks approaches the
problem domain: making it easier to build web apps. We begin by looking at Barracuda
(since we know that best after all ;-) and then look at some other leading efforts.
Barracuda
- The Barracuda Presentation framework is built as a series of layers that depend on the
Servlet 2.2+ API, each of which can be used independently of one another. In terms of
audience, Barracuda definitely aims at the Java Developer end of the spectrum (with the
idea that tools integration will ultimately make the approach more accessible to Page
Author types).
At the highest level, the Barracuda architecture can be summarized by the
following diagram:

The key features of Barracuda are summarized here:
- Client Capabilities - Automatically identifies client capabilities
(browser type, target locale, etc).
- Event Model - Maps client requests to first class event objects;
dispatches events to all interested listeners; guarantees that an HTTP Response is
generated.
- Form Mapping & Validation - Converts HTTP Form parameters into
first class Java objects and provides a powerful validation mechanism to verify them.
- XMLC - Compiles HTML, WML, and XML documents into DOM template objects
that can be manipulated programmatically.
- Localization - Automatically creates localized versions of the DOM
templates for additional locales. These templates can be loaded based on a target client
locale.
- Component Model - Uses familiar UI Widgets with strongly typed
Swing-style MVC interfaces to dynamically populate the DOM templates with data. the DOM
can then be rendered and returned to the client browser.
A detailed explanation of these areas follows:
Client Capabilities -
Barracuda begins by identifying the client's capabilities. In particular, it can
determine:
- client type -- what kind of client are we dealing with (NN, IE, etc) as
well as the specific version of the client
- client scripting capabilities -- what kind of scripting is supported
(Javascript, VBScript, WMLScript, or None) along with the specific version information
- target output format -- what kind of output the client expects (HTML,
WML, XML, etc) as well as the specific version of markup supported
- target client locale -- the client locale information
This information is available throughout the entire request-response cycle, making it
easy to perform custom processing based on a client specifics.
Event Model - The Barracuda
event model is all about routing -- it's responsible for turning HTTP Requests into first
class event objects, dispatching the events to interested parties, and then making sure
that an HTTP Response was generated. There are a number of specific features:
- makes it easy to implement Model 2 style flow control by utilizing a
2-phase dispatch loop in which all Request (Control) Events are processed
first, followed by all Response (View) Events.
- allows for true event driven programming on the server since events are first
class Java objects (not just strings or method names) and any event can have multiple
listeners
- event handlers can be implemented using inner classes, just like in
Swing
- integrates with the component model, meaning you can add listeners to
components and your server-side event handler code will automatically get invoked when an
action occurs on the client
- events are hierarchical in nature, making it very easy to make an
application secure (by controlling what events can be fired without
needing to modify the actual event handler code) and robust (by ensuring
that a response will always be generated, even if the developer forgets to handle a view
event)
- the model is fundamentally scalable -- event handler instances are lightweight
and short-lived (lasting only for the duration of a req-resp cycle)
and event dispatching is fast (no reflection / introspection)
As a final note, the Barracuda Event model is based on interfaces, making it fully
pluggable (you could easily substitute your own event dispatching mechanism if
need be). In addition, while the model is tuned for the HTTP Req-Resp paradigm, it
could also be integrated with other non-response based protocols (ie. SMTP, JMS,
a 3rd party scheduling system, etc).
Form Mapping & Validation
- Once the Event Model has routed control to the proper location, it is often necessary to
examine a client's input parameters before actually generating a response. This is where
Barracuda's Form Mapping & Validation layer comes into play:
- easily map HTTP Form parameters into first class Java objects based on
key name and data type (String, Boolean, Integer, Date, Long, Short, Double, Float)
- provide default values if an expected parameter is not present
- provide a number of prebuilt validators (NotNull, ValidType, Equals,
MaxLength, MinLength, Range, Digit) to handle common validation tasks in a reusable
fashion
- support the the notion of custom validators to express specific
business logic validation requirements
- allow for validator aggregation, by which any number of simple
validators can be used as building blocks for more complex validation behavior
- support for nestable validation exceptions, making it possible to
catch either the first exception or all exceptions on a collection of data
These features make it easy to get data back from the client in a form that is more
easily handled on the server.
XMLC - Once we have converted data
that came from the client into something more useful than raw String data, we usually need
to respond in some fashion (ie. the Do-Something-on-the-Server phase). If
we are following the Model 2 pattern, this might involve updating some kind of
"Model" via JDBC, RMI, EJB, etc.
Barracuda offers no help yet imposes no restrictions on what you do in
this stage. Instead, it waits for the Render-a-Response phase that
inevitably follows. This is the point in which we finally generate a page (or
"View") in response to the client's HTTP Request. Barracuda has a lot to offer
in this area, and it all starts with a tool called XMLC.
XMLC is a tool that generates DOM based template objects from HTML
and XML documents. Unlike traditional template
approaches (JSP, WebMacro, Velocity, etc.) which require you to embed programming logic in
the UI markup (aka "Pull-MVC"), XMLC allows the developer to
manipulate a template programmatically (aka "Push-MVC"). There
are a number of distinct advantages:
- provides excellent code-content separation -- the presentation markup
is physically decoupled from all programming logic used to manipulate a page (each is
stored in separate files)
- this paradigm mirrors the dual roles (Designer vs. Developer) prevalent
in real-world webapp development and benefits both parties in the dev process
- for the designer...
- guarantees the template documents will always be valid, well-formed markup
- this makes it much easier for a designer to create and maintain the documents using standard
interactive design tools
- furthermore, a collection of template source documents can continue to function as a working
mockup of the application
- in addition, the designer can make changes to the presentation layout
without involving the developer
- for the developer...
- the developer can make changes to the business logic layers without
involving the designer or impacting the presentation layout
- the developer can create more portable code by coding against well
defined industry standard DOM interfaces (ie. w3c.org)
- this approach supports multiple document types (HTML, WML, XML,
etc...anything that can be read as a DOM)
- compile time parsing of HTML/XML document offers a significant
performance benefit for complex pages.
- XMLC's Lazy-DOM support further improves performance by only creating DOM
nodes for those portions of the template which are actually modified dynamically
- clean separation of roles promotes full parallel development -- the
designer can focus on design and the developer can focus on programming logic. Neither has
to worry about interfering with the other
- enforces good development practices -- developers cannot create KLOCs
of unmaintainable presentation code like they can with JSP; corporate developers like this
enforcement (Merck and GE are examples of corporate IT shops that have selected XMLC for
the natural policy of markup/Java separation)
- offers advanced compilation features
- supports runtime auto compilation if markup changes in original doc are detected.
- supports runtime classloading if new DOM class template is detected.
- factory methods make it possible to implement one DOM class template interface with
multiple, dynamically selected implementations.
These features combine to make for a very powerful templating mechanism that is not
subject to many of the limitations found in more traditional templating approaches.
Localization - Barracuda
leverages the strengths of XMLC to provide a unique and innovative solution for
Localization. Typically, when one wishes to localize a template driven application, one
either creates localized versions of all the templates (efficiency at the expense of
maintainability), or one dynamically localizes both text and data in a page for every
given request (more maintainable, but at the expense of efficiency).
Barracuda looks for a better solution, one that provides the best of both
worlds -- we need something that is efficient (ie. we'd only like to localize static text
once for each template) and yet at the same time maintainable (ie. we don't want to have
to manage separate localized versions of each template). The solution is elegant.
- Barracuda uses the Ant build system, allowing us to provide a custom XMLC
taskdef that not only compiles the *ML template (ie. Foo.html) to an XMLC object
(FooHTML.class), but also looks for the presence of a master properties files associated
with that template (ie. Foo.properties)
- the master properties file can be used to identify the portions of the
template that map to "static-but-localizable" text
- the taskdef then looks for matching localized properties files that
follow the locale naming convention (ie. Foo_es.properties). If found, additional
templates (ie. Foo_es.html) will be created from the master template, with the localized
text substituted in. These too will then be compiled to XMLC objects (ie.
FooHTML_es.class)
- Barracuda provides a custom DOM loader which can load an XMLC DOM
template based on a target locale (ie. the programmer specifies "FooHTML.class"
for a target locale of "es" and receives a reference to
"FooHTML_es.class"
- the DOM loader works on the same principle as Java's ResourceBundle
class, so if a particular template is not available (ie. language "es", country
"CL"), the next closest match will be used.
This approach makes it very easy for the programmer to select a localized
DOM template for use in the rendering process without having to jump through any special
hoops.
Component Model - Once
the developer has loaded the appropriate "View" template, the next step is to
dynamically populate the DOM structure with data. Unfortunately the DOM interfaces are
rather low-level and tedious to program against (especially for complex structures like
Lists and Tables). This is where the Barracuda Component Model comes into play.
The basic idea behind the component model is that you can create a
hierarchy of components which are each bound to various portions of the DOM hierarchy. Now
rather than manipulating the DOM directly, we can put the data in the components and then
render them. The components are intelligent enough to to render the data properly into the
DOM structure. There are a number of specific features:
at the most basic level, Barracuda components can be viewed as UI
Widgets that are similar in many ways to what you find in Swing:
Barracuda components are also different from Swing components in many
ways:
- they are modeled on the data rather than the UI functionality associated
with that data (ie. instead of having multiple components like JLabel and JTextArea, there is
one BText component which can render text into many different types of DOM nodes. Similarly,
there is one BList component that can render list data into many different markup structures)
- in addition to having well defined Model interfaces, all Barracuda components must also be
bound to at least one View on the DOM.
- Barracuda components are more concerned with data than layout, since
layout information is typically encapsulated in the DOM template
- as such, they are extremely lightweight (because they don't have much
information to keep track of)
- they use pluggable renderers to render markup appropriate to the DOM
template type (ie. HTML, WML, XML, etc.)
- this allows for highly intelligent rendering; we can take into account
the type of node to which a component is bound and render the data accordingly
Barracuda components also have to address component
aggregation/reuse differently, since the code-content separation means we need more
than just class files to create a reusable component -- we need an accompanying DOM
template, plus static resources that might be associated with it (.gif files, etc).
While most of the Barracuda components extend the "Push-MVC"
model necessitated by an XMLC based approach, the BTemplate component enables
"Pull-MVC" as well.
- the BTemplate component parses the template looking for "directives" (stored
either in the template or in a separate properties file)
- these directives are then mapped to data in a manner similar to that of taglibs (except of
course that the model can return more than just String data!)
- this approach provides better designer-developer decoupling, while still leaving the
developer tremendous freedom in terms of how to provide the requested data
- this effectively "componentizes" the template engine approach so its just
another tool in the developers bag of tricks -- freely available when necessary, yet
conveniently avoidable when not. In other words, this doesn't lock you into using a template
engine for an entire page/app the way most template approaches do...you can use it where it
makes sense.
The result of all this is a component framework that is inspired by Swing
yet fully accounts for the intricacies of code-content separation and the HTTP Req-Resp
paradigm. In addition, it supports a full spectrum of server side development
methodologies, ranging from "Push-MVC" to "Pull-MVC".
Struts
- Unlike Barracuda, Struts is aimed primarily at the Page Author types. This is not to say
that Struts does not require Java coding--after all, you still need developer types to
implement Tag libraries and write Controller code. Rather, it aims to suggest that it is
Page Authors who will get the most mileage from the framework; if you do not adopt a JSP
strategy for rendering views, the value of Struts is greatly diminished.
Given this focus, Struts tries to streamline existing page based
approaches to webapp development. It values simplicity, and can make a lot of design
decisions for you automatically. At the highest level, the Struts architecture looks
something like this:

Struts consists of the following architectural pieces:
Controller - Struts
provides a Controller servlet to give the developer a default Model 2 flow control
implementation. This servlet acts as a kind of "central nervous system" to
ensure that requests gets routed, handled, and rendered according to this pattern. The
specific processing flow runs something like this:
- uses an XML configuration file to map URIs Action classes (the default name is
struts-config.xml, but its not hardwired)
- when a request is received route it to the appropriate Action...
- identify from the URI the appropriate mapping for this request
- use this mapping to select the corresponding action class
- if this is the first request for the action class, instantiate an instance of that class
and cache it or future use
- optionally populate the properties of an ActionForm bean associated with this mapping.
- call the perform() method of the action object, passing on a reference to the mapping that
was used, and the request and response objects. The action also has access to the underlying
ActionServlet and ServletContext.
- Actions may take data from the request, may update the Model (beans), handle any errors,
and then return a "forwarding address" to the Controller. This "forwarding
address" may be a page, another Action, or even a URL.
- The Controller returns the Response to the container, which may invoke a JSP, fetch an
HTML page, or whatever else is required.
- The JSP may display data from Model (beans, session context, etc), access the Struts
mappings to render a URL, and/or access message resources to display internationalized
text.
Model - A common task in
most applications is getting data from the HTTP Request into the Model layer (which acts
as a facade to underlying business objects). Struts provides ActionForm and Action classes
to streamline this process.
An Action class acts as an "adapter" between the web layer
(HttpServletRequest) and the business logic (JavaBeans, EJBs, whatever). An ActionForm is
really just a server-side representation of the current contents of an input form.
Typically a developer writes Java code that extends these classes to provide the
implementation details specific to a particular action.
This layer also provides a mechanism for developers to validate the data
and redirect flow if an error occurs.
View - Of course,
applications also need to generate responses to client requests. In Struts, this occurs in
the View portion of the framework. Views are typically rendered with JSPs, which use Java
Taglibs to pull data out of the Model and insert it into the JSP page. Once the page has
been populated with data, it is ready to be returned to the client.
As one might guess, Struts has invested a lot of effort in the Taglibs end
of the framework. Specifically, Struts offers:
- Bean taglib - tags useful for defining new beans (from a variety of
sources) and rendering them in the page.
- HTML taglib - tags useful for creating various HTML elements
dynamically, including input forms
- Logic taglib - tags that allow a developer to put conditional logic in
the JSP page (Comparators, Conditionals, Iteration, etc)
- Template taglib - tags that are useful in creating dynamic JSPs
templates for pages that share a common format
Custom tag support - JSPs in general allow a developer
to create their own custom tags as well -- you can integrate third party tag libraries,
write your own app-specific ones, or subclass and specialize the existing Struts tags
It is also possible to use a different technology for the view layer,
without giving up on the controller and model layer features of Struts. That could be as
simple as using Faces components instead of the Struts tags, or as radical as using
Velocity, WebMacro, or Cocoon instead. The automatic support for ActionForms and
validation can continue to be used, because Struts cares about HttpServletRequest
parameters, not the technology used to submit them
Utilities - Struts offers
several utilities aimed at specific aspects of the development process:
Future directions - Struts
also has some interesting ideas for future development:
Comparison / Contrast - Now that
we've addressed the basics, it may prove helpful to look at how the frameworks compare on
specific issues.
UI Issues -
Separating
Presentation from Programming Logic - It is important to evaluate how well
the various approaches succeed in separating presentation from programming logic (which is
a generally accepted "Good Thing"). By separation we typically mean that code
that gets run on the server should be cleanly separated from code that will get processed
on the client -- Java shouldn't contain HTML, and HTML shouldn't contain Java. So how do
the various approaches fare?
Struts - Struts (and similar
"Pull-MVC" template approaches) achieve separation by expressing
"Controller" code in Java (usually Servlets), and "View" code as *ML
(usually in JSPs). Java Beans are used for the "Model" layer, and taglibs
act as the bridge -- controller code processes the request, updates model beans, and then
forwards processing flow to a JSP which uses Taglibs to pull data back out of the
underlying bean layer and embed it into the View.
On the surface, it sounds pretty good. Upon closer inspection, however, we
can see several flaws with this approach.
JSPs allow Java code (Scriptlets) to be embedded in the markup (thereby
breaking the separation). There is no mechanism to force developers not to do
this, and current practice shows they frequently do so. While some might argue that this
is not a flaw (after all, it gives the developers greater choice), most knowledgable
Struts developers will advise strongly against using Scriptlets. The thrust of this
critique is that the basic architecture of JSPs precludes any means of enforcing this
recommendation.
Even if page authors do not use Scriptlets, they must reference taglibs
in order to get data into the page (and JSPs offers no mechanism to avoid this
implication). What this means is that we end up embedding server-side programming logic
into the markup. (It should be noted that most template approaches try and temper this
fact by calling it "presentation logic", subsequently insisting that its ok to
mix that in with the markup. Nevertheless, this logic is still being processed on the
server, and as such it ultimately breaks clean separation.)
While this effect might be tolerable if all it allowed was the simple
inclusion of data (ie. similar to server-side includes) taglibs inevitably allow for a far
more complex logical constructions, including looping, conditional evaluations, etc. This
effectively introduces a server side scripting language into the equation -- developers
usually end up needing to know markup, JavaScript (for client side scripting), Java, plus
the taglibs (server-side scripting) syntax. This ultimately pollutes clean separation, and
makes the development process more complex, not less.
It should also be noted the using taglibs ultimately result in a JSP
that is not valid markup, which therefore makes it difficult to be edited using standard
off-the-shelf markup editing tools. While there are some tools that offer limited support
for JSP with custom tags (Ultradev), a vast majority of developers end up editing JSPs by
hand.
It should also be observed that it is typically developer types -- not
designers -- who end up adding "presentation logic" to JSPs. This ultimately
fails to scale because you end up with designers and developers trying to work from the
same physical file (always a good indication that we have failed to achieve proper
separation).
Ultimately, most of these criticisms stem from architectural
implications of JSPs (rather than Struts per se). Nevertheless they are still applicable
since the vast majority of Struts applications use JSPs as their rendering mechanism.
Interestingly, almost all "Pull-MVC" implementations are also subject to these
same criticisms, and fail to maintain true separation of code from content.
Barracuda - In contrast to most other templating
mechanisms, Barracuda builds on XMLC to implement what is sometimes called a
"Push-MVC" model. In this approach, HTML and XML source files are compiled by
XMLC into Java classes that implement the DOM interfaces. Java Controller code then
(usually in Servlets) can be used to manipulate the Views (presentation markup) without
actually mixing code and content. There are a number of advantages to this approach:
The separation of Presentation and Programming logic is both clean and enforceable
(there is no way for a developer to actually embed server side logic into the markup)
Because the presentation markup remains logic-free -- the extent of any
embedding is ultimately limited to flagging markup elements with id or class attributes --
the markup remains 100% valid HTML, XML, etc, and can be manipulated by the designer in a
wide variety of standard page editing tools.
Because the markup is contained in a physically separate file from any
programming logic, both designer and developer can work simultaneously without interfering
with one another -- the set of ids specified in the markup is the only contract that binds
the two. This results in very loose coupling which makes for excellent parallel
development.
In addition, the designer can use/maintain a working mockup of the
application entirely within the markup files. This further streamlines the development
process.
For this reason, we can assert that XMLC delivers better code-content
separation. There are some limitations to this approach however. Any time we are
expressing all logic (including that pertaining to presentation issues) in server-side
Java, the code must necessarily have some knowledge of the presentation structure. For
instance, the code needed to render a JDBC result set will vary depending on whether the
markup structure that will contain the data is a list or a table structure.
Consequently, it is easy for dependencies to be introduced that require
developer changes when the design layout changes. While this is a reasonable result of
keeping the presentation layer intentionally pure, it does actually complicate the
development process in certain cases (although we would argue not so much as the
"pure" Pull-MVC model described previously).
To improve this situation, Barracuda offers a custom BTemplate component
which actually acts like a mini-template engine to apply a "minimalistic"
Pull-MVC approach to a section of markup. Using this approach, the template component
parses a section of markup looking for any "directives" it might contain. These
directives are very simple, allowing us to specify simple logic within the markup --
basically we can get data from the server model and perform a simple iteration loop.
The advantage of this approach is that it allows simple page layout logic
to be expressed in markup, which greatly decouples the designer from the developer -- the
designer can dramatically modify the structure of the page layout without requiring the
developer to make any changes to the server side code. In this sense, the BTemplate
approach is architecturally similar to taglibs.
While this might seem hypocritical given our previous diatribe on putting
logic in the template, we believe there are some key differences worth noting:
This "Pull-MVC" implementation is so minimalistic it barely
qualifies as scripting -- there are no conditional expressions, etc. -- you can set data,
perform simple iterations, and discard nodes. That's it!
Instead, its really much closer to the way stylesheets work -- the
markup uses ids to refer to "processing instructions" that are contained in a
separate file. This allows the markup to remain 100% valid at all times.
We can safely avoid "feature creep" in our scripting
constructs because the BTemplate is implemented as a Barracuda component. If a developer
wants more powerful scripting features that are beyond the scope of this component they
should use a different component. Similarly, if embedding even this limited amount logic
in a presentation template makes a developer uncomfortable, they can simply choose not
to use it.
Ultimately then, the Barracuda approach to "Pull-MVC" is that we
recognize a number of cases where it is really useful (80%), but because we have
implemented it as a component, we don't really need to worry about all the weird cases
where it would become utterly complicated (20%). We can do this precisely because of the
underlying component model -- BTemplate is just another component. The result is an
approach which gives developers the best of both worlds without locking them into any one
way of doing things.
Barracuda makes it possible to maintain absolute separation of code from
content, while at the same time making it easy to fudge on that rule if the developer
wishes to allow it for the sake of handling a very common set of situations (simple data
substitutions, looping). At the same time we avoid the slippery slope that most templating
approaches fall into -- they ultimately need a full fledged scripting language for
manipulating the markup since they start with the assumption that all markup will be
manipulated within the context of the template. Ah the beauty of components :-)
Page Design - By
page design, we really mean that a development approach should support the ability for
Page Authors to modify the layout of pages within standard HTML page editing tools like
Ultradev, Dreamweaver, etc. These tools support content designers in their primary task --
defining the look and feel of a web application.
Struts - As mentioned in the previous section,
approaches like Struts tend to view JSPs as a great construct for dealing with markup.
Unfortunately, by embedding custom tags we create something that is not valid HTML, XML,
etc. Not surprisingly, tools support for JSPs with custom Taglibs is lagging. There have
been some simple "tag aware" plugins created for Ultradev, and the newest
version of the JSP spec makes it possible for JSPs to be defined as actual XML. For
the most part, however, the JSP approach (and most other template engines, for that
matter) does not adequately solve Page Design requirements. In practice, most JSPs today
are still edited by hand.
Barracuda - As per the discussion of XMLC above,
the Barracuda approach allows for easy integration with any page design tools that produce
valid markup (HTML, WML, XML, etc). In addition, the designer can easily modify the pages
without developer intervention, and maintain a working mockup of the application that is
completely detached from the developer's code and can be viewed through a standard
browser. We feel Barracuda / XMLC does extremely well in this particular area.
Taglibs - The need
for taglibs is actually somewhat questionable, unless of course we assume that JSP
integration must be part of a presentation framework, in which case they become much more
important. The purpose of this section is to address how each technology supports the
concept.
Struts - As we have already seen, embedding
Taglibs inside JSPs is an integral part to the Struts approach. Struts currently supports
4 distinct tag libraries: there is one for Bean interactions, another for HTML elements, a
third for Logical constructs, and one for Template support. Not surprisingly, Struts
developers are also increasingly looking to the Jakarta Taglibs Project, which
defines over 20 additional tag libraries. Consequently, it is safe to assume that Taglibs
support in Struts will continue to be excellent.
Barracuda - Barracuda currently has no Taglibs
offerings, although as was noted previously, the BTemplate approach is conceptually
similar to the taglibs approach. While it does seem possible for Barracuda to support
Taglibs in a manner similar to that proposed by JSR-127 (autogenerating), it is not clear
why we would actually want to do that (except perhaps to spur Barracuda adoption by those
already committed to JSP technology).
UI Layout - In
stated, client-server type applications (ie Swing, VB, etc), components are generally
responsible for managing both data and presentation (how the component renders on the
screen). Within the webapp paradigm, the separation of presentation from logic generally
means that the server side code only needs to worry about the data -- layout issues are
left up to the markup. There is general agreement in most camps that this is another
"Good Thing".
While there are some approaches like WingS, ECS, and Swinglets that try
and drive layout from the server code as well (in other words, the server code takes care
of everything, including generating all the markup), the general consensus among
webapp developers is that these approaches are "Not Such a Good Thing".
Struts / Barracuda - we know for sure that
Struts and Barracuda are NOT taking this latter approach -- layout remains in the
presentation layer where it belongs.
Localization -
When localizing a web application, there are really two different types of text that needs
to be localized: dynamic and static. Dynamic text -- often business data
from a database or EJB -- will typically need to be localized on a per-request basis. In
other words, if a user requests a particular screen repeatedly, the data portions of that
screen must usually be repopulated every time the page is requested to make sure the
resulting screen contains up-to-date information when it is returned to the client. Static
text, on the other hand, usually corresponds more closely to presentation data -- stuff
like labels, textfields, etc. As such this information generally doesn't change every time
the client requests a page. Its static, and thus it tends to stay the same within the
context of a given locale.
The standard Java libraries already provide a number of localization
features to deal with localizing dynamic data. Its more interesting, however, to see how
the various approaches handle static text that needs to be localized. There are typically
two basic approaches:
maintain multiple localized versions of each individual template
(efficient, because only the dynamic portions of the template need to be localized every
time the template is used, but difficult to maintain since we have multiple copies of the
presentation layout that must be kept in sync with one another) -OR-
dynamically set all localized text (both static and dynamic) every time
the template is requested (easier to maintain, since we only have one copy of the template
to manage, but not nearly as efficient, since we are dynamically setting text that is
really quite static, at least within the context of a given client locale)
It may be helpful to look at how the various presentation frameworks
approach this issue.
Struts - It appears to me that Struts offers
very little in terms of Localization support beyond what is already available in the
standard Java class libraries. It appears that most Struts developers adopt approach
#2 above, whereby all the text in a JSP is replaced every time the page is generated. This
naturally raises questions about performance in high load situations.
Barracuda - While not precluding either of the
options described above, Barracuda uses an approach described
previously to offer a solution that actually provides the best of both worlds --
performance and maintainability. This mechanism ensures that localized versions of the
master template are automatically produced from standard property files: the localization
of static text occurs at compile time, and yet the designer still only has to maintain one
master template no matter how many locales need to be supported. The proper templates are
selected on the server using a DOM loader utility that works off of a target locale in a
manner similar to that of ResourceBundles. This has turned out to be a very popular
feature within the Barracuda framework.
Support for multiple Client
Types - When we talk about supporting multiple client types, what we
really mean is that we should be able to create applications for various types of client
devices (web browsers, cell phones, PDAs, etc).
Struts - By using JSPs to create the views,
Struts can support multiple types of client markup ranging from HTML to XML.
Barracuda - By coding against the DOM
interfaces, Barracuda can also support multiple client types. We currently support HTML,
WML, and XML, and it is relatively straightforward to add support for other standard DOMs
as well. If it can be accessed via a DOM interface, Barracuda can work with it.
Support for multiple Client
Skins - The concept of skins is the idea that an application's look &
feel should be able to be drastically altered without affecting the basic functionality of
the application. In other words, even though various input controls like buttons, text,
and lists might change in appearance or location, the app will generally continue to
function in exactly the same way.
We can see this type of "Skinnable Interface" to some extent in
Swing's L&F toolkit, but even better in an application like RealJukebox. Ideally, we
would like to be able easily create the same type of effect in webapps. While it might
seem that the separation between code and content should make this relatively
straightforward, support is lacking in most frameworks.
Struts - To the best of my knowledge, Struts
does not actually offer anything in this area. JSPs in general tend to complicate this
goal, since they allow for programming logic to be embedded in the markup. If a designer
wishes to create an alternate skin, much of the presentation logic contained in the master
JSP would need to be duplicated. In practice, this quickly leads to maintainability
problems.
Barracuda - At this point in time, Barracuda
does not yet offer anything specific to creating skinnable webapps yet either. It is,
however, on the roadmap. The fact that Barracuda enforces such strict separation between
code and content actually makes the problem much easier to solve. At this point, we are
leaning toward a solution which would be similar in many ways to the way Barracuda handles
localization (ie. supporting multiple skins and automatically localizing those skins based
on a master properties file). More on this later as soon as details become available...
Client Capabilities
- When we speak of concept, we are recognizing the fact that in many cases server side
code may need to take into account the clients' capabilities when generating UI code. For
instance, what version of browser is the client using? What version of a particular markup
language do they support? Do they support scripting? and so forth. Some of this
information can be determined from the underlying Servlet request, but extracting it is
often a manual process. It would be nice if the frameworks offered something specific in
this regard.
Struts - To the best of my knowledge, Struts
does not offer any specific features that address this area.
Barracuda - As described in the Client Capabilities section, Barracuda automatically
identifies basic client capabilities such as client type (NN, IE, etc), markup
type/version (HTML 3.2, HTML 4.0, XML 1.0, etc), scripting type/version (Javascript 1.0?
1.1? etc), as well as target client locale. This information is automatically made
available to all Barracuda code. In addition, Barracuda components may take advantage of
this information when rendering, to take advantage of client functionality, rather than
simply rendering based on a lowest common denominator approach. In the future, we
anticipate the validation framework will also take advantage of this information to allow
for custom client side validations if the client is capable of supporting it.
Client Accessibility
- By client accessibility we mean the ability to automatically support clients with
disabilities in ways defined by WAI. This type of functionality is currently built into
Swing, but there is not a well defined model for how it would integrate into web browsers
and other devices that might interfaces with web apps.
Struts - This functionality is outside the scope
of Struts.
Barracuda - This functionality is also outside
the scope of Barracuda, although if we had to take a stab at implementing it, it seems
that Skins would be the way to go, rather than trying to autogenerate something (which is
the approach the Faces initiative seems to be headed).
Flow Control Issues -
Event Handling
- The real question to be addressed here is: How do these frameworks handle events? Of
course in order to answer this question we must first examine how each framework defines
the term "event".
Struts - Taking our cue from the J2EE
Blueprints, we could simply view an "event" as being synonymous with a user
"gesture" (any action on the client that results in a subsequent HTTP Request to
the server). For most frameworks this definition is sufficient, and Struts is no exception
-- the master controller is responsible for mapping URL requests to "Actions",
which are more or less synonymous with "event handlers". For Struts, then, events
are a simple mechanism to map one or more URLs to a single block of code on the server and
nothing more.
Now that we understand what events are in Struts, we also need to consider
how Struts delivers them. Some frameworks treat events as Strings that map to individual
methods within an object on the server (ie. a servlet, java bean, or some other object).
The problem with this approach is that it inevitably suffers from performance or
maintainability -- methods within the object must either be invoked through reflection
(not particularly fast) or with a manually written case statement (not particularly
maintainable). Fortunately, Struts takes a different tack -- events are mapped to Action
classes, the classes are instantiated and cached, and the Actions' perform() method is
invoked every time an "event" needs to be dispatched. This approach should scale
well under load.
There are some technical details worth noting:
For every request, there is a 1:1 mapping between user gestures and
actions. While you could have mutiple gestures handled by the same action on the server,
you will never have a gesture handled by multiple actions. This makes the Action handlers
more or less monolithic in nature.
(Note that while you could have an Action forward control to another
action, thereby technically having multiple Actions handle an event, in reality the
monolithic critique still applies -- at the end of the chain, the gesture is still being
handled by just one Action. For an explanation of why this is important, click here)
When writing Struts Actions, you must consider threadsafety issues, just
like you would when writing a servlet -- there is one instance of each Action class, with
(potentially) multiple threads using it. Consequently, Actions need to be written in a
threadsafe fashion (ie. avoid the use of class variables, etc).
Once instantiated, Actions stay in memory for the lifespan of the
Application. While this means that a very large app could conceivably end up with every
possible Action in memory at once, this will probably not have an adverse impact on
footprint since these objects are typically very lightweight.
ActionForms, on the other hand, are usually instantiated / scoped on a
per-request basis; an Action class will only ever receive one ActionForm instance (for the
form submitted for the current request)
I don't think any of these issues will adversely impact performance
(although the use of reflection in populating the ActionForms might). The most significant
implication, in my mind, is the fundamentally monolithic nature of the Request-Action
relationship.
Barracuda - While the Barracuda event model
certainly encompasses the basic functionality of events as defined in Struts (notifying
the server that something happened on the client), it does much more as well, offering a
number of unique features that distinguish it from other event frameworks.
To begin with, Barracuda models events as first class Java objects.
This allows us to avoid the performance / maintainability issues associated with treating
events as a String that corresponds to a method (described above in the Struts section).
In addition, it makes for strong typing and allows us to catch errors sooner (at compile
time) rather than later (runtime). Furthermore, such an approach presents the developer
coming from a rich client background with a familiar paradigm (it feels more like client
server).
One of the challenges in converting URLs to event objects is performance:
how do we instantiate events in such a way that minimizes overhead and maximizes
throughput. In Barracuda, we solve this problem by using an event pooling mechanism --
events are instantiated via reflection the first time they are needed and then stored in
an event pool for subsequent reuse. This makes event dispatching very fast. (It should
also be noted that this is one of the few places we use reflection within the Barracuda
framework).
Of course, one of the drawbacks of creating events which are first class
Java objects is that they must be defined in physical class files. While it is relatively
easy to pre-define generic events (ie. ActionEvent), web developers often need to
specify custom events which correspond to the business API that the web
application exposes (ie. GetLogin, AttemptLogin, GetUsers, etc). Indeed, this is an area
where a webapp event model will inevitably differ from its rich client counterparts. For
many developers, defining a set of events in actual Java files is a tedious process they'd
like to avoid -- they would much rather specify them from some configuration file.
Unfortunately, it is currently difficult to define events from within an
XML descriptor (since they need to be backed by a physical Java class). In addition,
defining events from a configuration file would tend to eliminate the strong typing
benefits we mentioned earlier. Fortunately, we will soon have a solution that addresses
both of these issues. By creating a custom Ant taskdef that operates in a fashion similar
to XMLC, we can autogenerate the event classes, thereby allowing them to be specified
dynamically, while still retaining the benefits of the strong typing (since the classes
would still physically exist at compile time). Support for this approach should be ready
in the near future...
One of the advantage of Barracuda's event model is that event
listeners can be handled using standard inner class adapters, just like in Swing.
Again, this presents obvious familiarity benefits to the developer. Want to handle an
event? Write an event adapter! The process is well understood and the advantages are
obvious.
Interestingly, implementing the necessary infrastructure to support inner
class event handlers presents some very interesting challenges in a servlet environment!
The basic problem is that unlike Swing -- in which event handlers typically exist in the
context of an application (which itself exists on a per-user basis) and are scoped for the
lifetime of the app -- in a Servlet context we typically have multiple user requests that
are all getting handled by a single instance of a servlet. Rather than funneling all user
requests through a single instance of an event handler (which would require
synchronization and kill throughput), we needed a way to create an instance of an event
handler for every individual request. When the request is done the event handler can go
away. This keeps the system very fast because it can serve multiple requests
simultaneously (without synchronization), and it also minimizes footprint, since the
memory associated with a handler could be reclaimed as soon as the handler has finished
processing the request.
The problem here (and if you are familiar with inner classes you've
probably seen it coming) is that the inner classes may only be instantiated by the class
that physically contains them. This makes it very difficult for the servlet container to
grab new instances of event handlers! Fortunately, there is a solution -- any
class that uses event handlers must provide a factory to instantiate those event handlers.
These factories are registered with Barracuda's Event Broker (the actual dispatching
mechanism), which can use them to instantiate as many event handlers as are needed. This
meets our performance requirements nicely, while minimizing the memory footprint of system
since the only part of a Barracuda application which is continually in memory is the
collection of event handler factories! This arrangement proves to be very advantageous
from a scalability and performance perspective.
One of the drawbacks of an event model like that found in Struts (and
other frameworks which similarly map a URL to exactly 1 event on the server) is that the
resulting code to handle that event tends to become somewhat monolithic. While some might
argue this is actually a "good thing", since it makes code less complex by
putting all the logic for a page in one location, others would contend that its "not
such good thing", instead citing the advantages of high cohesion where we strive for
more granular objects, each of which "does one thing and does it well".
This is such an important point that it might be a good place for an
example. Consider the following diagram which describes how data might flow through a
fictional Human Resources Application:

[Click here for a larger version of this
diagram]
Building on this example, let's see what happens when a client wishes to
"Add an Employee". Before we can actually return the proper data, we need to
actually go through a number of steps that may (or may not) have any correlation to the
actual request being handled. For instance, in the case given here, we might need to
perform a number of distinct tasks:
- first make sure that the client is logged into the system (Login Role)
- next check to see if they are actually authorized to view the data (Authorization Role)
- get a connection to the database (DB Mgr Role)
- execute the query (Query Role)
- log the fact that this request occurred (Logging Role)
- render the data and return it to the user (Render Role)
In a traditional CGI type approach, all of the above steps would have all
been handled by one single block of code. In a Model 2 approach like Struts (where 1 event
maps to 1 event handler) , the rendering step would usually be handled separately (by the
View portion of the framework), but the rest of the steps would probably still be handled
by one Action class in a monolithic fashion (the Controller portion of the framework).
Contrast this with a highly cohesive approach -- we might expect to see different objects
for each step, where the objects are more granular and are focused on handling one
specific role within the app. This type of approach makes it easier for developers to
program business logic that slices across large portions of an application.
Unfortunately, it is very difficult to achieve any level of granularity
when a given event has only one event handler. The Barracuda event model, however,
addresses this problem. In Barracuda, events can have any number of listeners.
This allows us to leverage the benefits of event driven code -- business logic to handle
events does not have to be monolithic; we can distribute the tasks among separate objects
which handle specific roles without needing to know about the details (or even the
existence!) of one another. This makes for very loose coupling, which makes it easier to
write better code and allows us to pick the level of granularity that makes the best sense
for our particular domain. It is difficult to overstate the importance of this feature.
Of course there are some challenging implications of this approach. In
typical client-server event models many events are generated that are often completely
ignored. Within the webapp space, however, events that originate from an HTTP Request must
always be handled (after all, HTTP requires that some response be sent back to the
client!). In addition, if we are allowing multiple listeners we also have to make
sure that only one event handler actually generates a response!
To solve this problem in Barracuda we distinguish between two
types of events (Control events & View events) and notify listeners using a 2
phase event dispatch loop. While the internals are somewhat complicated, the long and the
short of it is that this approach effectively allows you to have any number of event
handlers while guaranteeing that exactly one response will get sent to the client for
every HTTP request. Pretty cool. (You can learn more about the specifics of event
dispatching in Event Topology and
the 30,000 Foot Overview,
which explains how this approach actually implements the Model 2 pattern).
It is worth noting that the Barracuda event model is extremely
secure. What we mean by this is that it is impossible for an HTTP request to
access the View layer of an application directly, since the Application Gateway will only
dispatch Control events. This forces all client access to go through the developer defined
Control layer. This is a marked contrast with Struts and many of the other JSP approaches
where a malicious client can directly access the View portion of an application simply by
issuing a URL request for the JSP that generates the view. While this situation does not
necessarily constitute a security breach, it generally results in a scenario that the
developer has not anticipated -- model information that was set in the control layer may
be missing, and as such the page will probably not be processed correctly. This could
expose sensitive server side information to a client. While a developer could anticipate
this type of attack and take programmatic measures to ensure the JSPs handle this
scenario, most developers who follow the Model 2 / JSP approach today are not aware of
this security risk.
Another advantage of the Barracuda model is that event dispatching
is hierarchical in nature. This allows for unique dispatching policies based on
Polymorphic and Exceptional behavior. The basic idea behind event polymorphism is that
events can implement a marker interface (Polymorphic) to indicate to the event dispatcher
that they are polymorphic in nature, that is, they can also be viewed as instances of
their parent event.
For example, let's examine a simple event hierarchy which might be used
for the example given above. This event hierarchy effectively defines our "public
API" of events that can be handled through HTTP. It might look something like:
- ControlEvent
- HREvent
- PublicEvent
- AuthorizedEvent
- AddEmployee
- PromoteEmployee
- DemoteEmployee
- FireEmployee
- ViewEvent
Let's say we receive an HTTP Request for an AddEmployee event. Because all
control events are Polymorphic, before we ever actually dispatch the AddEmployee event, we
will first dispatch instances of its parent events, since it is in fact an instance of
those events too. This means that an HREvent would be fired first. A listener could
be installed on this event to ensure that the client is actually a member of the HR group.
If not, it could redirect the event flow altogether simply by firing a NotInHR event..
Likewise, a listener on AuthorizedEvent could implement a security check to make sure that
whoever is trying to execute this group of events is actually authorized to do so (ie.
while everyone in the HR group may be allowed to list employees, not everyone will be able
to fire them). While this example is obviously contrived, it illustrates the basic point: event
polymorphism allows us to install behavior on large blocks of a system (ie.
Security) without having to touch the code that does the actual low level work (Adding,
Promoting, Demoting, and Firing). This promotes the granularity and cohesion discussed
earlier. In addition, as we add new events to the hierarchy they automatically inherit the
business logic that applies to their parents. Consequently, if we add a new
"TransferEmployee" event, it would automatically inherit the security policies
created for HREvent and AuthorizedEvent.
By default, all View events implement the Exceptional interface -- this
essentially causes the opposite effect of event polymorphism: when an Exceptional event is
not handled (ie. a request for a specific view is ignored), this interface tells the event
dispatcher to fire the parent event, just like what happens with Exceptions. For instance,
if there are no handlers for the NotAuthorized event, then an HRErrorEvent will be fired.
If that event is not handled, then a more generic ErrorEvent will be fired. Thus, Exceptional
events are propagated up the event hierarchy until someone handles them. This
ensures that we always generate a view for a client request, even if the programmer forgot
to actually implement that code. This makes for much more robust -- and maintainable --
systems.
(If you are interested in learning more about Polymorphic and Exceptional
behaviors, you may wish to refer to the Simple
Login App documentation.)
As a final note, we should point out that the Barracuda event model can
also be integrated with other non Req-Response protocols, like SMTP and JMS. This makes it
more flexible than most other approaches.
MVC / Model 2 -
Unfortunately, these terms are terribly abused in development today, to the point that
they have really lost a lot of their meaning. The result is that many people use identical
terminology and yet mean distinctly different things when they talk about MVC and Model 2.
Consequently, we want to begin by trying to be really clear what we
mean by these terms. In a nutshell...
we view Model 2 as a pattern that is MVC-ish; that is,
something processes an HTTP request ("Controller") and updates some kind of
server state somewhere ("Model"), and then forwards control to something else
which takes data out of the model and creates an HTTP Response to send back to the client
("View"). This approach, when viewed from a high level, follows a
Model-View-Controller pattern. The problem is, the pattern is so generically defined that
just about anything can conform to it (thus it suffers from vagueness).
we view MVC as something much closer to Swing; that is,
an approach that provides well defined Model and View interfaces for individual
components, similar to what we find when dealing with Swing widgets (of course we
recognize that it won't look exactly like Swing either -- there will have to be
adaptations to handle the HTTP req-resp model as well as the conscious separation of code
from content).
Struts - Struts (and most other Model 2
approaches) are MVCish, and as such flow control is really limited to how data
goes from the client to the server and then back to the client. The level of granularity
beneath this is undefined. While this works well for page based apps, it is unclear to me
how it would integrate with traditional IDEs, many of which are built around a well
defined notion of components (in the widget sense of the word).
Barracuda - As mentioned previously, we feel
that Barracuda's event model implementation (with its 2-phase dispatch loop) effectively
provides Barracuda with Model 2 flow control. Barracuda also addresses the more
traditional notion of MVC, however, by defining a distinct component model that has well
defined model and view interfaces to make it easy for users to get data in/out of
components, and for components to render themselves in views (more on this below). In
short, Barracuda provides both Model 2 and MVC flow control features.
Workflow - When
we speak about workflow, what we are really talking about is the ability to define how an
application flows at a meta level. In other words, we'd like some kind of capability to
express stuff like "When an application is in a particular state these particular
aspects of the application should be accessible".
For instance, when the user is not logged in, they should be able to get
the login screen and attempt to login (but nothing else!). Once they have logged in, they
should be able to do other things like list users, etc (but they should not be able
to return to the login screen unless the logout first!). Hopefully, you get the idea.
What we'd like to know is how these frameworks address these issues. (It
should be noted that there's not a lot of consensus on how to go about this yet -- Ian
Horrocks has written a book that proposes a Nested Statecharts approach; others tout
Hierarchical MVC (HMVC); I've even heard of some who are trying to define application
flows in UML and then generate the necessary code from that. Bottom line is that no one
seems to have found a really good abstraction yet that everyone else is willing to adopt)
Struts - Struts does not currently offer
anything at this level, but Craig McClanahan tells me they are working on it now. While I
have not had time to analyze the specifics behind there approach, you can learn more about
it here: http://jakarta.apache.org/struts/proposal-workflow.html.
I think it is a positive sign they they are attempting to break this into
2 distinct layers: one whis is a generic workflow engine that could be reused by any
framework, and another which is the Struts specific implementation. This seems like a good
approach to take...
Barracuda - Barracuda does not offer anything in
this area either, yet. It seems, however, that the event model might offer us some
interesting opportunities for exploration in this regard. By controlling which events can
be fired at a given time we could effectively manage the state of the application. The
real question then becomes, how do we express the state-to-event mappings that determine
whether or not an event is "allowed" for the the current state. If we could find
a way to express this via XML we'd be on to something. Not much research has been done in
this area yet.
Server Side Issues -
Form Mapping &
Validation - The issue here is how do we get data out of an HTTP Request,
into some kind of more accessible data structure, and then validate that data once we have
it.
Struts - Struts seems to do a good job in this
area. When the developer implements Actions he can also specify an ActionForm. An
ActionForm is just a standard java bean, which means that it should have setter/getter
methods. The set methods should always take String values (since the data will becoming
from an HTTP Request), but the get methods could really return objects of any class. This
seems to make it possible to convert data to first class Java objects, although in
practice I'm am not sure to what extent Struts developers do this.
If an ActionForm is available, the Struts controller will automatically
map the values from the HTTP Request into bean; this occurs before the Action class is
invoked, so at the point where the developer is handling an Action the mapping has already
occurred automatically.
Struts handles validation by allowing the developer to override a validate
method in Action class. Here the developer can do whatever he wants to determine whether
or not the data is valid. Once validation is complete flow is redirected accordingly to
the appropriate view renderer.
There does seem to be a performance implication worth noting here -- the
reliance on reflection to set data in the Java Beans seems to me to potential source of
impedance that might adversely affect throughput. At this point, however, I have no idea
how significant the impact of this might be.
Barracuda - Barracuda takes a similar approach,
although rather than using a Java Bean, form values can be automatically mapped into a
data collections structure as first class Java objects (Floats, Integers, Dates, etc).
This is useful since an application's back end business components are often coded to take
first class Java objects as parameters, not merely String values.
Values can be mapped simply by specifiying key name and data type; the
rest occurs automatically. Thus, it seems quite possible to script the form mapping layer
(although we don't have any examples of this yet).
In terms of validation, Barracuda seems to offer some interesting
innovations. Basically, a Validator can be attached to any collection of form values (ie.
to validate an entire form) or to individual form elements. In addition, any validator may
contain any number of child validators. This approach makes it possible to assemble
complex validation logic from much simple building block validators, enhancing reusability
while maintaining high cohesion.
Error Handling -
One of the questions that inevitably occurs when validating data on the server is
"How do we handle errors?" Frequently, when errors occur, we want to redisplay
the form the user was editing, and in doing so it is very important that we repopulate the
screen with the data that the user already entered (so they don't have to retype it all
over again). In addition, there may have been one or more errors on the page. Sometimes,
we only want to show the first error, but in many cases we want to show all error fields
(so the user can correct all problems at once and then resubmit).
Struts - At this point, I don't know a whole lot
about how Struts validation works. I do know however, that it addresses the basic
requirements listed above.
Barracuda - Barracuda's validation mechanism
allows us to catch either the first error or all errors associated with a form. Typically,
once we have these errors we simply store them in the event context and forward control by
firing a render event. When the screen renders, it sees the presence of the data and the
error messages, so in addition to building the basic page, it can also repopulate the data
and display the error messages as needed. Functionally, this allows us to accomplish the
same thing as Struts (although the implementation details vary slightly).
Component Models
- Just like "Event" or "MVC", the term "Component" varies
dramatically in meaning depending on who you talk to. In general, we can identify several
distinct uses of the word:
- From a very generic sense, it can often be used to describe any reusable piece of code.
- In a more specific, concrete sense, it is sometimes used to define a UI Widget (ie.
Swing), which usually knows how to store some data and then render it as required.
- In addition, there is often a sense in which components can be viewed from a meta-level,
that is as a collection of smaller components which, when aggregated together can be
viewed as a larger "Meta" component
Struts - Struts really takes view #1 when
speaking of Components -- we see references to building Model components, View components,
Controller components, etc. Because the term is used so loosely, it is difficult to find a
distinct concept of a "Component Model" within Struts.
Barracuda - Barracuda tends to view components
based on #2 (while not precluding #3). Thus when we talk about Barracuda's "Component
Model" we are really talking about its UI Widget architecture which in many ways is
closely based on Java Swing. For more details on this layer, refer to the Component Model section (above), or the 30,000 Foot Overview.
Component Reuse
- When we talk of component reuse, what we are really speaking of is the idea alluded to
in component definition #3 above -- the idea that individual components may be aggregated
together into a larger component (which can itself be viewed as a single unified
component). Such a notion is essential to the concept of component reuse (that is,
creating complex "mega" components that may be reused in a variety of contexts
through simple configuration).
An example of such aggregation might be something like a Login Screen, or
a Master-Detail view; the specifics would probably change dramatically depending on the
specific application, but the functionality should remain more or less the same.
Interestingly, code-content separation (which is highly desirable for the
web app paradigm) actually makes it much more difficult to achieve component reusability.
The reason for this lies in the fact that for any given component we now have information
residing in multiple different locations -- the data is generally associated with the
component (or the component's Models), but the layout is usually contained in a separate
markup file (ie the View). To further complicate matters, the markup often references
additional static resources like images. This makes it very difficult to assemble a
component into a shrink-wrapped package that can be easily deployed (ie. a jar file).
At this point, most "reuse" that is occurring in the web app
paradigm takes the form of cut / paste / tweak, which is a far cry from what we would like
to be able to achieve.
Struts - I'm not aware of anything in Struts
that is really addressing component reuse in this sense.
Barracuda - Barracuda does not currently address
this issue either, although its definitely something we are working on. Barracuda
component support the notion of composition, so it's certainly possible to assemble
hierarchies easily. The problem is that each of these hierarchies must be bound to some
portion of a DOM, and its unclear how to handle situations where individual components
might be bound to different DOM templates. One possibility is that tools integration could
ease some of the deployment issues. This is something that needs more research.
Scalability - When
we speak of scalability, we really mean two things. A framework that is scalable
should generally attempt to maximize throughput (how fast requests are
handled) and volume (how many simultaneous requests can be
handled). Now obviously, as volume increases throughput generally suffers. Nevertheless,
if we think of scalability as the area covered by volume and throughput we can see the
relationship clearly:
scalability = volume * throughput
Put simply if we can keep volume high and throughput fast, we will achieve
better scalability. If either volume or throughput suffers unduly at the expense of the
other, scalability will suffer.
Throughput
- How fast requests are handled. Typically, the way we maximize throughput is to try and
do things as quickly as possible, and to try avoid doing things which take a long time to
complete. Of course, speed is always relative, but there are certain things that are known
to take a long time in Java.
Network access (ie. database query) is generally the
slowest link in the equation (and none of the frameworks involved are going to do much
about that)
Disk access is also not very speedy. In the case of
both Struts and Barracuda, disk access is generally limited to the reading of
configuration files; since this occurs only at startup (or the first time they are needed)
this should generally not be an issue for any of these frameworks.
Reflection & Introspection are not particularly
fast (at least, they have been performance bottlenecks in the past). For Barracuda, use of
these features is limited to startup (when parsing an XML assembly descriptor) and event
instantiation (the first time and event is needed; pooled/cached thereafter). Struts
however seems to rely heavily on reflection to put data into beans and then to retrieve
it. This seems cause for concern to me (although I should be quick to qualify that I
haven't done any quantitative analysis on this yet)
Garbage Collection has been expensive in the past. This
could be a possible bottleneck for an approach like Barracuda, where lots of small objects
are created and then cleaned up as needed (keeping the footprint low). Realistically,
however, I don't think this is going to be an issue, especially given the recent advances
in GC technology (ie. in HotSpot JVM). Once again, I have no quantitative analysis on this
yet, although we have verified that the Barracuda event dispatching mechanism seems very
fast.
Synchronization is always a source of slowdown. While I
cannot speak for Struts, I know the Barracuda model requires almost no use of
synchronization (given its extensive use of event factories). This keeps things blazing.
Volume - How
many simultaneous requests can be handled. The big things to be avoided here are
synchronization blocks and single threaded issues. The bottom line is that an app must be
able to function in a multithreaded environment...frameworks that require Servlets to use
SingleThreadModel will inevitably not scale. I don't know of any volume limitations in
Barracuda, and have not heard of any in Struts (again, no quantifiable comparison info
here)
The bottom line in all this is that while both frameworks appear basically
scalable, we have concerns about Strut's extensive use of reflection. Unfortunately, we
don't have any kind of quantifiable analysis to show how they compare with one another
yet.
Tools Integration - One
of the interesting questions in all this is how these frameworks will support tools
integration. Keep in mind from our initial discussion that there are 2 distinct types of
tool: Page Tools and IDEs.
Page Tools -
Page Tools are primarily aimed at the page author. This is a person who tends to approach
webapps from a page based perspective, and who is generally comfortable with the notion of
embedding stuff in the page so that he/she doesn't have to write any Java code.
At this point, it appears that the primary integration mechanism for page
tools will be to interface with Taglibs (or something similar). The basic idea would be
that a Page Tool might be able to discover various tag libraries and allow the page author
to bind data to elements in the page.
Struts - Struts seems well suited for this task.
The problem however is that even in Struts there must be additional coding -- typically an
app has various flow control rules, access control issues, etc. In addition, someone has
to write the taglibs and bind them to data in the underlying model. The bottom line is
that not everything can be expressed in XML configuration files yet, so someone is still
needed to write code. Which makes the typical page author dependant on a backend
developer.
Barracuda - Barracuda does not currently offer a
Taglibs interface, so at this point I do not see a real clear way to integrate with the
basic Page Tools (at least not the current generation, many of which lack any knowledge of
Java or Appservers). We might be able to create a Plugin that would auto-generate
XMLC/Barracuda style servlets and data model classes from UltraDev. More research is
necessary in this area.
IDEs - IDEs are much
closer to the typical Java developer, and have been the traditional tools integration
point for RAD development approaches. The problem here is that while existing IDEs are set
up to easily assemble and manipulate hierarchies of components, they generally assume that
the components are capable of rendering themselves. In other words, they are not set up to
handle components which are based on the premise of decoupling content / layout from data
/ logic.
Struts - I am not really clear on how Struts
could be integrated into a traditional IDE.
Barracuda - I think Barracuda actually offers
some interesting opportunities for IDE integration. Because it has a well defined
event/component model, I think it would be very straightforward to define hierarchies of
components and add event handlers to them in much the same way that occurs today within
Swing apps. The difficulty, however, is figuring out out to bind those components to
elements in the DOM template. This actually may not be that difficult, since DOM
interfaces are ultimately just hierarchical representations of node. Nevertheless, IDEs
would need some tweaking to make this seamless (ie. to show the DOM nodes and to let you
bind components to them).
In addition, it should be noted that markup support is still pretty poor
in most contemporary IDEs (so it might not be feasible to show the developer a gui
representation of the DOM). Furthermore, both IDEs and Page Tools frequently lack XML
support. It seems that there might be some very interesting opportunities if an IDE vendor
could figure out how to leverage some of the markup editing capabilities of one of the
leading Page Tool vendors/
We will be doing some prototyping in the whole area of tools based
development for Barracuda here in the near future, so this section will be updated as more
details become available.
|