This book will demonstrate the use of freely available Java Open Source (JOS) development frameworks for building and deploying applications. Specifically, we will focus on the JOS development frameworks available from the Apache Software Foundation's Jakarta group (http://jakarta.apache.org).
While most books are heavy on explanation and light on actual code demonstration, this book emphasizes approachable code examples. The authors of this book want to provide a roadmap of JOS development tools to build your applications. Our intent in this book is not to present each of the frameworks in minute detail. Frankly, many of the development frameworks presented in this book could have entire books written about them.
This book will build a simple application using the following Jakarta technologies:
A Model-View-Controller-based development framework that enables developers to quickly assemble applications in a pluggable and extensible manner.
A powerful indexing and search tool that can be used to implement a search engine for any web-based application.
A templating framework that allows a development team to easily build "skinnable" applications, whose "look and feel" can be easily modified and changed.
An industry-accepted Java build utility that allows you to create sophisticated application and deployment scripts.
This chapter will not go into the details of the technologies listed above. Instead, it will highlight some of the common challenges in building web applications and explore some common design mistakes and flaws that creep into web-based application development efforts.
The truth is that, while all developers would like to write new applications from scratch, most of their time is spent in performing maintenance work on existing software. Identifying design flaws, referred to as antipatterns throughout this book, and learning to use JOS development frameworks to refactor or fix these flaws can be an invaluable tool.
Specifically, the chapter will explore how the following web-based antipatterns contribute to entropy within an application:
The chapter will end with a discussion of the cost savings associated with building your own application development framework vs. using JOS development framework.
In the mid-nineties, the field of software development was at its peak. The importance of using the Internet was quickly recognized as a revolutionary means for companies to communicate their data and processes not only to their employees but also to their customers.
Fueling the Internet explosion was the World Wide Web and the web browser. Web browsers offered an easy-to-use graphical interface that was based on standards and allowed easy to access to data on a remote server. Originally, the web browser was viewed as a means of allowing end-users to access static content of a web server. Early web applications were often nothing more than "brochures" that provided users browsing information about a company and the products and services it offered.
However, many software developers realized that the web browser was a new application development platform. The web browser could be used to build applications that provided customers with direct and easy access to corporate applications and data sources. This was a revolutionary concept because for many businesses, it eliminated the need to have a large customer service department to handle routine customer requests. It allowed them to make their processes more efficient and develop a more intimate relationship with their customers.
The ‘thin’ nature of the web browser meant that software could be quickly written, deployed, and maintained without ever touching the end user's desktop. Moreover, the web browser had a naturally intuitive interface that most end users could use with very little training. Thus, the Internet and the web browser have become a ubiquitous part of our computing lives and a primary application development platform for many of today's applications.
However, the transition of the web from being an electronic brochureware to an application development platform has not been without growing pains. Writing anything more than a small web application often requires a significant amount of application architecture before even a single line of real business logic is written.
The additional overhead for implementing a solid web application is the result of several factors, such as:
Early web-based development was often chaotic and free flowing. Little thought was given to building web applications based on application frameworks that abstracted away many of the "uglier" aspects of web development. The emphasis was on the first-to-market with their functionality. However, the size and complexity of web-applications grew with time, and many web developers found it increasingly difficult to maintain and add additional functionality to their applications.
Most experienced software developers deal with this complexity, by abstracting various pieces of the application's functionality into small manageable pieces of code. These small pieces of code capture a single piece of functionality and when taken together, as a whole, form the basis for an application development framework.
An application development framework can be defined as:
A collection of services that provides a development team with common set of functionality, which can be reused and leveraged across multiple applications.
For web applications these services can be broken down into two broad categories:
Enterprise services consist of the traditional "plumbing" code needed to build applications. These services are extremely difficult to implement and are outside the ability of most corporate developers.
Some examples of enterprise services include:
Fortunately, the widespread acceptance of building applications based on application servers has taken the responsibility for implementing these services out of the hands of corporate developers. Enterprise-level development platforms, like Sun's J2EE specification and Microsoft's .NET, offer all of the functionalities listed above as ready-to-use services that developers can use in their applications. Application servers have minimized the amount of plumbing code that an application developer has to write.
This book will not be focusing on the services provided by J2EE and .NET application servers, rather it will be focusing heavily on the next topic, that is application services.
The enterprise-level development platforms, such as J2EE or .NET, simplify many of the basic and core development tasks. While the services offered solve many of the enterprise issues (security, transaction management, etc.), they do not help the application architect with the often daunting task of building web applications that are maintainable and extensible. To achieve the goals of maintainability and extensibility, several challenges need to be overcome. These challenges include:
How does the end user move from one screen to the next? Is the navigation logic embedded directly in the business logic of the application? Web applications, having a primitive user interface, can allow users to access and navigate through thousands of pages of the content and functionality.
As web applications run in a thin client environment (with a web browser) the screen layout can be personalized to each user. Since user requirements are constantly changing, web developers need to adapt the look and feel of the application quickly and efficiently. Design decisions made early in the application design process can have a significant impact on the level of personalization that can be built into the application at a later date.
Very few web development teams have a consistent mechanism for collecting data, validating it, and indicating to the end user that there is an error. An inconsistent interface for data validation and error handling decreases the maintainability of the application and makes it difficult for one developer to support another developer's code.
This is one of the most problematic areas of the web application development. The reason being that the development team does not have a disciplined approach for building their business logic into discrete components that can be shared across applications. The developers couple the business logic too tightly to the web application, and resort to the oldest method of reuse, cut and paste, when they want to use that code in another application. This makes it difficult to maintain the business rules in a consistent fashion across all of the web applications in the organization.
The majority of web application development efforts involve integrating the front-end web application with back-office data stores. However, data retrieval and manipulation logic is tedious code to write, and when poorly implemented, ties the front-end application to the physical structure of the back-office data stores.
Unfortunately, most developers either do not have the expertise, or are not given the time to properly address these issues before they begin application development. With the pressure to deliver the application, they are forced to "design on the fly" and begin writing code with little thought to what the long-term implications of their actions are. This may result in antipatterns being formed within their applications.
These antipatterns contribute to the overall complexity of the application and ultimately increase the presence of entropy within the code base. Often, they do not realize the impact of these antipatterns until they have implemented several web applications and are now trying to support these applications while developing new code.
In the following sections, we are going to introduce the concept of patterns and antipatterns. We will then identify some common antipatterns in web application development, based on the discussion above.
One cannot open a software development journal or go to the bookstore without seeing some reference to the software design patterns. While many software architects love to enshroud patterns in a cloak of tribal mysticsm, the concept of a software development pattern is really quite simple.
Design patterns capture software development patterns in a written form. The idea behind design patterns is to identify and articulate these best practices so as to help other developers avoid spending significant amount of time re-inventing the wheel. The notion of the design pattern did not originate in the field of software development.
Design patterns originated in the field of architecture. In 1977, an architect by the name of Christopher Alexander was looking for method to identify common practices in the field of architecture that could be used to teach others. The concept of design patterns was first applied in 1987 by Kent Beck and Ward Cunningham (http://c2.com/doc/oopsla87.html).
However, the embracing of the software development design patterns really occurred with the publishing of the now famous Gang of Four (GOF) book, Design Patterns: Elements of Reusable Object Oriented Software (Gamma, Helm, Johnson, Vlissides), Addison-Wesley, ISBN 0-201-63361-2. First published in 1995, this classic book identified 23 common design patterns used in building software applications.
The concept of the antipattern was first introduced in the groundbreaking text, AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis, John Wiley (ISBN 0-471-19713-0). The book examined common patterns of misbehavior in system architecture and project management. As we are going to explore various antipatterns associated with web application development, it is useful to look at the original definition (from the aforementioned book) of the antipattern:
"An antipattern is a literary form that describes a commonly occurring solution to a problem that generates decidedly negative consequences. The antipattern might be the result of a manager or developer not knowing any better; not having sufficient knowledge or experience in solving a particular type of problem, or having applied a perfectly good pattern in the wrong context."
An antipattern is a means of establishing a common language for identifying poor design decisions and implementations within your application. Antipattens help identify poor design decisions and help give suggestions on how to refactor or improve the software. However, the suggestions associated with the antipattern are only that. There is no right or wrong way of refactoring any antipattern, because every instance of an antipattern is different. Each instance of an antipattern will often have a unique set of circumstances that caused the pattern to form. Web antipatterns focus on poor design decisions made in web-based applications.
It is not an uncommon experience for a developer studying an antipattern to stop and say: "I have seen this before" or to feel a sense of guilt and think, "I have done this before". Antipatterns capture common development mistakes and provide suggestions on how to refactor these mistakes into workable solutions. However, there is no single way to refactor an antipattern. There are dozens of solutions. In this book, we merely offer guidance and advice, not dogmatic principles.
The web development antipatterns that are identified and discussed throughout this book are not purely invented by the authors. They are based on their experience working with lots of development teams on a wide variety of projects.
For the purpose of this book, we have identified six basic antipatterns that most Java developers will encounter while building web-based applications. The web development antipatterns to be discussed are:
Since the original definition of an antipattern is a literary form of communication, we will discuss each antipattern in general. In addition, symptoms of the antipattern are identified along with suggested solutions. However, the solutions described in this chapter are only described in very general terms. Specific solutions for the antipatterns will be demonstrated, throughout this book, by the application of JOS development frameworks.
This book is written considering the following key points:
Architecture is done right when it has been implemented in the most straightforward fashion. Simplicity, above everything else, will guarantee the long-term maintainability and extensibility of an application.
Now let's discuss the different web antipatterns in more detail.
The Concern Slush antipattern is found in applications when the development team has not adequately separated the concerns of the application into distinct tiers (that is, the presentation, business, and data logics). Instead, the code for the applications is mixed together in a muddy slush of presentation, business, and data-tier logic. While development platforms like J2EE help the developer separate their application logic into distinct tiers, it is ultimately how the application is designed that determines how well defined the application tiers are. Technology can never replace good design and a strong sense of code discipline.
This makes the code extremely brittle. Changing even a small piece of functionality can cause a ripple effect across the entire application. In addition, every time a business rule needs to be modified or the structure of a data store changes, the developers have to search the application source code looking for all the areas affected by the change. This leads to a significant amount of waste of time.
This antipattern also tends to lead to insidious bugs creeping into the application, because invariably the developer will miss some code that needs to be modified. The bugs resulting from these missed changes might not manifest themselves for several months after the change to the original code was made. Hence, the development team has to spend even more time tracking down the missed code and fixing, testing, and redeploying it.
Most of the time the Concern Slush antipattern will emerge for one of the following reasons:
The development team does not have a senior developer playing the role of an application architect. The application architect's primary role is to provide high-level design constructions for the application. The architect establishes the boundaries for each of the application tiers. They enforce development discipline within the team and ensure that the overall architectural integrity of the application stays in place.
The development team is new to enterpise development and writes its web applications without a thorough understanding of the technology it is working with.
Often the developers are used to writing code in a procedural language (such as C or Visual Basic) and are suddenly appointed to write web-based applications with an object-oriented language like Java. The development team members continue to rely on their original training and continue to write code in a procedural fashion, never fully embracing object-oriented design techniques.
The team realizes its mistakes during the development, but has been given an agressive deadline to be met. The developers toss caution to the wind and begin coding. They often do not realize how poorly designed the application is, until they begin the maintenance phase of the project.
Often, the development team will work together on a quick prototype for an application, as a proof of concept. The code for the prototype is poorly designed. However, upon demonstrating the prototype, it becomes a huge success. The developers now fall victim to this success as they are put under a heavy pressure to deliver the prototyped application quickly. Therefore, they decide to use the prototype code as the basis for the application.
For web applications based on the Java platform, the symptoms for this antipattern will usually manifest in one of two ways:
The first symptom, overloading of responsibilities, occurs when a single or small group of servlets or JSP pages are responsible for all actions carried out by the application. A basic tenet of object-oriented design is that each class within the system should have small, well-defined, and discrete set of responsibilities.
A class, in this case a servlet or JSP page, is overloaded when the exact responsibilities of the class are not clear. Servlets and JSP pages that do not have well-defined responsibilities are often said to be "fat" or "heavy". The call to such a page always includes a number of control parameters that are used by the servlet or JSP page. These control parameters are used by conditional logic embedded by the servlet or JSP page to determine the code to be executed within the page.
In the second symptom, a servlet or JSP page mixes together presentation, business, and data logic into one massive procedure call. An example of this particular symptom is out.write() statements mixed with business logic and data logic. JSP pages are even more prone to this abuse because JSP scriptlets make it extremely easy, for even a novice web developer, to quickly build an application.
In the second symptom, we are assuming that no session Enterprise JavaBeans (EJBs) are being used in the application. When EJBs are used in an application most developers will gravitate towards putting the business logic in the EJBs. The Concern Slush antipattern manifests itself in EJBs, when the developer indiscriminately mixes data-access logic with the application's business logic in the EJB.
The solution is to provide software constructs that adequately separate the application's code into readily recognizable presentation, business, and data logic. For Java-based applications, the JSP Model-2 architecture is the recommended architectural model for building web applications. The JSP Model-2 is based on the concept of a Model-View-Controller (MVC) framework.
In an MVC framework, all requests made by the end user are routed through a controller class (usually a servlet) that determines the business object used to carry out the request. The data that the users request and the corresponding business object are considered as a model piece of the framework. After the business object has processed the user's request, the results are forwarded by the controller to the view portion of the framework. The view portion of the framework is responsible for the presentation logic that renders the results of the user's request to the end user. The diagram overleaf presents a conceptual view of an MVC framework:
The two key features of the MVC framework are:
The Tier Leakage antipattern occurs in applications that have been separated into three distinct layers of application logic. Tier leakage occurs when code and functionality from one tier are exposed to the other tiers.
This antipattern occurs when the application architect does not enforce the principle of "closed" tier architecture. A closed tier architecture allows each tier to communicate only with the tiers immediately above and below it. In other words, the presentation tier can only communicate with the business tier. It should never bypass the business tier and access data directly. The communication between the tiers happens via well-defined interfaces that do not expose the underlying implementation details of that tier to the one above.
In the case of Tier Leakage, the application architect breaks the application into three tiers, but they also allow communication between the tiers to be open. This means the presentation tier can still call and invoke services on the data-access tier. In addition, even if there is encapsulation of services, the underlying tier details still remain exposed. This allows the developers to bypass the application partitions put in place and use functionality they should not have access to.
The diagram below illustrates the differences between a closed and open tier architecture:
The end result of not enforcing a closed tier architecture is that, while various classes within the web application can be identified and grouped together in distinct tiers, there still exist dependencies between the tiers. This means that the changes to one tier can have side effects that ripple through the code in the other tiers.
This antipattern occurs when the development team has not defined discrete interfaces that hide the implementation details of one application tier from another. The causes for the Tier Leakage antipattern are very similar to those of the Concern Slush antipattern; developer inexperience, compressed delivery dates, and inappropriate reuse of an application prototype.
Some of the symptoms of Tier Leakage include:
The first symptom is a common mistake. Instead of wrapping data retrieved from the data tier, the business tier exposes the details about the data tier, by allowing the data-tier objects to be passed back to the presentation tier. This results in the presentation class being unnecessarily exposed to the data-access technology being used to retrieve data (that is, JDBC, JDO, entity beans). It also tightly couples the presentation code to the physical column names, data types, and data relationships from the database. If physical details of the database change, developers need to walk through all of the code in the application to reflect the database changes.
The second symptom occurs when the developer allows tier specific classes to be passed back and forth between the different tiers. For example, you may have several classes, responsible for the business logic within your web application, which you'd want to reuse in a Swing based application. However, you cannot easily reuse the business logic, as it accesses an HttpSession object passed to it. The developer, rather than pulling the data out of the session object and then passing it to the business class, passes the HttpSession directly to the class.
There are three steps that can be taken to avoid tier leakage:
This review is designed to be very short (no more than five minutes long). It forces the developers to verbalize exactly what they have written and give the reviewer a chance to catch tier-leakage mistakes before they creep into the overall code base.
While any one of the steps shown above can help minimize the risk of Tier Leakage, you will probably find that using all three steps combined is the most effective. As you will see in later chapters, even with application frameworks such as Struts, you will still need to apply the J2EE design patterns within your application.
Using a development framework can still create dependencies in your code if you are not careful. You can still end up having your application being too tightly bound to the application development framework. Chapter 5 will look at how we can leverage various J2EE design patterns to cleanly separate your application code from the development framework.
While the Tier Leakage antipattern dealt with dependencies being created at the architectural level of the application, the Hardwired antipattern occurs when developers create dependencies at the application level. Hardwiring arises when the developer does not provide configurable plug-in points for screen navigation and application business rules. These items are hard coded into the application source code; thus, any changes to functionality require the source code to be altered, recompiled, and redeployed.
The Hardwired antipattern makes maintenance of web applications difficult because:
The Hardwired antipattern develops because the web development team does not use a declarative approach to build its applications. A declarative design approach separates the application's "what happens" functionality from the application's "how it happens" functionality.
In a declarative architecture, the application is broken into small pieces of functionality that can be configured together using metadata. Metadata is essentially data about data. In most application frameworks, metadata is used to define how a user's request is to be carried out and processed by the framework.
Metadata is usually stored in configuration files, independent of the application source code. When the application development team needs to change the behavior of the application, they do it by changing the metadata configuration. Using metadata to control application behavior is often termed declarative architecture. In a declarative architecture, you define certain behavior and the architecture code carries out the behavior. By using this type of architecture, new functionality can be added or existing behavior modified by changing the metadata. Thus the behavior of the application is not hardcoded and does not require a recompilation and redeployment for the changes to take place.
The advantage of a declarative architecture is that it allows the development team to introduce new functionality into the application, while minimizing the risk of ripple effects that the change will have throughout the system. The disadvantage is that it can be overdone to the point where the application becomes over abstracted, hard to maintain because of the complex configuration rules, and suffers from poor performance.
The symptoms for the Hardwired antipattern begin to manifest themselves, when changes to the application require functionality that was not in its original scope. The symptoms of hardwiring include:
One of the true indications that your application is suffering from the Hardwired antipattern is that a small navigation or business rule change causes major headaches for you or your development team.
The Hardwired antipattern can be refactored, by taking the responsibility of writing the code for screen navigation and business rule invocation out of the hands of the application developer. Instead, this logic should reside as a service within the application architecture. Since this service is no longer a responsibility for the developer, consistency can be enforced among the entire development team and much of the application's navigation, workflow, and business rule invocation functionality can be described as metadata.
The MVC pattern is again an excellent tool for refactoring this antipattern. The controller of the MVC is responsible for application navigation. The business logic for the application is cleanly separated from the presentation logic. Metadata is used to tie all of these different pieces together.
Even if an MVC development framework is used, the only true way to guarantee that a Hardwired antipattern does not develop is through strong software development practices. These practices include:
Do not become overzealous while avoiding Hardwiring in you applications. It is easy to want to make everything in the application configurable.
Good application architecture lies in its simplicity. You always have to negotiate between the need to generalize and abstract framework functionality and the need to avoid tight dependencies. In the end, over abstraction or tight dependencies both lead to the same problem: code that is too complex to understand and maintain easily.
The Stuts development framework takes a declarative approach for writing applications. This framework allows you change the behavior of the application by modifying configuration files. In both of these frameworks, application configuration is very easy and is designed to avoid the over-abstraction problems mentioned above.
The Validation Confusion antipattern revolves around the inconsistent application of validation and business logic in an application. Many web application developers do not clearly separate the application's validation logic from its business logic in an organized fashion.
For the purpose of this book, validation logic is defined as any type of user interface code that involves:
Validation logic is considered extremely "lightweight". Validation rules are considered light, because changing them should not have a significant amount of impact on the overall business processes supported by the application. Business logic is the "heavyweight" cousin of validation logic. Business logic supports business processes. Changing this logic can have a significant impact on how a business is operated.
Why worry about the separation of validation logic from business logic? Failure to separate these two types of logic from one another makes it difficult to support the code. Since the validation logic is not centralized, developers have multiple spots to check when modifying a business rule.
More importantly, not cleanly partitioning the application's validation logic from its business logic can make it more difficult to reuse that business logic in another application. Validation rules are often very specific to an application. Business logic can be abstracted, generalized, and reused across multiple applications. However, with validation rules specific to the application embedded inside the business logic, a tight dependency is created that makes code reuse problematic.
A clean validation logic approach can help avoid previous antipatterns mentioned, namely Concern Slush and Tier leakage. The validation layer can be responsible for adapting the input provided by the user interface to the input required by the business logic. This can help prevent the user interface details from leaking down into the business logic.
This antipattern occurs when the web development team has not clearly defined how it is going to handle the validation of the data collected from the end user. The developers pass all of the data directly to the business rules in the application, without first putting the data through some kind of filter that ensures the data validity.
Validation Confusion can be spotted in one of the following cases:
Refactoring the Validation Confusion antipattern can be accomplished by defining a consistent set of services used for form validation in the web application. These validation services are invoked before any of the business logic for the application is invoked. Any validation errors that occur are immediately processed and the end user is notified in a consistent and repeatable fashion.
In Chapter 3 we will discuss the mechanism provided by Struts for handling form validation and errors.
Web-based applications have the ability to deliver unprecedented amounts of personalized content to the end user. Traditionally, companies pushed information out to their customers in a mass marketing approach. In this approach, customers were categorized into broad groups who shared similar interests and backgrounds. The company would then direct different advertising messages about their products to these groups. Mass marketing approach was considered successful if the organization running marketing campaign received a response rate of one percent.
The web development platform, with its thin-client, easy-to-use, and personalizable interface, has turned the mass marketing concept on its head. Web-based applications can deliver tightly-focused information and functionality to individual users, with very specific preferences and interests. Many of the sophisticated web applications that are currently online:
However, the ability to deliver a customizable user interface to the end user requires some careful planning, in the design phase of a project. The Tight-Skins antipattern is a presentation-tier antipattern. It forms when the development team has not built its presentation tier to be flexible enough to handle personalized content for individual end users.
This antipattern can occur for a number of reasons:
Unfortunately, the only way to combat the Tight-Skins antipattern, after it is formed, is to rewrite the user interface from scratch. This is why it is critical to identify personalization requirements for the application before any serious development work begins.
This antipattern has a number of symptoms including:
The solution for the Tight-Skins antipattern involves cleanly separating application content from your Java source code. This way the content can be presented in multiple formats without having to wade through code. This also makes it easier to change how the content is to be displayed to the end user. Some ways of separating the application's content from its source include:
The Struts framework makes heavy use of custom JSP tag libraries. Some of the Struts tag libraries will be covered in greater detail in Chapter 3.
Most web developers know that embedding data access logic inside of presentation code is poor design. Applications written in this fashion are difficult to maintain, and are tightly coupled with the underlying data structure of the database that they are manipulating. A change to the database can cause many elements of the user interface to be visited and often modified.
Many Java-based web development teams never allow the presentation layer of an application to directly obtain a database connection and use it to access a data store. Instead, they always wrap these calls inside the business tier. The development team never breaks out the Create, Replace, Update, and Delete (CRUD) logic associated with manipulating the data into a distinct set of classes. Instead, they intermix business and data access logic together inside the business tier.
The Data Madness antipattern forms when the application's architect does not decide how data-access logic is to be abstracted away from the other tiers in the application. When building a data-access tier, the following items have to be considered:
As most developers do not think of a data-access tier while designing, the formation of a Data Madness antipattern can significantly increase the amount of time and effort needed to complete a project. Consider the following:
A significant amount of a development team's time is taken up writing data-access code (usually SQL code). Code that does not fit an object-oriented development model is prone to be coded improperly, and is scattered haphazardly through an application's business tier. This is the crux of the Data Madness antipattern.
Most development teams do not see the symptoms of the Data Madness antipattern until they are well along in their development efforts. The first symptoms of the Data Madness antipattern include the following:
Later symptoms of the Data Madness antipattern usually appear in the maintenance and enhancement phase of the project:
With a well-defined data access strategy in place, the development team could have abstracted how primary keys are generated, and centralized all of this logic in one class responsible for primary key generation.
Two steps can be taken to refactor the Data Madness antipattern:
The first step above is a design-based approach involving the use of common J2EE data-tier patterns, like the Data Access Object and Value Object patterns, to abstract away database and data access details. These patterns are extremely easy to implement and when used help the development team maintain data-tier code without affecting the rest of the application.
The second step is a technology-based approach. Java is an object-oriented language that is not well suited to deal with the table-centric structure of relational databases. Instead of having the development team write its own SQL code, use an Object Relational (O/R) mapping tool to perform Create, Retrieve, Update, and Delete (CRUD) actions on behalf of the developers.
O/R mapping tools allow the development team to declare how data retrieved from the database maps to Java objects. O/R mapping is not a new concept. The J2EE API supports the concept of Container-Managed Persistence (CMP)-based entity beans. CMP-based entity beans allow the developer to provide O/R mappings to the J2EE application server and in turn, the application server generates all of the SQL code needed to access the database.
An alternative to entity beans is to use commercial O/R mapping tools. These tools have been available for years to C++ developers and have started gaining a significant amount of acceptance from the Java development community.
Commercial O/R mappings tools, while being very powerful, often carry long and expensive licensing agreements. They are often complicated to use and being a commercial product require a heavy investment in training, before the development team becomes proficient in their use.
However, over the last two years, JOS O/R mapping tools have started gaining more and more acceptance as an alternative means of building data access tiers. In Chapter 5 of this book, we are going to examine how one such JOS O/R mapping tool, ObjectRelationalBridge can be used to solve many of the problems created by the Data Madness antipattern.
When web antipatterns form in an application, the cost of building and maintaining that application grows substantially. The development team's time is eaten up with the complexity that has crawled its way into the application. Less time is available to write real code and the code that is written is usually of mediocre quality.
Why are these antipatterns allowed to form? Developers do not purposely write poorly designed applications. We believe that web development frameworks can significantly reduce the occurrences of web antipatterns forming within an application. Antipatterns sometimes appear because applications are extremely complex to build and implement. Developers do not purposely go out and introduce these antipatterns. These antipatterns often occur because the developers try to manage the complexity of just implementing the application's business logic. At times, they do not realize that the decisions they make now will come at a high price later when an antipattern manifests itself.
A well-designed web development framework will promote consistency and structure for the development team. A framework will provide core application services for screen navigation, data validation, error handling, business rule management, and data persistence. With all of these benefits why haven't more Java web developers adopted the use of web development frameworks in their application development efforts? The reasons vary:
Until recently, open source development frameworks have not been readily available to developers. This meant that if a development team wanted to use a framework, the developers needed to build it themselves. Writing a homegrown development framework can be an expensive undertaking. It usually requires a group of senior developers with several months of uninterrupted time to design, implement, and thoroughly test the development framework.
Most IT organizations do not have senior developers and architects sitting around with nothing to do. Usually these individuals are extremely over allocated and giving them the time to focus on one problem requires commitment from the highest level of management. Even after the framework is completed, additional ramp-up time is needed as the framework developers begin training the development teams in how to use the framework.
For example, the Struts framework has a significant number of services embedded in it. To write an in-house version that offers even a fraction of the services offered by Struts, you have to take into consideration the resources contributed to the Struts framework:
For an organization to build a framework like Struts for internal use with the same level of sophistication and quality assurance could literally cost between a half a million and a million dollars.
Let's not forget that even after a custom framework has been built, the costs of the framework continue to accumulate, as you begin to factor in the development resources needed to maintain and support the framework code base.
For organizations building their own application frameworks, it can take up to year or a year and a half before the organization starts seeing firm return on investment from its framework development efforts. (This includes the time needed to develop the framework and actually build two or three applications using the framework.) This is simply too large of a leap of faith for most companies to make.
Java open source development frameworks offer a viable alternative to building your own application architecture. These frameworks provide the following advantages:
This information is free of charge and unlike most commercial software products does not require an annual support contract. Some open source projects have groups willing to sell support for the product. (Such as, the JBoss Group at http://jboss.org, which not only builds the JBoss application server, but also offers different levels of paid support for the project.)
There are a few downsides with open source development frameworks that should be noted:
Open source frameworks free a development team from having to invest its time in writing infrastructure code. Infrastructure code is the entry price you must pay before you can seriously begin writing an application. From the authors' anecdotal experiences, in many projects, up to 40-60% of development effort involve the implementation of infrastructure code. For the "we don't have time for architecture" development teams, that 40-60% of infrastructure development effort is usually spent in increased maintenance of the application over the course of its lifetime.
Trying to cut costs by implementing complex architectures shifts the upfront architect and infrastructure costs to the maintenance phase of the application.
Ultimately, leveraging the functionality in open source frameworks translates into three direct benefits:
Both the benefits listed above allow the developers to produce higher quality code and deliver their applications more quickly to their end users.
From a management perspective, there are still some items to consider before you use a JOS development framework on your projects:
As stated earlier in this chapter, the purpose of this book is to provide a simple and straightforward roadmap that demonstrates how to successfully use the Jakarta web development frameworks. To do this, we are going to build a simple WebLog application (also known as a Blog). A WebLog, in its simplest form, is an electronic bulletin board where one user can post a story and other users can comment it. Often, a WebLog ends up to be a combination of reports on real-world events with a heavy dose of editorial bias from the storywriters and their commentators. Our WebLog is called the JavaEdge.
The requirements for the JavaEdge application are:
Individuals who visit the JavaEdge Blog can register themselves to be the members of the JavaEdge community. By registering, the users can receive the weekly JavaEdge newsletter.
Visitors to the JavaEdge web site will be able to see the latest top ten stories posted by the JavaEdge community. When browsing the stories, the JavaEdge user will be able to see a short summary of the story. Clicking on a link next to each story will bring up the complete story listing.
When a user clicks on a link next to each story, they will be presented with not only a complete listing of the story they have chosen but also all of the comments associated with that particular story. Each posted comment will display the comment text, when the comment was posted, and who posted it.
Individuals can post a story or comments for an already existing story. If the individuals choose to register themselves as JavaEdge members, any stories or comments posted by them will show the name they provided during the registration process. If they do not register as the JavaEdge members, they can still post stories and comments, but their name will not appear next to the story. Instead, the story will be posted as from a anonymous user.
Users can register to become the members of the JavaEdge community by providing some simple information (such as name, e-mail address, user-ID, password, etc.)
A user can search all the stories, posted on the JavaEdge web site, using a simple key word search engine. Any hits found by the search engine will be displayed as a list of URLs
The application code for JavaEdge is relatively sparse because the authors wanted to focus more on the underlying open source frameworks than building a full-blown application. In addition to demonstrating the capabilities of the Jakarta Java development frameworks, the application will illustrate some basic design principles that will ensure the long-term maintainability and extensibility of the JavaEdge code base.
Not every application developer needs to be an architect. However, all application developers need to have some basic understanding of software architecture. Otherwise, it is easy to make common design mistakes, which form into antipatterns that can make code difficult to support and extend.
This chapter has identified six common antipatterns that often spring up in web-based application development. These antipatterns are:
Along with descriptions of these antipatterns, general solutions to these antipatterns were discussed. A common theme that has formed throughout our discussions of solutions is that JOS development frameworks offer a structured mechanism to develop applications and minimize the amount of infrastructure code being written. Developing an application framework is an expensive proposition. Open source frameworks have the advantage of being:
We also discussed the requirements of the JavaEdge Application that we are going to develop in this book.
The rest of this book will demonstrate the technique to use the following open source frameworks to refactor the antipatterns discussed earlier:
After reading this book you should have: