
Java Enterprise Edition platform
The Java Enterprise Edition platform is nothing more than a set of API specifications that act as building blocks that you can use to build enterprise applications.
Note
With its most recent release, the name of the Java Enterprise Edition platform has been simplified.
Instead of being called the Java 2 Platform, Enterprise Edition (J2EE) v1.5, the version up from J2EE v1.4 is now labeled Java Enterprise Edition 5 or Java EE 5. It is incorrect to abbreviate this name as 'JEE'.
The main drivers for this change are a desire to do away with the '2', which really was beginning to lose its meaning anyway; and to provide center stage to the word 'Java', which is the core technology underlying the different platform editions.
While this may seem like just a rebranding decision, there are some real issues associated with it. Firstly, you need to be aware that you might come across JARs named j2ee.jar
and javaee.jar
and will need to know which one to pick. Secondly, you need to remember that this is more like deprecation, rather than a replacement, that is, most people will continue to use the term J2EE long into the future - on resumes, job requisitions, design documents, and on blogs.
An 'enterprise application', just by the sound of it, seems more forbidding than plain old 'application'. It is therefore interesting to look at what exactly makes an application, an 'enterprise application'.
What is an enterprise application?
To help us see the difference here, let us consider prototypical examples of both types of applications. A representative 'application' might be the standard personal finance management applications, such as Microsoft's Money™ or Intuit's Quicken™. A prototypical 'enterprise application', on the other hand, would be an online banking system.
Both applications are fairly similar in that you can view the transactions for one or more accounts, transfer money either into or out of an account, schedule bills that come due, and you can reconcile your checkbook based on statements. In addition, you may also have the ability to run reports on amortization tables, spending patterns, or transaction histories.
So what makes one an enterprise application and the other not? The essence of an enterprise application can be boiled down into four concepts—simultaneous users, highly performant systems, heterogeneous environments, and a distributed nature.
An enterprise application is expected to be used simultaneously by more than one user. In fact, such applications are often expected to be accessed simultaneously by hundreds or even thousands of users.
This adds complexity as you now need to apportion system resources across these users. In addition, you must also ensure that one user does not interfere with the operations of another, even if they happen to be working on the same data.
An enterprise application is one where there is usually significant potential for loss if its users are unable to access and use it in a predictable manner. This encompasses the concepts of availability, reliability, and scalability.
An online banking application has to be available when the customer needs it, irrespective of the time of day. It has to function reliably when used by that customer and should be able to handle higher peak loads over certain periods such as major holidays like Christmas or the periods when paychecks are deposited by employers.
A failure on any one of these criteria results in a loss of customers, a loss of revenue, or both.
While these characteristics are equally important to non-enterprise applications, the impacts of failure are often much less dramatic as such applications are generally designed to be used either by a single user, or by a very small set of users.
A typical enterprise application has very little control over its destiny. Most often it is cobbled together from various collaborating systems, many of which have been in operation for a number of years (or decades).
An enterprise typically already has a significant investment in terms of software, hardware, staffing, and infrastructure in its existing legacy systems. By necessity, any new development needs to play nice with these. This may include software systems (such as Enterprise Resource Planning systems, Custom Relationship Management products, and mainframe systems), operating systems, data sources (such as IMS, Oracle, and SQL Server), application servers (such as WebSphere, WebLogic, and JBoss), communication protocols, and data formats. An ability to integrate nicely with these disparate technologies is the hallmark of an enterprise application.
A point of note is that one of the most significant investments that an enterprise makes is in its data. Most of the time this investment is locked within silos throughout the enterprise, making the task of turning it into useful information a very daunting one. Most enterprise applications have, as their central focus, the ability to access this shared data, freeing it from the grips of traditional systems.
On the other hand, non-enterprise applications are fairly standalone entities. For instance, installations of Microsoft Money never need to deal with the issues of application or system integration, or with the issues of integrating data from multiple data stores.
The only real complexity often arises from data transfer format requirements. For example, personal finance software will typically download transaction data from financial institutions using either the Open Financial Exchange (OFX) or the Web Connect (QFX) formats.
An enterprise application rarely runs on a single computer host. This is almost always necessitated because of performance and scalability, as there is a practical limit on how much work can be assigned to a particular computer; as well as of heterogeneity, since the collaborating systems may run on their own dedicated hardware.
As a result, when describing your enterprise application, you tend to speak in terms of server farms, clusters, load balancers, DMZs, firewalls, and so on.
A corollary of this fact is that portions of the enterprise application itself may be distributed across multiple hosts. For instance, the logic that determines what is rendered to the user can be separated into its own tier from that of the logic that defines the business rules for the application, and there can be yet another tier that houses the persistent data store used by the application.
It is important to note that these tiers can either be logical (when all these tiers run on the same physical machine, possibly within the same Java Virtual Machine) or physical (when each of these tiers runs on a dedicated physical machine.)
On the other hand, the typical vanilla application runs on a single workstation and is designed to serve a single user. You will be hard pressed to find a distributed implementation of either Money or Quicken.
To summarize, there are very valid reasons as to why enterprise application development is crucial to a corporation's survival - it serves as the best way to leverage your existing technology investments.
Java EE architecture
In its most basic form, the Java Enterprise Edition platform describes a set of APIs that must be implemented by any Java EE compliant application server platform. These APIs are guaranteed to be available to any application that runs on a Java EE compliant server.
The API implementations that are provided by a Java EE application server provider make it easy for a developer to focus on the business requirements, instead of having to implement infrastructural aspects of a complex enterprise application, such as having to figure out how to implement 2-phase commits to ensure that transactions work across disparate data sources.
Note
A transaction is defined as a grouping of tasks that must be either executed completely or must not be executed at all. The typical example is that of a transfer of funds between two accounts, which is comprised of two tasks—a withdrawal from the first account and a deposit into the second. If a system failure occurs between these two tasks, then data corruption is likely as the withdrawal has taken place but no corresponding deposit has occurred. The complexity of transactions in an enterprise application is compounded by the fact that the individual tasks may involve completely different database servers or other legacy data stores.
An additional benefit of writing applications based on the standard Java EE APIs is that your application is now implementation independent. In other words, your application can be deployed on any vendor's Java EE compliant application server.
In fact, a popular recommendation is to deploy applications on the reference implementation, as well as on the target application server. This ensures that you have not inadvertently locked yourself into a particular vendor's platform implementation.
However, you need to take this advice with a pinch of common sense. Vendor lock-in is not always bad, especially if you are getting something material in return (such as improved reliability, stability, or functionality). The choice of a vendor is often based on numerous factors, such as licensing costs, administrative/deployment staff expertise, and proven performance on existing production applications. As a result, changing vendors rarely happens as often as one might fear.
There are a few key features about the Java EE architecture that merit mention.
The Java EE platform is a superset of the Java SE platform. As a result, it inherits its basic advantages, such as the ability to run Java applications on diverse operating systems, its mature and flexible object-oriented programming model, its ability to work well across a network (including over the Internet), its automatic garbage collection mechanism, and its inherent multithreaded nature, all of which make for a very compelling package.
A key aspect of enterprise application development is the need to work and integrate with a variety of disparate systems. Learning the individual APIs of each of these diverse systems can be an insurmountable task. Java EE provides a solution for this problem—by separating the vendor-agnostic aspect of an interaction, the API, from the vendor-implementation aspect, termed the Service Provider Interface (SPI).
This design provides for an astonishing decrease in the level of complexity that developers need to contend with during enterprise development.
As an example, consider the Java Naming and Directory Interface API. The published API is generic enough to be used against any particular vendor implementation, whether LDAP, the RMI Registry, or even just the file system.
As a developer, all you need is to be aware of the vendor-agnostic API. You will also supply some configuration information that is appropriate for your choice of vendor such as the URL at which to access the service, authentication credentials, and the factory class for the initial context.
A service provider implements not only the SPI that defines the core service implementation, but also any abstract classes and interfaces that are left undefined in the API itself. Service providers may be linked into the Java EE platform server either statically (through configuration files or deployment descriptors) or dynamically at runtime. When multiple providers implement the same functionality, an application may choose, at runtime, which particular provider's implementation to use.
As an application programmer, you will typically use a factory method to interact with the service provider, which will return to you the appropriate instance, which implements an interface within the Java EE API. Your application interacts with this generic interface using the functions defined by the API and is completely oblivious to the specific implementation class.
This basic theme is repeated over and over again within the Java EE.
The Java EE platform is designed around a containment hierarchy, where an application server hosts containers, each of which in turn hosts components.
A container is responsible for configuring its components based on the deployment descriptor, allowing component behavior to be controlled using configuration rather than code. For example, a deployment descriptor may specify that a particular Enterprise JavaBeans method may not be invoked unless the user belongs to a given security role.
It is also responsible for managing the life cycle of its components. For instance, a servlet container will load the servlet class, instantiate it, call its initialization method, will repeatedly call its service method as requests come in, and will finally call its destruction method when it is being taken out of service.
The container is also the gateway through which its components may access their runtime environment. It is also the intercessor when one component needs to communicate with another Java EE component. This intercession allows the container to add value by transparently propagating transactions, implementing security checks, and so on.
This container-based architecture provides an effective way of providing a separation of concerns. The deployed components can now focus on the business problem being solved, whereas the container can provide the plumbing and infrastructure required to make everything work.
Each platform vendor must implement these containers so as to maintain the contract with its components as specified in the appropriate API specification. While this does not stop the vendor from providing additional services through the container, it does ensure that each component can be guaranteed to find a baseline set of services, irrespective of the particular vendor implementation that it is deployed into.
The Java EE specification defines four types of containers.
An application client container provides the runtime environment for Java programs (either graphical user interface based or command line) that execute on a client workstation. Application clients are the same as standard Java SE applications, so no special life cycle calls are made by this container.
An applet container contains applets that typically execute natively within a browser or through the Java Plug-in product.
A servlet container hosts Servlet API and JavaServer Pages API components, which are used to service HTTP requests from web clients.
Finally, an Enterprise JavaBeans (EJB) container hosts EJB components, which houses the business logic that is usually found in the middle tier of a Java EE application.
A typical servlet container (such as Apache Tomcat) will, among other things, allow a developer to package a web application as per the Servlet specification. It will load the appropriate servlets as necessary, will invoke a servlet's lifecycle and service methods, and will provide the servlet instance with access to information about its operating context.
Similarly, an EJB container will provide its contained components (Enterprise JavaBeans) with services for security, transactions, instance pooling, and so on.
A container is usually controlled through configuration files, such as Tomcat's server.xml
file.

