Chapter 1

J2EE in Practice

In this chapter:

1.      You will look at various issues to address in during different phases of a J2EE project

2.      You will look at characteristics of a successful J2EE project

3.      You will look at step-by-step approach to J2EE project execution 

 

Welcome to the real world! Understanding J2EE technology is one thing. Applying it effectively and successfully to J2EE projects is a different story all together. As J2EE has matured over the years, J2EE application server vendors have concentrated on providing a robust and scalable runtime platform for your applications. While a solid and scalable environment is a key factor, it is not the only factor affecting the success of J2EE projects. Now, more than ever, there is a need to implement projects faster, on time, on budget and relatively bug free. Most of all, they have to perform well. Remember that if the application is not designed well from the grounds up, no application server can scale it. The applications should also not hog your network. They should be maintainable and easily extensible. The list goes on. A J2EE project, like any other programming endeavor, has roughly the following phases: Inception, Design, Implementation, Testing and Support. The tough part is figuring out when in your project should you tackle these issues and take action and what are the strategies. Answering these questions form the theme of the rest of this book.

1.1 Issues to address in J2EE projects

As pointed out earlier, there are different issues to address in various phases of a J2EE project. This section focuses on the issues faced during development (design and implementation), testing, deployment and support. A clear understanding of these issues and their solutions make J2EE project execution much easier. Sometimes questions such as choice of a environment, software are already made and beyond your control.

Development-time considerations

In a J2EE project, typically you create JSPs, Servlets, other web components and EJBs in the development phase. As you develop them you try to think ahead of how your application will be used by the end user. You also think about how to make the application more maintainable. Here are some of the questions you want to address.

1.      How do I easily change the look and feel of the web application? [Templates, Tiles, CSS – Chapter 9]

2.      How can I declaratively control logging from my application? [Logging Service - Chapter 4]

3.      How do I load my configuration data without having to change my Java programs whenever there is a new set of application data to be configured? [Configuration Service - Chapter 5]

4.      How do I externalize domain objects and form validation? [Business Rules Service – Chapter 7]

5.      The case of Navigation Control Framework (Chapter 10) can be made in the following different ways:

a.      I want a declarative and automated way of controlling the navigation between pages. How do I do that?

b.      I have a long sequence of screen navigation in the workflow. I want to make sure that they happen strictly in that order. I want to prevent the end user from jumping in the middle and proceeding. How do I do that?

c.      I am currently using “conveyor belt programming” i.e. dumping data in the session and accessing it elsewhere. Business folks just decided to change this flow. Now I am not getting the data I expected in this JSP. How to effectively and easily change states and hence the navigation when the business requirements change?

6.      How do I handle when the user tries to access a previously bookmarked page out of its context? How should I handle browser refresh events? [Handling Browser events – Chapter 11]

7.      I want to reuse a set of pages in different contexts. How do I do that? [Reusing Workflow – Chapter 10]

8.      When and how do I prevent the user from doing sensitive resubmissions? When should I use redirects instead of forwards? Should I prevent the user from using the back button? If so, when and how? [Sensitive Submissions – Chapter 11]

9.      I want to do pre processing and some checks when the user accesses the JSPs. How do I prevent from directly accessing the JSPs? [Controlling direct JSP access – Chapter 11]

10.   Where do I handle my exceptions - In the JSP, in the EJB tier or in the web tier? [Exception Handling Framework – Chapter 19]

11.   How do internationalize my application? [Internationalization and Localization – Chapter TBA]

12.   What does it take to use LDAP with my application server. [Using LDAP – Chapter 13]

13.   How do I secure my application? [Using SSL – Chapter 12]

14.   How can I provide Single Sign on for the entire corporation running multiple application servers? [Single Sign-On – Chapter 14]

15.   How do I integrate various open source frameworks and get a working system? [Putting it all together - Chapter 20]

You might have many more questions that belong to this category.

Testing-time considerations

As you are developing you want to test the code that you just developed.  Since J2EE has a defined way of deploying the applications, you would want to create a WAR or EAR to deploy your applications. As you are creating the WAR you might find that ejb tier classes depend on web tier classes or the classes common to ejb and web tier depend on one of these tiers. Worse, you might even have a circular dependency. There are many such questions. Here are some samples.

