« links for 2007-07-28 | Main | links for 2007-07-30 »

Struts 1 Problems

Update 2007/07/28: Paul Brown has some pointers and ideas on moving to Struts2, tho, I have a quibble with the title :)

I've been known to be critical of Struts 1 (aka "Struts classic") in the past, and in some cases have argued against its use in projects. Saying Struts sucks isn't especially enlightening, so for future reference I thought it would be handy to write down in one place (and dispassionately as possible) the issues I've seen. Where I can think of them, I've mentioned alternative approaches.

Verbosity and indirection. Even simple applications require a number of actions, controllers and form handlers. Large websites end up with very lengthy struts-config.xml files that in turn drive a demand for visual tools to understand them in maintenance. Some issues have been dealt with by extensions (eg DynaForms solving some issues with form beans), but the amount of surface area required to generate pages results in significant complexity and is reminiscent of the situation with EJBs. The important issue here is time to market; if you need to be flexible, be able to quickly deliver and react to the customer promptly over repeated iterations, Struts will not easily support those needs. Any associated maintenance capacity with Struts is driven by Java itself and heavy IDE support an is not inherent to the framework. Specifically, walking up to a Struts app and understanding where all the redirects are going, and how the various orthogonal concerns are managed is normally a challenge, and that keeping Struts apps clean and well organised over time requires effort to fight down entropy..

Limited pattern matching. Struts doesn't support wildcarded or templated URLs. The common workaround being URLs that end in *.do, *.html or *.jsp purely to satisfy the framework's mapping capability. It's hard to embed URL slugs in Struts without building a micro-framework on top to handle them. This can result in messy and inflexible URLs. Technically this can be dealt with, but the framework does not directly support good URL design.

struts-config.xml struts-config tries to capture primarily the flow of application state on the server, by being an awkward representation of a call graph. In doing it misses a key aspect of the web - hypertext. In web architecture, HTML hypertext on the client is the engine of application state, not an XML file on the server. Struts-config.xml tries to say too much - declaring controllers, forward dispatching and validators, etc. The end result is that it's difficult to understand how a Struts application works or is organized; it's often easier to click around the site and follow log traces or attach a debugger. Ultimately the configuration file focuses on the wrong thing, server sided redirection instead of URL mappings to the domain objects.

Alternatives: If you want to see an exemplary example of stating the URL space and view dispatching, look at Django's urls.py. For entirely automated mappings, Zope dispatch or Rails routes are good examples.

Difficult to test or reuse code. Struts over-exposes the Servlets framework in method arguments, making the code difficult to test outside a container.This design idiom also encourages developers to pass down and depend things like ServletContext deep into the object domain. Struts use an inheritance driven API (essentially Java 1990s style), which makes it awkward to reuse code or keep the domain independent of the web framework.

Alternatives: Spring MVC and Struts2/WebWork keep Servlet specific artifacts to a minimum.

Limited template support. The templating system in Struts is Tiles. Although it does allow you to define things like footers in one place, which is good, it's difficult for developers to manage the look and feel of a website independently of its engineering. For designers it's hard to actually see see the layouts - the primary design artefact is the Tiles configuration itself (which is technically unnecessary). This makes Struts an incomplete framework that tends to couple the view and template (granted, JSP is a cause here as well).

Alternatives: In Java teams often migrate to SiteMesh to support cohesive layouts and layout switching, which it does by inverting the rendering flow - pulling content from the JSP output into the template. Django templates' page blocks along with template inheritance achieves DRY for both includes and layouts. Plone layouts are modular skins and are divorced from content objects. Movable Type and Wordpress have template/skin support by defining function based DSLs a template author can use.

Conceptual mismatch with the Web. Struts is impedant with Web architecture by focusing actions instead of nouns. Specifically forms and actions (common gateways) are emphasised instead of requests to resources. This is because Struts is action/controller driven (sometimes called Model2 in the Java world). Controllers come from the "MVC" pattern, which was originally derived for organizing desktop applications. Unfortunately desktop applications have very little in common with web applications, either in terms of interaction design or engineering. In pattern language terms, the MVC pattern has been reapplied to the Web domain without consideration for the forces induced by the Web. MVC frameworks tend to be inwardly focused contraptions of server sided redirects.

Alternatives: On the web, a suitable pattern is View, Model, Template. A request to a URL is dispatched to a View. This View calls into the Model, performs manipulations and prepares data for output. The data is passed to a Template that is rendered an emitted as a response. ideally in web frameworks, the controller is hidden from view. Note that this framework style is often called MVC anyway, confusing matters somewhat; The key differences are that Views and Templates are cohesive and Controllers are pushed down into the framework infrastructure.

Other supporting design patterns are Decorator for rendering and Proxy/Interceptor for introducing orthogonal concerns (such as permissions checks and entity caching). SiteMesh is a good example of a Decorator and the Servlets spec supports Interception via servlet filters.

Almost any issue mentioned here has a workaround,a compensating pattern, or an extension you can use. The obvious exception is "conceptual mismatch with the Web" - that can't be solved without changing the framework altogether. I'm sure there are many many people who are happy and successful with Struts; this isn't meant to disparage people working with it - once upon a time. Struts was the only real game in town for Java web development. Nonetheless Struts 1 is limited and is showing its age. Starting new projects with it needs careful consideration, despite its continued popularity.

July 28, 2007 11:10 PM


Post a comment

(you may use HTML tags for style)

Remember Me?

Trackback Pings

TrackBack URL for this entry: