Wednesday, September 26, 2007

A Review of the MVC pattern

Tight coupling among software components is one of the common problems in large enterprise applications. This is due to the large amount of data and the way in which this data is represented to users of the application. In practice, it's very easy to fall into the problem of writing unorganized code that, although it delivers a product, it does not maintain any known convention or standard. This only contributes to the problem of extending application functionality (scalability) which is almost certain to happen. Many design patterns are used in the industry to solve different business problems. Among these, the Model-View-Controller (MVC) pattern is one that if often misquoted and misused. In using the Struts Framework for building web-based applications, it is crucial that every developer understand this pattern.

In the MVC patterns, a clear distinction is made between three different components. These are the Controller, the View and the Model. Each of this components help segregate and centralize certain functionality of our code away from each other (loose coupling), thus scalability and re-usability is feasible. The following figure provides a small representation of how this components are meant to interact:

Figure 1 - Diagram of the Model-View-Controller Pattern

In this pattern, the Model component is a representation of some business data. This is also known as "domain model" and is specific to a business. It can also serve as a representation of a "real-world" process that the application is identifying or hold the state of a business entity. The View component is a specific display of the model component in the user interface (UI). This is also known as the "presentation layer" of the application. Thus, if the model component is a BankAccount object, the view component may be an HTML page containing account balance and transactions, or a frame of UI widgets representing the account holder personal information. Note that for both of this examples, the model knows nothing about the view, however the view needs to know some about the model component in order to display it. This direction in dependency is an important concept in this paradigm which encourages loose coupling among components: Developers programming in the model component do not depend on the presentation layer.

Changes to the model component (information holding business data) are handled through the Controller of the application. This means that if the view component has a function (e.g a button, or a drop-down) that needs to be triggered in order to execute an update on the model component, the view communicates this event to the controller component who executes this change and updates the model component. This level of redirection ensures the controller to handle the proper action per view according to business needs. For example, a bank account number may need to be "read-only" to customers but to staff members, this may be an editable field. In this case, it is up to the controller to decide whether the action of updating the account number should trigger an update operation on the model component and is up to the view component to determine if this functionality is even displayed to the user.

In the context of the Struts Framework, the MVC pattern can be represented using the following diagram. Note that the three components of this pattern appear in the same order as in Figure 1:

Figure 2 - Struts implementation of the MVC pattern.

Struts is focused on web-based Enterprise Applications and is heavily based on Servlet Technology. At the core of the controller component is the ActionServlet object. In general, this servlet forwards control to Action objects (to perform CRUD operations on the model component) or to another view component. This ActionServlet knows how to associate view components with specific Action objects through one or more XML files loaded during the servlet initialization process - init() method. Thus changes to this XML file typically represent a reload of this ActionServlet. In this approach, developers are left to insert code in the Action objects of their choice in order to perform changes in the component. When objects need to be placed in the presentation layer, the controller also uses this Action objects to place this model in proper scope (page, request, session, etc).

Struts also provides different tag libraries to help in the rendering of the model components in the presentation layer (view), however, it is left to the developers to decide how to display the data by virtue of the MVC pattern. This means that JSP, velocity or any other rendering engine can be used as part of the presentation layer. As for the model this can be any representation of the domain model of the application such as an entity bean EJB, a Java Bean using Hibernate (Session in View) or Data transfer objects to partially represent a domain model object. Other components can also be plugged to controller component such as resource bundle configuration, menu capabilities, tiles, etc. This pluggable architecture mixed with other configurable features (e.g. validation) has made Struts a preferable option when choosing to use the MVC pattern as part of the architecture of a Java Enterprise Application.

Loose coupling between components is the key concept. Different frameworks are available in the open source community, among which some offer an MVC architecture for Java Enterprise applications, however keep in mind that, as quoted in Martin Fowler's "Patterns of Enterprise Application Architecture":

"The value of MVC lies in its two separation. Of these the separation of
presentation and model is one of the most important design principles in
software, and the only time you shouldn't follow it is in very simple
(page 332)