1.      Why can’t I hot deploy the web application? [Deployment issues related to development – Chapter 22]

2.      How do I unit test the web application? [Chapter 26]

3.      How can I set up an incremental build process? (Doing a complete build when there are small changes in the development cycle is time consuming) [Ant Build Strategies – Chapter 23, Advanced Maven – Chapter 25]

4.      How do I communicate, collaborate the build and deployment at a higher level than Ant? [Maven – Chapters 24 & 25, Cruise Control – Chapter 23]

5.      What is the ClassLoader mechanism in J2EE and how does it affect my packaging and application partitioning? (Alternatively, Why do I get a NoClassDefFoundError or ClassCastException even when the class is present in the EAR?) [Classloader hierarchies, Application partitioning – Chapter 22]

6.      I have added new functionality to my application. How do I do the regression testing to ensure nothing has been broken? [Regression testing with Cactus– Chapter 26]

7.      When and how do I run performance test? [Chapter 26]

8.      How can I automate the performance test and collect metrics? [Collecting Metrics from Test – Chapter 26, Chapter 28]

9.      What other tests should I run to ensure my application works as expected? [Performance tests rerun, Stability Tests, Tests inside and outside the firewall – Chapter 26, Chapter 28]

10.   How I improve the response times for the JSPs? [Strategies for improving response times – Chapter 28]

You might have many more questions that belong to this category.

Deployment-time considerations

Deployment phase refers to the actual production deployment or it may refer to deployment to machines other than the developer’s computer. In the former case all the function testing would have been complete. In the latter case the QA is yet to start. In either case, the deployer is faced with the challenge of getting the application working by assembling the components. Everybody has the heard developers standard rumble “It works on my machine”. This is where the component discovery mechanism helps the deployer. Here are some of the questions that need to be addressed in this phase.

1.      How do I use plug and play components in the web application? [Component Discovery Mechanism – Chapter 3]

2.      How do I set up clusters? [Fine tuning – Chapter 28]

3.      How do I SSL-enable my application? [Using SSL – Chapter 12]

4.      How do I tune my deployment process so as to reduce the downtime to a minimum or possibly eliminate it totally? [Chapter 22]

Obviously most of the issues here are vendor specific and you will have to refer the vendor manual to implement them. Where possible, however we will provide general pointers throughout the book to make the deployment as smooth as possible.

Until now, you had a glimpse of various issues to be addressed in different phases of the project from a developer and architect’s point of view. There are other concerns which stem from production point of view. These concerns are highlighted in the next section under Operational considerations since they span the entire project lifecycle but have to be addressed by the project developers and architects.

Operational considerations

Now that the system is deployed in production after all the hard work, you can relax only if you have built a fool proof system and addressed the following issues well in advance.

1.      What kinds of outages are possible? [Exception Handling Framework – Chapter 19] For each of these outages:

a.      Do the operations get notified when there is an outage? [Exception Handling Framework – Chapter 19]

b.      How do the application components respond to the outage? [Chapters 19 & 27]

c.      Is there a data loss due to the outage?

d.      Do users get meaningful error messages during the outage? [Chapter 19]

2.      I am seeing some problems in production. I had turned off logging in production for performance reasons. How do I turn on logging when the production server is running? [JMX Configurator for Log4J – Chapter 4]

3.      How do I monitor the application and provide proactive customer support? [Chapter 27]

4.      What is the degradation under peak load if one or more servers in the cluster fail to respond? [Chapters 26 & 28]

5.      Can the software versions be upgraded without requiring significant application rework? [Chapter 3]

6.      How stable is the environment?

7.      The web application uses too much bandwidth. How do I control it? [Bandwidth usage analysis – Chapter 28]

8.      I did not expect so many users. The system is not scaling. [Capacity Planning – Chapter 29(Tentative), Fine tuning – Chapter 28]

9.      Customer has reported a problem. I have no mechanism to track it or reproduce it. The production logs are huge. What can I do? [Tracking Activity with Logs – Chapter 27]

10.   My manager wants a report on the success rate of a new promotion. How do I figure out how many users are positively responding to the promotion [Web site analytics, JMX – Chapter 27]

11.   I am developing the web application in addition to maintaining the released version. What are the best practices in Configuration Management that I can apply to make the release and maintenance procedures smooth and simple [Best Practices in Configuration Management – Chapter 25]

