编程语言

img DinoSantiago

Barracuda - Framework Comparisons(翻译)

发表于2004/10/20 14:14:00  2622人阅读

分类: Java

 

Last Modified: 01/07/2003 01:15:37

Barracuda - Framework Comparisons
写作本文的目的是为了提供对Barracuda与Struts的详细barracuda.gif (11357 bytes)分析。我们首先关注于它们各自大体的架构,然后再就关键问题进行比较/对比。
  1. 开发方式
  2. Framework概要 
    1. Barracuda
      1. 客户端接受能力 
      2. 事件模型 
      3. 表单映射与验证 
      4. XMLC
      5. 本地化 
      6. 组件模型 
    2. Struts
      1. Controller
      2. Model
      3. View
      4. Utilities
      5. 未来的发展方向 
  3. 比较与对比 
    1. 用户界面方面
      1. 界面表示与程序逻辑的分离 
      2. 页面设计 
      3. 标签库 
      4. 用户界面布局 
      5. 本地化 
      6. 对多种类型客户端的支持 
      7. Support for multiple Client Skins
      8. Client Capabilities
      9. Client Accessibility
    2. 流程控制方面
      1. 事件处理 
      2. MVC / Model 2
      3. 工作流程 
    3. 服务器端 
      1. Form映射与验证 
      2. 错误处理 
      3. 组件模型 
      4. 组件复用 
    4. Scalability
      1. Throughput
      2. Volume
    5. 与开发工具的集成 
      1. Page Tools
      2. IDEs

开发方式 - 当我们进行Web应用的开发时,很难去夸大不同开发方式间的差异。不过,如果经过更进一步的观察,我们还是可以识别出一些现今的开发方式上的分化。

  • 开发者类型 - 今天,有两种截然不同的开发者正在创建Web应用:

    1. 页面开发者 - 趋向于从基于页面的视角来看待Web应用。目前为止,这一类人为数众多,他们的重心倾向于JSP, ASP, PHP, Cold Fusion等等基于模板的技术。他们一般对JavaScript和VBScript这样的脚本语言也比较熟悉。

    2. Java开发者 - 趋向于从以应用为中心的视角来看待Web应用。这些人更喜欢用强数据类型的面向对象语言,比如Java, C++或是SmallTalk来编码,并且经常使用Servlet技术来进行Web应用的构建。

  • 开发工具 - 循着相似的线索,我们能看到两种截然不同的开发工具与上面提到的两种开发者相对应:

    1. 基于页面的工具 - 一般指类似于DreamWeaver, UltraDev和FrontPage这样的可视化编辑器。

    2. 传统的IDE - 一般是指类似JBuilder, NetBeans/Forte, VisualAge或是VisualCafe这样的开发环境。

