The Struts 1 front end framework was one of the first java web application tools to be published, and it's still being used.
(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.) ActionForms include only String and boolean items, and nothing else. Since ActionForms 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 ActionForms, 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 is not necessary since other tools have demonstrated that dynamically populated forms can simply reuse standard HTML forms as part of their implementation. It is 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.
Actions are always cached and reused by Struts 1. This is both a performance optimization and a constraint, since it requires Actions 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 is 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.