(Calling Struts an "application framework" is inaccurate. Struts assists the developer in building only the front end of an application. It does nothing for the model layer or the database layer. It's not a full-stack framework.)
It can be argued with some force that Struts 1 is a mediocre tool. Here are some reasons why.
No policies for translating request parameters into common java objects.
All java web applications need to translate raw request parameter values
into common items such as Integer
, Date
, and BigDecimal
.
However, Struts 1 provides no support for this task. It
does not define reasonable default policies, nor does it encourage the
user to define such policies in any way.
ActionForms are a massive parallel structure to the "real" model.
The ActionForm
classes are not intended as the actual model.
They are intended as a preliminary validation buffer between the raw HTTP
request and the "real" model class. (For example, an ActionForm
might validate that a request parameter can be parsed into an Integer
,
whereas the related model class might validate that the Integer
is within the range 1..10
.) ActionForm
s include only
String
and boolean
items, and nothing else. Since ActionForm
s
and model classes exist as a pair, this creates massive unnecessary
parallelism.
This point is closely related to the first one. If centrally defined
policies for translating request parameters into Integer
, Date
,
BigDecimal
,
and so on, existed, then model objects could indeed be constructed out
of request parameters more or less directly.
Furthermore, even though Struts 1 requires that model objects be constructed
out of related ActionForm
s, it gives no direct support to the
programmer for performing this task.
Data validation is separated from the Model Object.
A fundamental idea in object programming is to unite data with related actions. Typical business applications are excellent for illustrating this idea, since business data usually has many related validations. Thus, the Model Object should typically encapsulate both data and validations. In Struts 1, however, data validation is completely separated from the Model Object. Why? Why have the creators of Struts 1 lost sight of such a fundamental, basic idea in object programming? It does not seem to have any justification.
Standard HTML forms are not used.
In Struts 1, forms usually depart widely from standard HTML, and are usually implemented with a specific set of custom tags. This is neither necessary nor desirable. It's not necessary since other tools have demonstrated that dynamically populated forms can simply reuse standard HTML forms as part of their implementation. It's not desirable since the page author cannot reuse their knowledge of standard HTML, but is instead forced to learn a new set of custom tags specific to Struts 1. This is unproductive.
Actions must be thread-safe.
Action
s are always cached and reused by Struts 1. This is both
a performance optimization and a constraint, since it requires Action
s
to be safe for use in a multi-threaded environment.
As a performance optimization, this policy is of dubious quality. The
stack traces of a web container are large. If an Action
is "just
another object", it's of very little benefit to cache and reuse it. On
the other hand, designs in which an Action
holds a reference to
an expensive object (such as a database connection) are often inferior.
As a constraint, Joshua Bloch explains clearly in Effective
Java that ensuring a class is usable in a multi-threaded environment
is a non-trivial task. Forcing all Action
implementations to be
thread-safe seems an onerous requirement having doubtful benefit. For example,
in a Struts 1 Action
, data shared between methods cannot be stored
in a field; rather, it must be passed as a parameter.
Struts 1 is an unimpressive implementation of the Command pattern.
The execute
method has four arguments, which must always be
passed in, regardless of whether or not the argument is actually relevant
to a particular action. In the Design Patterns book, the number
of arguments to the execute
method is exactly zero. There is a
good reason for this, and it's illustrated by almost every design pattern
in the Gang Of Four book: the central methods of any design are free of
implementation details. Data needed by the implementation of an abstraction
is almost always passed to a constructor. This keeps the abstractions
clean, and places data specific to the implementation in a place where
inheritance and polymorphism do not apply (the constructor).
In addition, Struts 1 always requires a cast to be performed in an Action
,
to get access to a specific ActionForm
.
Casts are something to be avoided unless absolutely necessary, since they
lead to runtime errors.
The web4j tool was built out of strong dissatisfaction
with the Struts 1 front end framework.