J2EE Earns JAVA a Station in the Enterprise

While java has gained significant acceptance as the object-oriented language of choice for e-commerce and Internet-based applications, its acceptance as a platform for enterprise computing has been lagging. Concerns about other capabilities of the Java platform as a prime-time player in the enterprise computing game have historically had many IS managers and CTOs cautious about betting the ranch on Java as the platform on which to build and deploy the new generation of n-tier app systems.

Building complex, distributed application systems is more than just having a solid set of functional APIs readily available. Despite its solid set of APIs, Java before J2EE was not "ready for prime time" when it came to enterprise computing. Issues such as a consistent security model, transaction support, administration, configuration and deployment raised doubts in the minds of potential adopters about the applicability and usability of Java to solve real-world problems.

However, J2EE has quickly dispelled most of those concerns and has many of those skeptics seriously considering and evaluating J2EE as "the platform." Integrated services, combined with dynamic configuration and deployment capabilities, have clearly entrenched Java in the high-stakes enterprise computing game. In this article, I will take you on a grand tour of the total J2EE offering with stops at various key points that will illustrate the power and applicability of J2EE.

J2EE enables solutions for developing, deploying and managing n-tier server-centric enterprise apps. It provides numerous capabilities, such as:

  • A consistent and integrated API set;
  • A consistent component model that extends to all processing tiers;
  • Reusable components that can be customized to the runtime environment;
  • A consistent and integrated set of enterprise services, including the ability to configure them in the runtime environment dynamically without requiring changes to processing logic;
  • An architectural framework that allows for the creation of complex applications; and
  • Best practices and guidance in applying the framework to real-world problems.

Despite the obvious advantages, J2EE is more than just a "packaging" of Java-enabling APIs. J2EE provides a framework for "allocating" component functionality and code to the appropriate platform using the appropriate technology. It provides developers and architects alike with a roadmap for how to appropriately apply the range of Java technologies to real-world programming and architecture challenges.

J2EE consists of the J2EE platform, the J2EE Programming Model, J2EE Compatibility Test Suite (CTS) and the J2EE Reference Implementation (RI). Before I go into detail on the first two items, which are the core of J2EE from an application development and architecture perspective, I will touch on CTS and RI. These two elements provide the foundation for J2EE in terms of acceptance by the industry at large.

The J2EE Compatibility Test Suite (CTS) is a suite of compatibility tests that is used by vendors to validate and certify that their products are completely J2EE-compliant. Vendors run this test suite on their platform implementations to ensure that all APIs are supported correctly and that all constituent technologies work together properly for a completely functional J2EE environment. Products that carry the J2EE "stamp of approval" are therefore guaranteed to support the complete set of J2EE technologies and functionality.

The J2EE Reference Implementation (RI) provides a minimal J2EE runtime environment for J2EE applications and is used by both product vendors and developers. For vendors, it defines the minimal operational environment or "gold standard," allowing vendors to determine what their platform implementations must do under a particular set of application conditions. For developers, it is used to verify the portability of their J2EE code base and to provide the standard platform for running the CTS.

The J2EE platform

The J2EE platform is a consolidated set of Java technologies and APIs that provide a standard platform for hosting J2EE applications. To connect the components running across all the tiers of the J2EE model, the platform contains a standard set of enabling and connectivity APIs. Table 1 lists the constituent APIs for J2EE.

Historically, Java APIs have been delivered in dribs and drabs with no real coordination between them. This was fine when the APIs were evolving in isolation. With J2EE, however, the constituent APIs have "grown up" to become integrated and dependent on each other for key functionality. For instance, early on there was no requirement for Java Database Connectivity (JDBC) to support the Java Naming and Directory Interface (JNDI) or transactions. The 2.0 release of JDBC provides support for transactions and utilizes JNDI to store target datasource names.

The key to creating a solid and foundational platform for enterprise computing, as well as e-commerce-based computing, is a solid set of core services. More importantly, these services have to be integrated across the platform. With J2EE, services like security, transaction support, and naming and directory are not "add-ons" — they are integrated across all tiers of the architecture.

Even though support for the Java Message Service (JMS) is not currently mandatory for J2EE, I anticipate that most, if not all, J2EE application server vendors will provide a JMS engine, if only to provide product discrimination and a key purchase point. JMS supports connectivity and information exchange between Java components in both point-to-point and many-to-many fashion, providing key messaging service capabilities for complex and interactive Java apps. In that vein, JMS is a key and vital element of e-commerce-based solutions, enabling information exchange between partners on the supply chain.

J2EE security services are designed to ensure that only authorized users access resources and components. The J2EE security model supports both authentication and authorization facilities. For authorization, access control is provided and controlled using an application's security domain, which is configured and administered independently of application code.

Unlike other enterprise application models, which require platform-specific security features in each app, J2EE's security environment provides declarative access to security configuration and attributes. This allows security settings to be configured outside of program code at deployment time and not at development time. These rules are interpreted when the application components are deployed in the runtime environment. In addition, J2EE requires that all app server and platform vendors provide standard login mechanisms, eliminating the need for developers to supply this logic.