1.2 Characteristics of successful J2EE projects

 Now that we have looked at the issues you have to address in a typical J2EE project, its time to look at the characteristics of successful J2EE projects.

Framework based Design

The first and foremost factor influencing the success of a project is frameworks. Simply put, frameworks are tried and tested code for the recurring tasks in everyday programming. Every J2EE project involves doing the same tasks over and over again. Such tasks are refactored as frameworks to take the burden off the developer’s shoulders. Frameworks aid in designing applications using well-known object oriented principles rather than quick and dirty implementation. With frameworks you have to take a disciplined approach to development and obviously there is a learning curve.

Frameworks can be roughly classified into two categories based on their origin. First, there are Third party frameworks. Several such frameworks have evolved over time both in the commercial and open source domains and have been successfully used by the Java community. The second category of frameworks are the ones you develop in-house. A question immediately arises that if frameworks are available off the shelf, why develop them in-house after all? Well, each business is different in its own way and not everything can be generic enough to warrant a generic off the shelf framework. Every project encounters this situation more or less. 

While projects of any size can reap benefits from off the shelf framework, small projects will find it hard to realize value with in-house frameworks. Development of any framework needs a lot of time and effort, since the framework has to be generic enough within the project scope. Small projects don’t have that kind of time and resources at their disposal. Moreover it takes a while before the time and money spent in developing the framework can be recovered elsewhere – generally possible in medium and large projects. It is doubtful if any medium to large project can be successful without appropriate frameworks. Part II of this book is devoted to developing frameworks and integrating them with various open source frameworks and laying the foundation for a complete the front-end story.

Plug and Play Components

In addition to providing Application Programming Interfaces (APIs) that increase developer productivity, frameworks also provide Service Provider Interfaces (SPI) that lets the plug and play modular deployment mechanism. It is up to the developer to use the frameworks in such a way that plug and play components are possible.

Thinking about Performance

Impatient users are one of the new challenges posed by the web and the high-speed Internet. If your site does not respond fast enough, your competitor’s does. It is unfortunate that performance takes back seat in many web projects, a situation that may be too late to address if performance is only treated as an afterthought. Remember that the frameworks and technologies that you choose can affect performance. If you are using a framework that is using too much of Java Reflection API, chances are it will be a bit slower. 

Another scenario of performance bottlenecks is the incorrect use of Entity EJBs. For instance, if you application is a online retailer for books, then it does not make sense to implement the “Book” domain object as a Entity EJB with Container Managed Persistence(CMP). The “Book” is a read mostly entity and is seldom updated. Often EJB containers provide the option of deploying the same EJB as read-only objects and can be used as an alternative, but is vendor specific. If your application is a read mostly system and you use Entity EJBs with CMP, the unnecessary transactions will bog down your system. A better alternative is to use Session EJBs and Plain Old Java Objects (POJO), optionally an object-relational (O/R) mapping framework like Hibernate and a caching mechanism.

The performance figures are driven by the business factors. The architect should get input from business experts about the usage pattern and from system folks about the hardware budget to plan the resources to handle that load and select the technologies and frameworks to handle the anticipated load satisfactorily by running various mock tests.

Performance tests help in the following way:

1.      To identify bottlenecks and optimize the application in an environment similar to production

2.      To detect errors those occur only in multi-user environment.

3.      To provide inputs to fine-tune system capacity

4.      To uncover potential threading problems

5.      To measure response times under average and peak load.

As we gloss over in the next sections and detail in Chapter 3, the performance figures (for e.g. response time) decided at the project inception should drive other project activities like capacity planning, framework selection etc. In Chapter 13, we will use Grinder – an open source performance-testing tool to gather the metrics for ABC Bank.

Designing for scalability

Scalability is somewhat related to performance. However, it is quite possible that your system will show good response times, but still might not scale well when the number of users increase and the response times will degrade. A small percentage of degradation is unavoidable. However a large degradation points to a faulty code, faulty design or faulty architecture. Chances are that there are memory leaks, unreleased resources or other reasons. What is important is that performance metrics when run in isolation are not relevant. The performance figures under load are the real measure of the strength of your application.