然而这些都是显而易见的,如果我们能够更为清晰地描绘出这些差异将会很有意义,因为许多Web 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.

  1. 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:

    arch_overview.gif (20966 bytes)

    The key features of Barracuda are summarized here:

    1. Client Capabilities - Automatically identifies client capabilities (browser type, target locale, etc).
    2. Event Model - Maps client requests to first class event objects; dispatches events to all interested listeners; guarantees that an HTTP Response is generated.
    3. Form Mapping & Validation - Converts HTTP Form parameters into first class Java objects and provides a powerful validation mechanism to verify them.
    4. XMLC - Compiles HTML, WML, and XML documents into DOM template objects that can be manipulated programmatically.
    5. Localization - Automatically creates localized versions of the DOM templates for additional locales. These templates can be loaded based on a target client locale.
    6. 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:

    1. 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.

    2. 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).

    3. 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:

      1. 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)
      2. provide default values if an expected parameter is not present
      3. provide a number of prebuilt validators (NotNull, ValidType, Equals, MaxLength, MinLength, Range, Digit) to handle common validation tasks in a reusable fashion
      4. support the the notion of custom validators to express specific business logic validation requirements
      5. allow for validator aggregation, by which any number of simple validators can be used as building blocks for more complex validation behavior
      6. 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.

    4. 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.

    5. 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.

    6. 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:

        • any component may contain other components
        • the primary responsibility of components is to render data into the portion of the DOM to which they are bound, and to render all child components
        • there are a number of basic components (BInput, BToggleButton, BAction, BLink, BText, etc) that all extend from a base BComponent
        • there are several more advanced components (BList, BSelect, BTable, and BTemplate) that provide strongly typed MVC interfaces, just like you'd find in Swing
        • all Barracuda component models may return multiple data types -- Strings, DOM Nodes, or other BComponents. This is strategic for supporting component aggregation.
        • there is no framework imposed lifecycle -- you can keep components around for as long or as short a time as makes sense for your domain. In other words, you can create/destroy them repeatedly for every render cycle, or you can cache them on a per-session basis. The developer is not locked into any one approach.
        • similarly, there are no imposed state restrictions -- the framework does not force you to take any particular approach to manage component state. You can persist component state where you wish when/if you need to do so.
        • some Barracuda components offer event model integration -- by adding an event handler the server can be automatically notified when a client gesture occurs. For the developer the process appears seamless, just like 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".

  2. 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:

    mvc2_struts.gif (6329 bytes)

    Struts consists of the following architectural pieces:

    1. 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.
    2. 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.

    3. 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

    4. Utilities - Struts offers several utilities aimed at specific aspects of the development process:

      • Localization - Struts uses the standard Java localization mechanism, augmented with a standard Message Resource that can be accessed by various custom tags. The tags can automatically display the appropriate text for the user's locale.
      • Digester - a simple but powerful abstraction around a SAX-based XML parser that is handy for converting XML documents into trees of Java objects with an isomorphic structure. The digester is now available through the Jakarta Commons project as a standalone utility.
      • Database support - Struts allows you do define JDBC data sources from a config file and provides a JDBC connection pooling mechanism

    5. Future directions - Struts also has some interesting ideas for future development:

      • a "ValidatorForm" is being integrated with Struts that offers client and server side validations from the same XML configuration. It is now available as a plug-in.
      • an advanced templating package called "Tiles" that is appropriate for building portals and other complex layouts
      • a regular expression scripting language that can be used to more easily/powerfully express what data to retrieve from collections of JavaBeans (while many prefer XPath syntax, they will probably adopt whatever the JSP Taglibs working group decides upon...looks like something similar to JavaScript)
      • support for dynamic properties within ActionForms (so that you don't have to hand-create a bean class with getters and setters -- you can use a hashmap structure instead)
      • workflow mechanism that can be specified via an XML descriptor


Comparison / Contrast - Now that we've addressed the basics, it may prove helpful to look at how the frameworks compare on specific issues.

  1. UI Issues -

    1. 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.

      1. 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.

      2. 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.)

      3. 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.

      4. 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.

      5. 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).

      6. 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:

      1. 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)

      2. 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.

      3. 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.

      4. 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:

      1. 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!

      2. 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.

      3. 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 :-)

    2. 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.

    3. 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).

    4. 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.

    5. 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:

      1. 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-

      2. 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.

    6. 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.

    7. 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...

    8. 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.

    9. 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).

  2. Flow Control Issues -

    1. 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:

      1. 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)

      2. 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).

      3. 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.

      4. 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:

      event_dispatcher.gif (77575 bytes)
      [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
            • ListEmployees
          • AuthorizedEvent
            • AddEmployee
            • PromoteEmployee
            • DemoteEmployee
            • FireEmployee
      • ViewEvent
        • ErrorEvent
          • HRErrorEvent
            • NotInHR
            • NotAuthorized
        • ShowEmployee

      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.

    2. 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.

    3. 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.

  3. Server Side Issues -

    1. 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.

    2. 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).

    3. 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:

      1. From a very generic sense, it can often be used to describe any reusable piece of code.
      2. 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.
      3. 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.

    4. 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.

  4. 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.

    1. 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.

    2. 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.

  5. 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.

    1. 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.

    2. 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.


For all the latest information on Barracuda, please refer to http://barracudamvc.org
Questions, comments, feedback? Let us know...

阅读全文
0 0

相关文章推荐

img
取 消
img