The J2EE transaction model is a flat model, which means that a transaction cannot have any child or nested transactions. J2EE takes the complexity out of the transaction management process by implicitly handling many transaction details, such as propagating transaction context and coordinating transactions across multiple transaction managers. This is done by leveraging the methods on the interfaces of the JTA.

However, it is important to note that the transactional capabilities of J2EE are clearly tipped toward the business logic or Enterprise JavaBean (EJB) tier — Web components (Java Server Pages [JSPs] and servlets) are not designed to be transactional in nature. Transactional behavior should always be delegated to an EJB, which can use one of two styles of transactional behavior: bean-managed transaction demarcation or container-managed transaction demarcation. In the former case, the EJB programmer takes responsibility for managing all aspects of the transaction in program code such as transaction start, rollback and commit. With bean-managed demarcation, the EJB container handles all transaction details and operations, driven by instructions in the EJB's deployment descriptor. Session beans can support both types, but they cannot be used at the same time.

J2EE naming services provide application clients, EJBs and Web components with access to a JNDI naming and directory environment. J2EE components locate other components by looking them up in a naming context, a hierarchically organized collection of logical names that map to the physical location of the component. This provides a structured and disciplined approach to managing and locating objects in complex distributed environments, overcoming the chaotic and free-for-all approach that typically occurs.

A J2EE component can access both system-provided and user-defined objects. The names of system objects, such as JTA transaction objects, are stored in a special naming context. In addition, J2EE allows a component to name user-defined objects such as EJBs, environment entries, JDBC datasource objects and JMS message connections. For JDBC datasource objects, this allows application code to locate and open a database source based upon an easy-to-read logical name instead of the often clumsy and usually long database URLs that were prevalent with JDBC 1.x.

Table 1: J2EE API thumbnail
API Product Version
J2SE Java 2 Standard Edition 1.2
JSP Java Server Pages 1.1
Servlets Servlet API 2.2
EJB Enterprise JavaBeans 1.1
JNDI Java Naming and Directory Interface 1.2
JTA Java Transaction API 1.0
JDBC 2.0 Extension Java Database Connectivity 2.0
JMS Java Message Service 1.0
JavaMail Java Mail API 1.1
JAF Java Activation Framework 1.0
A listing of the constituent application programming interfaces (APIs) for J2EE.

The J2EE Programming Model

The J2EE Programming Model provides a standard and extensible model for architecting, building and deploying multi-tier, distributed, thin-client apps. J2EE is positioned to be the platform for distributed computing supporting the architecting, development and deployment of e-commerce systems as well as Internet-, intranet- and extranet-based apps.

J2EE applications consist of three fundamental elements — components, containers and connectors. Figure 1 illustrates the relationship between components and containers. Containers provide all J2EE application components with the J2SE platform APIs, which include both the Java Interface Definition Language (IDL) and JDBC core enterprise APIs. In addition, support is provided for the APIs listed in Table 1. Containers provide the execution environment for components that run on all three processing tiers of J2EE — client, Web and server. These containers are really a formalization of what we have seen in the various Enterprise Java initiatives — browsers on the client side, servlet and JSP engines in the Web middle tier, and EJB containers in the business logic middle tier.

Connectors sit under the J2EE platform and define a portable service-level API to connect heterogeneous information systems and sources into a J2EE app. These connectors provide the EAI functionality for the J2EE platform by allowing processing assets stored in diverse EIS-tier systems — host-based systems, pre-packaged apps and ERP systems such as Baan, PeopleSoft and SAP — to be accessed in a consistent manner from middle-tier components.

The J2EE Programming Model partitions application components and models into three logical tiers: client, middle and EIS, as shown in Figure 2. At the top of the model is the client tier, which is composed of a combination of HTML page-based clients and HTTP content-based clients. These clients interact with components in the middle tier. These middle-tier components are either servlets and/or JSPs in the Web tier, or EJBs in the business-logic tier. Middle-tier components provide the underlying server-side processing capabilities of J2EE apps. In the business-logic tier, business code packaged as EJBs executes in an application server-based environment. At the bottom of the J2EE "stack" lies the ultimate pot of gold, the EIS tier, which contains the key processing systems and apps.

J2EE apps can be Web- or non-Web-based, allowing the user interface to be presented as HTML pages, Java applets, Java-Beans or a combination of the three. For example, HTML-based apps can be generated via dynamically generated HTML pages and forms. More sophisticated application services will interact with first-tier clients by exchanging business data directly. In this scenario, JSPs and servlets are used to format and present this data in a way that is easy for J2EE clients to consume and use. These clients can be both Java applets running in a Web browser and Java technology-based programs (such as wireless or hand-held devices, for example).

With HTTP content-based clients, advanced functionality is attained through the use of client-side logic execution. In this case, raw information such as eXtensible Markup Language (XML) is exchanged between the middle and client tiers, while execution on the client is typically in the form of Java apps, applets or JavaBeans. To support the plethora of browsers and their various versions dynamically, J2EE provides the ability to load the runtime environment dynamically using the Java plug-in.