In addition to the initial performance tests run by the architects for evaluating hardware and frameworks and technologies, the developers should run limited amount of load testing on the use cases they design. In our experience, because of tight project deadlines, developers tend to think of it as “If it works without defects I have hit the deadline” and these tests are never run. The technical folks in the project should educate the management about the importance of these tests. If these tests are not run early enough, the performance and scalability bottlenecks will come back to haunt later in the project with costs multiplied. When it comes to performance tests, the bottom line is “the earlier, the better”.

Thorough Testing

Who wants a system as fast as a bullet but throws NullPointerException every now and then? Your system has to robust and reliable from a functional perspective too. It is no wonder that less than 50% of the project costs are linked to design and development. The real measure of a developer’s productivity is delivery of modules with as few defects as possible. While it is not feasible to build a completely defect free system, it has to be relatively defect free.

In the recent years several open source frameworks have sprung up. JUnit is one of the important frameworks that help in unit and regression testing. Several testing frameworks exist for web applications too (e.g. Cactus). Some of them are even specific for frameworks (e.g. StrutsTest). Best of all they are open source. You can even integrate them with Ant (the de facto build tool from Apache), so it will run automatically after the daily builds to verify the functionality. As you will notice coding the tests takes time and effort but will save a lot of time and money down the line. It’s time management caught up to the concept that even tests are deliverables. When it comes to unit tests, the bottom line is “test early, test often”.

Automation

Every project has core models or repositories that drive various artifacts and executables. For instance, UML models in Rational Rose describe the analysis and design models. You can generate the Java code for EJBs, servlets and normal Java classes from the models. Maintaining a unified repository lessens the chances of various project personnel getting out of sync.

In Chapter 10, we will develop a Business Rules Service and store the business rules in a XML repository. At runtime the XML gets loaded as Java objects and can be used to run business validation. In addition, Java code can be generated from the XML during the build process and can be used at runtime. In Chapter 14, we will use Rose script to generate XML for web navigation control from a Rose Activity diagram for JSP state transitions.

1.3 Effective Planning

Planning is key to success of a project. Planning starts right from the inception and occurs in bursts till the end of the project.

Requirements Planning

This planning phase occurs immediately after the inception of the project and is driven by the business experts and stakeholders. The scope and usage of the application is decided in this phase. The various parameters to be met by the project like response times are decided here. The parameters regarding the size of the user community such as average and peak concurrent users, average and peak active load are also forecasted.

For instance, here is the usage pattern forecast that came out of requirements planning for ABC Bank. Majority of the customers are individual users. Roughly 50% of the depositors also apply for mortgage loans with the bank. The volume of users is expected to be high in the morning between 9:00 – 10:00 am and also high in the evening 7:00 pm – 9:00 pm with a peak load of 500 users and 250 average users. The application is read mostly with users viewing transactions in their accounts. The users applying for loans perform read–write operations and load is constant throughout the day. Usage pattern will let us characterize of load and serve as input for deployment planning. It will also serve as input for architecture planning.

Performance and Architecture Planning

The phase is immediately after the requirements planning phase and is driven by the inputs from the requirements planning. The application architect plays a major role in this phase. The application architecture and underlying technologies are decided in this phase, given the usage patterns, response times and user loads.

For different kinds of performance and usage patterns, different combinations of technologies have to be chosen. For instance, if the web application is read mostly, then using a cache will really boost the application. If the application is more of write, then the usage of caching itself can be a bottleneck because of the traffic generated between the servers in the cluster when each write happens. For smaller loads using plain servlets and DAOs will suffice. For larger loads using Session EJB s along with normal java objects mapped to data through an O/R tool is a good solution. For read write transactions with a stress on writes, Entity EJBs are a good choice. For batch updates, batch reads, JDBC or stored procedures is the good approach. Each approach has its pros and cons. A particular approach may be very fast, but its maintenance cost might outweigh the speed in the long run. It is matter of trade off and careful choice depending on what is important to the business and the usage pattern of the application and forecasted user load.

Acceptable response time for average load and allowable degradation in response times acceptable to the business are also agreed upon in this phase. For instance, the average response times for average load of 250 users is 2 seconds and handle a peak load of 1000 users with a 15% degradation in response time. The response times have to be state in average and max. But max can get way out of bounds falsely showing a large deviation. Hence 90th percentile of max response time can be considered as the max response time.