This figure summarizes the concepts that we've introduced so far—the distinction between the API and the SPI, the Java EE containers, and the component model. The specification of the platform is comprised of the specifications for multiple containers. Each container is responsible for hosting its own component model. The components for each container expect certain services to be provided by their container.
The face that services expose to components is defined by the service's API. The vendor implements each service by providing code that implements the SPI, the abstract classes, and interfaces that are defined by the API.
Finally, a deployment descriptor may be used to configure the container's services and runtime environment, as well as to define how the components are deployed into that service.
The Technology Compatibility Kit (TCK) is a set of tests that allow you to validate the compliance of a container implementation with its specification.
The Java EE platform uses a component-based development model. This is different from a class-based model as a component typically consists of more than one class cooperating to achieve some reusable unit of functionality.
A Java EE application is built by assembling multiple such standalone components and deploying them with their configurations into their associated containers.
The power of Java EE comes from the fact that components can be independently developed, tested, assembled, and deployed into any Java EE compliant vendor's server implementation.
Each container can deploy its own unique set of components. The application client container can contain application client components, which are standard Java programs. The applet container contains applet components. The web container contains web components, such as JSP, Servlet, Filter, and event listener components, whereas the EJB container contains enterprise bean components.
Application logic typically resides in the components, and business logic usually resides in the enterprise bean components.
In this book, we will primarily focus on the servlet container and web components.
The Service APIs serve to simplify your programming tasks by providing standard APIs to access diverse systems or alternative implementations.
The key APIs that are defined by the Java EE platform include:
- Java Database Connectivity (JDBC) API: The JDBC API provides a database-independent mechanism to access a relational database server. Note that even application client components may access a database directly via the JDBC API. However, the preferred mechanism in Java EE 5 is to use the Java Persistence API whenever possible.
- Java Naming and Directory Interface (JNDI): A naming service allows applications to bind an object to a logical name and to use that logical name at a later time to retrieve that object. Examples of a naming service include the file system, where a file name maps to a file object, or the Domain Naming Service, where a URL is used to lookup an IP address.
A Java EE container implements a naming service. A component within that container can access this naming service to look up various system- or user-defined objects, such as a
DataSource
, an environment variable, or an Enterprise JavaBean.A directory service lets you manage a hierarchical tree of objects and their attributes. Examples of directory services include Lightweight Directory Access Protocol (LDAP) directories that can be used to store user information such as user names, passwords, and contact details.
- Java EE Connector Architecture (JCA): This API lets you access data that is contained in existing corporate assets such as non-relational databases and mainframe applications, from within the Java EE platform.
- Java API for XML Processing (JAXP): JAXP allows a Java EE application to process XML documents, using DOM, SAX, or StAX APIs that are independent of the underlying XML processor implementation.
- Java Message Service (JMS) API: A messaging service allows distributed applications to communicate using messages. This communication is usually asynchronous. The JMS API provides a generic API that can be used to access enterprise messaging implementations from different vendors such as TIBCO or IBM MQ Series.
- JavaMail API: This API provides an interface that an application can use to interact with different email systems. It uses the JavaBeans Activation Framework (JAF) API to handle MIME data that are included in email messages.
- Java Transaction (JTA) API: This is a generic API for transaction management that even supports the complexity of transactions involving distributed databases. The Java Transaction Service (JTS) provides an implementation of this API.
- Remote Method Invocation (RMI) over Internet Inter-ORB protocol (RMI/IIOP): This API allows distributed EJB components to communicate with each other and with distributed CORBA services.
- Java Persistence API (JPA): This API provides an object/relational mapping facility for developers. Applications should use this technology in preference to either CMP entity beans or JDBC access.
- Web Service APIs: The Java API for XML Web Services (JAX-WS) and Java API for XML-based RPC (JAX-RPC) support the invocation of web services using the SOAP/HTTP protocol. The Java Architecture for XML Binding (JAXB) defines the mapping between Java classes and XML. In addition, the Java API for XML Registries (JAXR) provides client access to XML registry servers.
- Java IDL: It allows Java EE application components to invoke external CORBA objects.
- JavaServer Faces (JSF): This API provides a standard way to build component-oriented web applications that run within a web container.
- JavaServer Pages Standard Tag Library (JSTL): This library defines tags that provide core functionality required by web applications.
- Streaming API for XML (StAX): The StAX API provides for a simple pull parsing programming model for XML. Rather than waiting for program callback, as with the push-parsing that is used by the Simple API for XML (SAX) parser model, StAX lets the programmer retain control of the parsing operation.
- Java Management Extensions (JMX): This API supports the web-based management and monitoring of applications and services.
What is a typical Java EE application architecture?
In the typical multitier model, the enterprise application's functionality is divided into three tiers.
- The Presentation tier, which is comprised of the web container, and which houses web components like servlets and JSP pages.
- The Middle tier, which is comprised of the EJB container, and which houses enterprise bean components.
- The Persistence or Enterprise Information Systems tier, which houses the persistent data store.
The presentation tier reacts to client requests by invoking business logic that resides in the middle tier and is responsible for generating the view that is rendered at the client. The business logic for the application is housed in enterprise beans that live in the middle tier. This tier is responsible for updating the data stores in the persistence tier, based on the client's actions.
The creation of multiple tiers gives us the opportunity for scalability, but at the cost of performance.
However, most applications don't require this level of complexity, and so the Java EE specification does not require that all three tiers should actually be present.
In particular, the presence of an EJB container in the middle tier often adds unnecessary complexity. In such cases, you do not need a full blown Java EE application server, such as JBoss or GlassFish. Instead, you can make do with just a servlet container such as Tomcat.
In this scenario, the client is a browser, which communicates with the servlet container using HTML over HTTP. Web components receive these incoming requests, process them, access the data store as necessary, and return a HTML over HTTP response to the client browser. In this case, the business domain classes, the business rules, and the presentation logic are typically interwoven into the web components.
This is the application architecture that we will consider for the remainder of this book.