So, keep these in mind when using Struts. Additional features offered by the framework should not be confused with the objective for which Struts was designed. Overuse and/or additional design without careful planning can prove to reduce scalability thus reducing the value of the product in the long run.

Saturday, September 15, 2007

Introduction to Struts 1.x

Some years ago, I was asked to add a new feature to an existing struts-based application. The feature would include some form validation, form pre-population as well as some embedded logic depending on the authenticated user. Double submissions were also a big concern and had to be detected and avoided. These, among others, are many of the tasks where Struts can be extremely helpful. Sure, there are many things that experienced developers will find as shortcomings (just as any other tool has weaknesses), yet Struts continues to grow from these and is now a well-defined Java Framework for building Enterprise Applications using a Model-View-Controller (MVC) architecture.

One thing to remember is that Struts is not the only solution, is only one of the many. Specifically, it's one commercially popular in the Java programming language. There are other solutions available such as WebWork (now merged with Struts to make Struts2), Spring MVC, Swing, JSF (which is now the official MVC specification from Sun MicroSystems), Stripes, JFace, OpenBravo, etc. Alternatively, other programming languages (such as Ruby on Rails) have an MVC approach of their own. In general, it is the pattern (MVC), not the tool (Struts), that we must remember brings success to an Enterprise Application.

If you are a newbie, be aware that Struts is now branched in two different projects: Struts1 and Struts2. The first one aims to continue development on the original Struts Framework. Struts2 is the new approach for MVC development as developers from the Struts and WebWork2 (OpenSymphony) communities joined forces to provide a cleaner (and simpler) way of developing web-based applications. You may want to consider choosing one first (as suggested on their official site) if you have never used either version as both bring to the table fundamental differences. Unfortunately, as a newbie you are going to need to have some understanding of basic technologies. Although the Struts documentation suggests some of these, I would list the following as the key technologies to understand:

  • HTTP Request/Response Cycles
  • Properties Files and Resource Bundles
  • Servlets, Filters, and Web Containers (e.g. Tomcat, Resin, Weblogic, WebSphere)
  • Java Server Pages Technology (JSPs, Tags)
  • XML
  • Model-View-Controller Pattern
Reading about these shouldn't be difficult for the average developer. The challenge will come later when a developer uses Struts in a real case scenario. It is fundamentally important to remember that Struts is a tool and not the "only" tool to generate Enterprise Applications. Often times, I've found source code where developers have misused Struts by forcing their many features to address a business problem already solved by other technologies (e.g. JSP, Filters, etc). Start with small sample projects and work your way up. For the curious newbie, I've found the JAD decompiler (while developing using Eclipse) to be a great tool for development of Struts Application using your favorite IDE (so you can look at the needed source). This source code is available anyway, but with this tool you can view only what you need, when you need it. Tracing the ActionServlet Servlet object in the org.apache.struts.action package can prove to be a very insightful experience... Enjoy!

Before Struts, your would have to extract each parameter of a request using a "getParameter()" method of the ServletRequest object. Struts encapsulates this with their ActionForm object, thus learning the life cycle of this class is essential when dealing with incoming HTTP requests. Also, prior to Struts, you would also have to write certain logic to learn how to forward a request to another Servlet for further processing. Struts solves this with their ActionServlet and one or more XML configuration files that drive the application flow. Double submissions of HTML Forms were handled by some hack in between Servlet calls. Struts solves this problem by using a "token-per-request" approach and the methods isTokenValid(), resetToken() and saveToken(). In general, Struts provides an Object Oriented API which helps visualize these problems and many more as objects.

In my experience, learning about the Model-View-Controller pattern is the key to using Struts successfully. This understanding, coupled with adherence to good and useful programming practices (which I plan to address in a different blog entry) will help you appreciate Struts better. So read about this and other practices and use this framework to do what is meant to do: " create/help web applications utilize an MVC architecture" (Reference)