Deployment and Capacity Planning

Depending on the architecture chosen in the previous phase, performance figures agreed upon and allowed degradation, appropriate hardware, infrastructure and software have to be chosen and bottlenecks have to be addressed.

Hardware includes Web Servers, Application Servers, Load balancers, monitoring tools etc. Infrastructure includes network capacity, bandwidth for Internet traffic.

Bottlenecks come in forms of open sockets from web servers, application servers, and database connections. There are other bottlenecks like heap size, waiting queue for servicing its request, ejb pool and servlet threads. It is important to remember too much is not always good. Big pool size will put overheads in terms of memory to maintain it, more garbage collection to be done and so on. Clustering is often chosen to provide fail-over and balance the load. Application Servers and cache synchronization frameworks using clusters have a lot of traffic between them and can impact the performance of the application itself and also require a larger LAN capacity.

1.4 Step-by-step approach to J2EE project execution

Now that we have looked at the issues in J2EE projects and characteristics of successful J2EE projects, it is time to look at steps to execute a J2EE project successfully. Here is a list that provides a high level overview of the steps involved in a J2EE project execution. All the steps in this section are in the logical order in which they will be carried out.

1.      Decide on the usage pattern, customer community, performance metrics and load size.

2.      Decide the technologies from the J2EE spectrum and corresponding tools, which in combination will solve the business problem and meet the requirements in 1.

3.      Decide and budget for the hardware and infrastructure to support the projected load and technology selected.

4.      Choose the UML tool (White board, Visio or Rational Rose depending on your budget or ArgoUML).

5.      Choose the IDE based on the features important for your project and availability of third party plug-ins to accelerate the developer productivity throughout the project cycle. More and more IDEs have UML features integrated. With such a tight coupling, round trip engineering becomes easier.

6.      Use an application services framework for configuration, Logging etc. for generic infrastructure tasks. Use off-the-shelf or build one if required.

7.      Choose web tier presentation framework(s). Develop extensions to the presentation framework if needed.

8.      Build a Navigation Control Framework to effectively control the user navigation in a stateless web environment.

9.      Decide on how and where you will handle the exceptions and how you will notify operations and take action.

10.   Partition your application based on functionality and tiers. Plan your deployment and packaging based on application partitioning.

11.   Develop an incremental and milestone build strategy. Keep in mind the deployment scenario when you develop build scripts. Try to maintain similar deployment structure in development and deployment. Pre compile your JSPs.

12.   Develop back end framework if needed.

13.   Start the development from back to the front. After the initial set of EJBs for the first usecase (i.e. if you chose them. Any other kind of back end code is fine) are developed, test them using JUnit/Cactus scripts.

14.   Develop Business Delegates or dynamic proxies to invoke the back end. This way you can isolate the back end implementation from front-end controller, model and view. Sample functionality in Business Delegates includes handling of RemoteException and adapting it to the presentation tier.

15.   Look again at the usecases and enhance the frameworks

16.   Develop the first usecase as proof of concept and demo purposes. (Management wants to see the first tangible deliverable early on for gaining confidence)

17.   Come up with test cases and test the usecase end to end.

18.   Run profilers to get rid of leaks and loitering objects.

19.   Deploy the developed usecase using the build tools.

20.   Check if the packaging has to be changed.

21.   Run performance tests and benchmarks. Tweak the JVM, application server and rerun. The metrics might surprise you. If it is an Internet system, be sure to test from outside the firewall.

22.   If the performance figures meet the business expectation, it is a green signal; else it is time to revisit the system or choice of technologies. For instance, if you have designed your List/View by using EJB finders, it is time to change them.

23.   Assuming that the direction is right, analyze the metrics on CPU usage, bandwidth usage and tune the system again if necessary.

24.   Most of all let you user community use the application and get their initial inputs. Don’t plan a big bang release.

25.   Instrument your application components using JMX for easier management.

1.5 Summary

At this point, you should have a good understanding of issues involved in real world J2EE application development and how it differs from understanding the technology as such. The business logic implementation rarely fits any of the design patterns perfectly. Real world J2EE development needs careful attention to details and processes. You saw the characteristics of a J2EE project and a high level overview of steps involved in making J2EE project successful. In the rest of this book we will address almost all the issues we raised in the beginning of the chapter.