Servlets and JSP components comprise the Web tier of a J2EE application. Servlets are a portable way to deliver dynamic content, while JSPs provide a text-based, presentation-centric approach to developing servlets. In the runtime environment, JSPs are compiled into servlets that are then run in a Web container. Combining JSPs with JavaBeans offers all the advantages of servlets with the added benefit of separating content and display logic cleanly.

One key advantage to this approach is that content developers do not have to be concerned with app logic, eliminating the need for presentation developers to understand Java app code and the need for EJB developers to understand HTML or presentation logic. This fits in with the roles associated with J2EE, which I will discuss later. In addition, with this approach, Web templates can be created easily, allowing a Web-based J2EE app with a consistent look and feel to be created with minimal effort.

From my experience, I have noticed that a typical dilemma is determining how to leverage JSPs and servlets, as well as deciding among the various approaches and technologies to developing and packaging Web components. The advice and guidance that I typically offer is that servlets provide a programmatic approach to capturing functionality on the Web server. Servlets are used to capture code that changes infrequently or that provides access to low-level functionality. JSPs are used as a presentation-centric, declarative approach to binding dynamic content with processing logic.

As we have seen, J2EE is more than just a collection of APIs that provide the ability to create distributed Java systems. J2EE is positioned to be the foundation of a complete application and architectural framework, providing the services required to build e-commerce-based applications. A key component of this "architectural blueprint" is the inclusion of a guide for architecting and building these applications. This integrated set of documentation provides guidance and best practices for architecting, designing and building n-tier distributed application systems. The J2EE Blueprints component provides the "cookbook" for building well-architected applications that leverage the J2EE product and technology set.

Assembling and deploying J2EE applications

As an integral element of J2EE's discipline, a set of six roles has been defined to cover the range of activities that are performed in creating and deploying a J2EE application system. These roles are product provider, application component provider, application assembler, deployer, system administrator and tool provider. The roles reflect the distinct and clear separation of product purchase from development, deployment and administration. Most of these are derived from typical industry usage and should be familiar to application development organizations. The identification of such roles is not novel, but their formalization into a platform such as J2EE is. An application component provider creates J2EE components — such as Web components or EJBs — and packages them in archive files, while an application assembler takes these packaged components and assembles them into a complete J2EE app.

The deployer role entails deploying the complete J2EE application into the runtime environment. This role is key because of the declarative nature of a significant portion of J2EE functionality. For example, a deployer would be responsible for setting all the attributes of an EJB deployment descriptor targeted for a specific environment, including transaction and security attributes. The system administrator is responsible for the day-to-day health of the J2EE system. This person will typically utilize the administrative capabilities of the application server environment to tune and optimize the J2EE runtime environment.

J2EE extends the deployment model we are familiar with from Java and EJBs, with a few new acronyms thrown in. A J2EE application is packaged as an Enterprise Archive (EAR) file, which is a standard Java JAR file. These EARs comprise one or more J2EE modules and a J2EE deployment descriptor, as illustrated in Figure 3.

The creation of an EAR is a two-step process. In the first step, application component providers create the constituent tier deployment modules — EJB, Web and client modules. One key point to keep in mind is that each of the constituent deployment modules is an independent deployable unit. The client components are packaged as .jar files, while the EJBs are packaged in EJB-JAR files. A new archive construct, the Web Archive (WAR file), contains all the elements of the Web tier, including JSPs, servlets, HTML files and supporting Web files (images, sound files and so on).

In the second step, the application assembler packages these modules into an EAR file that contains the complete, deployable J2EE application. During this step the application assembler edits deployment descriptors for each of the constituent J2EE modules to link dependencies between components that are contained within each archive as well as components in different archives. For example, the JSP and servlets in the WAR file need to refer to the correct EJBs in the EJB-JAR file.

Once the assembly step is complete, the EAR should be run through a J2EE verifier tool (one is included in the J2EE SDK) to ensure that the contents are well formed. While this verification is not a solid guarantee that the application will behave correctly at runtime, the verifiers provide a significant number of static checks to ensure that the deployment descriptor and the archive file contents are consistent with the EJB, servlet, JSP and J2EE specifications.

Unlike earlier deployment descriptors, the J2EE deployment descriptor is XML-based and consists of a series of name-value pairs that are organized in a hierarchical manner. Deployment descriptors contain a variety of information, such as structural information that describes the components that comprise the archive and assembly information. Most important, a deployment descriptor contains attributes and values that control the runtime behavior of the components stored in the archive. For example, an EJB-JAR file contains entries and attributes that control the security and transactional behavior of contained EJB components.

To be continued ...

As we have seen, the J2EE platform is a significant step in the evolution of Java as a platform for enterprise computing. However, this is not the end of the story. During the next year, improvements will be made in the platform to tighten up some loose ends and to solidify J2EE as the platform for enterprise computing. This includes the addition of JMS as a first-class API in the platform and its integration with EJB as a core service.

Of more importance is the evolution of the EJB container with new enterprise-class features that will enable it to become the standard execution environment for components. The addition of key and core services to the container framework, including inheritance, persistence and the ability to support dynamic relationships, provides the foundation of an extensible and reliable execution environment for J2EE applications.