Develop complete J2EE solutions with an eight-step cycle
In the commercial world, we use Java 2 Enterprise Edition (J2EE) to solve business problems, to develop commercial software, or to provide contract services to other businesses' projects. If a company wants to build an e-business Website using a multitiered architecture, it usually involves managers, architects, designers, programmers, testers, and database experts throughout the development lifecycle.
For different parties to work efficiently and effectively, they often need a software development process. Some classic development processes include the waterfall model, rapid application development (RAD), and extreme programming. In this article, we will focus on a popular software engineering process, the Rational Unified Process (RUP). RUP provides a disciplined approach to assigning tasks and responsibilities to different roles. Its goal ensures we produce high-quality software that meets user needs within a predictable schedule and budget.
I like to use RUP for J2EE development for three reasons. First, RUP is architecture-centric; it develops an executable architecture prototype before committing resources for full-scale development. Second, RUP is iterative and component-based. The architecture baseline often includes a framework or infrastructure to facilitate adding components through iterations to customize and extend a system's functionality without affecting the rest of the system. Third, RUP employs an industry-standard language, UML, to visually model a system's architecture and components. RUP has four different development phases: inception, elaboration, construction, and transition. This article, however, covers eight essential activities involved in J2EE development from a technical perspective in a manner that maintains the architectural focus.
I. Requirements analysis
The requirements analysis describes what the system should or should not do so that developers and customers can create an initial business contract. You can document functional requirements in business concepts, domain glossaries, use cases, and user interface (UI) mockups. Nonfunctional requirements, such as performance and transactions, you specify in a supplementary requirements document. You can create the high-level UI mockup on paper or in HTML, depending on how deeply you are involved in the project.
Figure 1 shows two sample use cases of a typical e-business system. The viewOrder use case tells us that a user logs into a system through a Web interface, sees an order list, and clicks a link to view order details of a specific purchase order. The addLineItems use case tells us that the user browses a product catalog, selects interesting products, and adds them to a purchase order.
Figure 1. Order use cases
II. Object-oriented analysis
Analysts generate problem domain models: classes, objects, and interactions. Your analysis should be free from any technical or implementation details and should contain an ideal model. Object analysis helps you understand the problem and acquire knowledge about the problem domain. You must maintain a pure domain model without technical details because a business process changes much more slowly than information technologies.
These first two steps -- requirements analysis and object-oriented analysis -- are not J2EE-specific; they are quite generic for many object-oriented methodologies. Figure 2 shows a high-level object analysis model of a pet store sample application. It illustrates the major concepts we identified from requirements analysis use cases. We model these concepts into objects and identify their relationships.
Figure 2. Higher-level analysis model: The pet store domain
The result of requirements and object analyses is the entry point for J2EE architecture development. To develop an architecture, you select a vertical piece -- often a critical part, such as the order domain object model -- for object design, implementation, testing, and deployment. (A vertical piece, an RUP concept, is a small portion of a system. The starting point is a subset of use cases, as shown in Figure 1, and domain analysis models, as shown in Figure 3. The implementation of a vertical piece results in a fully functional mini-system including all the tiers, such as UI-tier JavaServer Pages (JSPs), middle-tier business objects such as Enterprise JavaBeans (EJBs), and often backend databases.) You can apply experience gained from the prototype to domain objects, and let that knowledge serve as a design guideline for the object design stage.
Figure 3. Detailed object analysis model: Order
III. Architecture specification
After the first two steps, the business domain problems and requirements should be clear. Now we'll focus the effort on the technical strategies and architecture. An architecture is a blueprint of all the parts that together define the system: the structure, interfaces, and communication mechanisms. We can further divide an architecture into enterprise and application architectures.
Enterprise system architecture
Enterprise-wide system architecture covers hardware and software infrastructure, network topology, development, testing, production environment, and so forth. These reflect an enterprise's long-term investment. Before development, you want to evaluate your existing software and hardware infrastructure and possibly add new components and upgrade your existing system if it cannot fully support J2EE. You need to thoroughly evaluate hardware, including computers, routers, network switches, and network topology, as they all impact system performance and reliability. Figure 4 shows a possible multitiered network topology.
Figure 4. Enterprise architecture: Network topology
A possible multitiered enterprise architecture shown in Figure 4 has the following major components:
- A Web browser client may or may not sit behind the client-side organization's firewall
- An HTTP server is the Web server known to the public. It usually sits in a subnet known as the DMZ
- Web containers host presentation and possibly business logic components
- Application containers host business logic components
- Relational Database Managements Systems (RDBMS) and databases host data and data logic
The system architecture type you use depends on your requirements for security, performance, and reliability, as well as your organization's financial situation. At the least sophisticated end, you can reasonably run a simple second-hand computer in a garage with a phone line. There are many open source operating systems, Web servers, application servers, and database management systems available through the Internet. This system type's cost would be a few hundred dollars and a few sleepless nights.
High-end customers, such as many Wall Street financial institutions, might require a system that continually supports security, high throughput transactions, and unpredictable network traffic. In this situation, you commonly need an n-tier architecture with Web servers and application servers configured as clusters for fault tolerance.
You also need to evaluate the software infrastructure, including the Web server, security management software, application server, domain name management server, database management system, and third-party software components. If you have not purchased your application server yet, selecting a J2EE vendor is an important aspect of this evaluation process. I should note that different vendors implement J2EE quite differently, and some vendors only support old J2EE versions. Additionally, some Web containers or application containers might be faster than others. Other than implementing the J2EE specification, many vendors might also sell J2EE infrastructure components or frameworks. Selecting a stable J2EE vendor who provides support is also critical. Common functionalities that you can purchase or develop at the system infrastructure level include:
- Internationalization and localization
- Clustering and object distribution
- Session management
- Application performance measuring and profiling
- Workflow management
- Portal and personalization management
- Tier-to-tier communication protocols
- Security and firewalls
Application architecture, built on top of an enterprise-wide system architecture, refers to a specific project or application. After the infrastructure is complete, the architect studies how to build a specific application. If your enterprise architecture only partially supports an old J2EE version, you might first upgrade your system. If you cannot upgrade due to budget or timing concerns, then you may have to work within the technical constraints associated with older versions. While it's important to build enterprise-wide reusable components, you first must be able to use in order to reuse. The ultimate goal here is to satisfy customer requirements -- one project at a time.
An architect is not a designer; architecture and design are two different things. An application architecture's scope is the system's major structure, its architectural design patterns, and the frameworks upon which you can add components. The architecture's major concern realizes nonfunctionality, whereas design is concerned with the business use cases you apply to convert the domain object model into a technical object model. Application architecture is the project's structure, a particular application. Common application architecture decisions you must make through application architecture development include:
- Functionality partition between tiers
- Model domain objects
- What legacy system to save
- What software components to buy
- What components to build
- How to integrate third-party components
The order domain objects in Figure 3 demonstrate how you can model domain objects. With current Java technology, you could distribute domain objects among Web containers as developer-managed persistent objects, EJBs in the application server, or as RDBMS-hosted Java stored procedures.
In the BluePrint pet store, we design the order object as an entity bean, a detail object, and a data access object as shown in Figure 5 and later in Figure 6. When you see this, you should realize its architectural significance. Ask why a domain object in an analysis model maps into so many objects. Ask what would happen if you change the design. You might have heard good things about EJBs, but be aware that the performance of different vendor implementations varies. When a new technology comes along, you need to research and perform hands-on work before plunging into a full-scale design effort. You can often apply the lessons learned about designing and implementing the domain object model's vertical pieces to the design of many other domain objects. This is what architecture development is about.
Figure 5. Order object design model
In the early J2EE days, some object-oriented designers tried to map domain objects into entity beans and pass them across tiers. They obtained nice UML diagrams, but the result was a slow system due to unnecessary network traffic. To go from object analysis directly to object design without architecture development, without clearly understanding a new technology, almost always leads to project failure.
As J2EE architecture is a relatively new topic, the deliverables for a J2EE architect are not well defined. From the pet store sample application, it is difficult to see where architecture stops and design begins. The document begins with a high-level examination of the application architecture, a discussion of the Model-View-Controller design pattern, and an architecture overview. The low-level documentation is available in the source code. There are no UML diagrams. The assignment part of Sun's J2EE Enterprise Architect certification requires all deliverables to be in UML. However, the marks only distribute into one class diagram, one component diagram, and a few object interaction diagrams. These are far from sufficient for real-world J2EE applications. To get started, the architecture specification and process requires at least the following:
- A system architecture document to describe your existing hardware, software, network topology, and other components
- An application architecture document to describe the application's major structure, including a logical view of all architecturally significant components, use case components, and legacy components
- A new components design guideline to describe all design guidelines and architectural decisions, explain all those decisions, and describe possible consequences if an alternative option is used. These guidelines should capture all important base determinants that the new component design must respect to maintain the system's architectural integrity
- A working architectural prototype to evaluate new technologies; gain experience developing and deploying J2EE applications; build architectural frameworks; address risks by measuring performance, scalability, and ease; as well as prove to project stakeholders that your approach works
After you develop several J2EE solutions and gain more experience, the prototype becomes less important and a few UML diagrams and some design guidelines may be sufficient.
IV. Object design
Guided by architectural specifications, the design technically expands and adapts the analysis result. While domain object modeling at the analysis phase should be free from technical details, the object design fully accounts for technical factors, including what kind of platform, language, and vendors are selected in the architecture development stage. In analysis, you keep your eyes on the stars, but at the design phase you put our feet on the ground. Theoretically, you shouldn't tamper with business objects unless absolutely necessary in order to maintain their basic properties and behavior.
Guided by architectural decisions, a detailed design effort should address specification of all classes, including the necessary implementation attributes, their detailed interfaces, and pseudo-code or plain text descriptions of the operation. The specification should be detailed enough so that, together with model diagrams, it provides all the necessary coding information. In many automated software production processes, you can generate code skeletons from object-oriented diagrams. Figures 5 and 6 illustrate a high-level and detailed object design for a few domain objects. Note that the stubs and skeletons are not usually shown in diagrams as they are transparent to the designers and programmers. I've included them in Figure 6 to illustrate EJB basics.
Figure 6. Object design model: Order EJB detailed design
After you finish the detailed object design, you complete the object-relational mapping of domain objects. The reason for this is that although object-oriented methodologies are pretty advanced now, the most popular and mature persistence stores are relational. Additionally, a customer's IT infrastructure in many cases already reflects existing investments and preferences for commercial RDBMS vendors. So converting domain object models into relational models, or database tables, is very important. There are many container-managed persistence tools, but they cannot replace a good relational database design.
With a good architecture and detailed design, implementation should be a clear task. Additionally, because we designed and implemented a vertical piece of the system in the architecture prototype stage, fewer surprises should exist in the implementation stage. In many organizations, developers often arrive at the implementation stage too early. This problem is exacerbated when managers peer over developer shoulders to ensure they're writing code since, to them, anything else wastes company time.
As a result, instead of drawing UML sketches in hours or days, ideas are often tested concurrently with code development, which may take weeks or months. Since, in such circumstances, all the architectural decisions and design are made during coding time, discovering that development has moved in the wrong direction often takes several months.
Validation consists of testing to verify that the system works as designed and meets its requirements. The validation process occurs both in the development and production environments throughout the development lifecycle. Unit testing, integration testing, and user acceptance testing are important subjects unto themselves.
VII. Assembly and deployment
Component assembly and solution deployment is especially important in J2EE development. The development and production environment could be quite different. If EJBs are in the system, you need to produce container-generated classes using vendor-specific tools since, as I pointed out previously, Web or application component configuration could vary with different vendors. You must also consider whether the system to be deployed has any vendor-specific code implementation. In an extensible architecture, the system structure should be stable but should also support incremental deployment of new or old components without affecting the whole system.
VIII. Operation and maintenance
During the final stage, the application is in the hands of its users, for whom you must provide training, documentation, and education. Users will find bugs and might request new feature improvements. You must handle these through proper change management procedures. You don't need to shut down a working system in order to deploy a new component or replace an old component.
Architecture development process
Knowing we must make many architectural decisions, we must now figure out a process for architecture development. For an enterprise, there are usually many application projects, some of which could span several years, resulting in system evolution encompassing many cycles. Many common requirements exist across many projects in your domain. You should easily reuse an extensible and reusable architecture in a previous project cycle later in its lifecycle or in other projects. There is a need for common frameworks, reusable software architectures that provide the generic structure and behavior for a family of software applications.
If this is your first J2EE project, your architecture must be prototyped, tested, measured, analyzed, and then refined in iterations. BluePrints provides many good design guidelines and best practices, and the pet store sample application serves as a nice reference architecture. The most efficient way to deliver good solutions quickly but with high quality is to embrace and extend the BluePrints reference architecture and then plug in your own business components. The last thing you want to do is reinvent the wheel.
Embrace a reference architecture
To my understanding, the essence of the pet store architecture is the Model-View-Controller and the Command patterns. You can apply these patterns to both Web-centric and EJB-centric systems. For each domain object, a view is represented as nested JSPs. A controller handles related business events, and domain objects encapsulate business logic, transactions, and security. We use the front door servlet as the central controller to receive and intercept all user gestures. It dispatches business events to specific domain object controllers, which call domain objects to change persistence states. Depending on this event handling's result, a controller selects the next view to display. The following are architecturally significant components that we can modify and use for most J2EE applications:
- MainServlet. Front door component, interface between the Web container and this framework
- ModelUpdateListener. Interface for objects interested in getting the model update events
- ModelUpdateNotifier. Notify listeners when the update model event occurs
- RequestProcessor. Processes all requests received from the MainServlet
- RequestHandler. Interface for plug-n-play request handler components
- RequestHandlerMapping. Contains request handler mapping rules
- RequestToEventTranslator. Central request handler delegates request handling to plug-n-play request handling components according to request handler mapping rules. Translates http requests to business events
- EStoreEvent. Business event
- ShoppingClientControllerWebImpl. Proxy-to-EJB tier front door controller
- ScreenflowManager. Controls screen flow, selects views
- ModelUpdateManager. EJB tier model update manager, notifies what models are changed due to an event
- ShoppingClientControllerEJB. EJB tier front door, provides remote service to EJB clients
- StateMachine. Central event handler, delegates event handling to plug-n-play handler components according state handler mapping rules
- StateHandler. EJB tier state handler interface
- StateHandlerMapping. Contains state handler mapping rules
Extend the reference architecture
While the BluePrints sample application is a good starting point, you should modify it for each project or domain. Design patterns are reusable microarchitectures that you can use to extend the reference architecture. BluePrints, which provides a useful J2EE patterns catalog, and the 23 "Gang of Four " patterns are both excellent resources. For example, if you want to extend the reference architecture to support workflow management, you could dynamically register event handlers with the central controller at deployment time or runtime. The central controller asks each event handler registered to handle an event until a handler returns a message to indicate the end of the command chain.
Plug in your business components
The J2EE technology is the same for everybody, but the problems we try to solve could be quite different for diverse domains. Once you establish a basic J2EE framework, you must then realize a few use cases to show that the architecture actually works for your domain. You do this by selecting the scenarios, which capture the system's critical functionality, that are used most frequently and present significant technical risk. Starting from the domain analysis model, you then try to map your domain objects into high- and low-level design models just like we did in Figures 5 and 6. Implement the low-level design models and test it to see if they actually work. If everything works as intended, begin the next iteration by reassessing the risks, extending the scenarios to consider, and selecting a few more scenarios to extend architecture coverage. After a few iterations, the initial architecture prototype should become stable. Identify what components you can purchase, what legacy systems you should preserve, and how you can interface them. The next step is software design, where you can continue development using similar methods and processes as specified in the design guidelines.
Step by step
We use a process to divide a complex problem into smaller ones so we can more easily understand and solve them. In this article, we divided J2EE development into eight steps, focusing tightly on architecture and design. I've addressed important architecture topics and presented a process for making architectural decisions. I also discussed the roles and deliverables of a J2EE architect.
Learning to develop J2EE solutions using these steps is much like learning the steps to a dance. You first need to practice the basic movements consciously and diligently. But once you are more familiar with them, you want to put them all together and focus more on the size, speed, flow, and rhythm of each step in a specific context. But you should never let a process limit creativity. Instead, embrace and extend the process to fit your particular needs. Remember, your ultimate goal is to deliver a complete J2EE solution that satisfies your customer's requirements.
Jian Zhong, a senior software architect with ActioNet Inc. has been actively involved in J2EE architecture development for the last two years. He started Java programming in early 1996 and has been a Sun Certified Architect for the Java 2 Platform since October 1999 and a Sun Certified Enterprise Architect for the J2EE Platform since November 2000. Jian would like to thank Lindsay D. Ridgeway for in-depth discussions on many architecture topics while working in the CTO Group at SpaceWorks Inc. He would also like to thank Jeffrey D. Abish and Elisabeth A. Kinner for help in reviewing this article.
Learn more about this topic
- J2EE BluePrints, including design patterns catalog and the pet store demo architecture overview