Develop n-tier applications using J2EE

An introduction to the Java 2 Platform, Enterprise Edition specification by way of BEA's WebLogic Server

Java originally made its debut in browsers and client machines; at the time, many questioned whether it was suitable for server-side development. Now, with increasing third-party support for the Java 2 Platform, Enterprise Edition (J2EE), Java has become a widely accepted alternative for developing enterprise-strength server-side solutions.

The J2EE platform consists of a set of services, application programming interfaces (APIs), and protocols that provide the functionality for developing multitiered Web-based applications.

In this article, we will examine the 13 core technologies that make up J2EE: JDBC, JNDI, EJBs, RMI, JSP, Java servlets, XML, JMS, Java IDL, JTS, JTA, JavaMail, and JAF. We will describe where and when it is appropriate to use each technology; we will also describe how the different technologies interact with each other.

Moreover, to give J2EE a real-world feel, we'll look at its main technologies in the context of WebLogic Server, a widely used J2EE implementation from BEA Systems. With that in mind, this introductory article will be of interest to developers new to WebLogic Server and J2EE, as well as project managers and business analysts with an interest in understanding what J2EE has to offer.

The big picture: Distributed architectures and J2EE

In the past, two-tier applications -- also known as client/server applications -- were commonplace. Figure 1 illustrates the typical two-tier architecture. In some cases, the only service provided by the server was that of a database server. In those situations, the client was then responsible for data access, applying business logic, converting the results into a format suitable for display, displaying the intended interface to the user, and accepting user input. The client/server architecture is generally easy to deploy at first, but is difficult to upgrade or enhance, and is usually based on proprietary protocols -- typically proprietary database protocols. It also makes reuse of business and presentation logic difficult, if not impossible. Finally, and perhaps most important in the era of the Web, two-tier applications typically do not prove very scalable and are therefore not well suited to the Internet.

Figure 1. Two-tier application architecture

Sun designed J2EE in part to address the deficiencies of two-tier architectures. As such, J2EE defines a set of standards to ease the development of n-tier enterprise applications. It defines a set of standardized, modular components; provides a complete set of services to those components; and handles many details of application behavior -- such as security and multithreading -- automatically.

Using J2EE to develop n-tier applications involves breaking apart the different layers in the two-tier architecture into multiple tiers. An n-tier application could provide separate layers for each of the following services:

  • Presentation: In a typical Web application, a browser running on the client machine handles presentation.
  • Dynamically generated presentation: Although a browser could handle some dynamically generated presentation, for the widest support of different browsers much of the action should be done on the Web server using JSPs, servlets, or XML (Extensible Markup Language) and XSL (Extensible Stylesheet Language).
  • Business logic: Business logic is best implemented in Session EJBs (described later).
  • Data access: Data access is best implemented in Entity EJBs (described later) and using JDBC.
  • Backend system integration: Integration with backend systems may use a variety of technologies. The best choice will depend upon the exact nature of the backend system.

You may begin to wonder: why have so many layers? Well, the layered approach makes for a more scalable enterprise application. It allows each layer to focus on a specific role -- for example, allowing a Web server to serve Webpages, an application server to serve applications, and a database server to serve databases.

Because it's built on top of the Java 2 Platform, Standard Edition (J2SE), J2EE provides all the same advantages and features of J2SE. These include "Write Once, Run Anywhere" portability, JDBC for database access, CORBA technology for interaction with existing enterprise resources, and a proven security model. Building on this base, J2EE then adds support for Enterprise JavaBean (EJB) components, Java servlets, JavaServer Pages (JSPs), and XML technology.

Distributed architectures with WebLogic Server

J2EE provides a framework -- a standard API -- for developing distributed architectures. The implementation of an engine to implement this framework is left up to third-party vendors. Some vendors will focus on particular components of the overall J2EE architecture. For example, Apache's Tomcat provides support for JSPs and servlets. BEA Systems provides a fuller implementation of the J2EE specification with its WebLogic Server product.

By providing a complete implementation of the J2EE specifications, WebLogic Server makes it easy to build and deploy scalable, distributed applications. WebLogic Server and J2EE handle certain common programming tasks for you. These include the provision of transaction services, security realms, guaranteed messaging, naming and directory services, database access and connection pooling, thread pooling, load balancing, and fault tolerance.

By providing these common services in an easy-to-use and standard way, products like WebLogic Server provide more scalable and maintainable applications. The result is increased availability of those applications to a larger number of users.

The J2EE technologies

In the following sections, we'll describe each of the technologies making up J2EE, and see how WebLogic Server supports them in a distributed application. Perhaps the most commonly used J2EE technologies include JDBC, JNDI, EJB, JSPs, and servlets, upon which we therefore focus our attention.

Figure 2 illustrates where each of the J2EE technologies are most commonly used within a distributed application.

Figure 2. A sample n-tier application architecture

Java Database Connectivity (JDBC)

The JDBC API accesses a variety of databases in a uniform way. Like ODBC, JDBC hides proprietary database issues from the developer. Because it's built on Java, JDBC also is able to provide platform-independent access to databases.

JDBC defines four fundamentally different types of drivers, as we'll see next.

Type 1: JDBC-ODBC Bridge

The JDBC-ODBC Bridge proved most useful when JDBC was still in its infancy. With it, developers can use JDBC to access an ODBC data source. As a downside, it requires that an ODBC driver be installed on the client machine which, generally speaking, should be running a version of Microsoft Windows. By using this type of driver, you therefore sacrifice the platform independence of JDBC. Additionally, the ODBC driver requires client-side administration.

Type 2: JDBC-native driver bridge

The JDBC-native driver bridge provides a JDBC interface built on top of a native database driver -- without using ODBC. The JDBC driver converts standard JDBC calls into native calls to the API of the database. Using a type 2 driver also sacrifices the platform independence of JDBC and requires installation of client-side native code.

Type 3: JDBC-network bridge

JDBC-network bridge drivers remove the need for client-side database drivers. They make use of network-server middleware to access a database. This makes such techniques as load balancing, connection pooling, and data caching possible. Because type 3 drivers often involve a relatively small download time, are platform independent, and require no client-side installation or administration, they are good for Internet applications.

Type 4: Pure Java driver

Type 4 provides direct database access using a pure Java database driver. Due to the way type 4 drivers run on the client and directly access a database, running in this mode would imply a two-tier architecture. A better use of type 4 drivers in an n-tier architecture would be to have an EJB contain the data access code, and have that EJB provide a database-independent service to its clients.

WebLogic Server provides JDBC drivers for some of the more common databases, including Oracle, Sybase, Microsoft SQL Server, and Informix. It also comes with a JDBC driver for Cloudscape, a pure Java DBMS, an evaluation copy of which comes with WebLogic Server.

Next, let's look at an example.

JDBC Example

Our example assumes that you have a PhoneBook database set up in Cloudscape, and that this database contains a table CONTACT_TABLE with fields NAME and PHONE. We begin by loading the Cloudscape JDBC driver, and requesting that the driver manager obtain a connection to the PhoneBook Cloudscape database. Using this connection, we construct a Statement object and use it to execute a simple SQL query. Finally, the loop iterates through all entries in the result set, writing the contents of the NAME and PHONE fields to the standard output.

import java.sql.*;
public class JDBCExample
  {
  public static void main( String args[] )
    {
    try
      {
      Class.forName("COM.cloudscape.core.JDBCDriver");
      Connection conn = DriverManager.getConnection("jdbc:cloudscape:PhoneBook");
      Statement stmt = conn.createStatement();
      String sql = "SELECT name, phone FROM CONTACT_TABLE ORDER BY name";
      ResultSet resultSet = stmt.executeQuery( sql );
      String name;
      String phone;
      while ( resultSet.next() )
        {
        name = resultSet.getString(1).trim();
        phone = resultSet.getString(2).trim();
        System.out.println( name + ", " + phone );
        }
      }
    catch ( Exception e )
      {
      // Handle exception here
      e.printStackTrace();
      }
    }
  }

That's all there is to it. Next, let's look at the use of JDBC in enterprise applications.

JDBC in enterprise applications

The previous example is, by necessity, somewhat trivial. It also assumes a two-tier architecture. In an n-tier enterprise application, it is much more likely that the client will communicate with an EJB, which, in turn, will make the database connection. To enable improved scalability and performance, WebLogic Server provides support for connection pools.

Connection pools reduce the overhead of establishing and destroying database connections by creating a pool of database connections when the server starts up. When a connection to the database is subsequently required, WebLogic Server simply selects one from the pool rather than creating one from scratch. Connection pools in WebLogic Server are defined in the weblogic.properties file. (Refer to the examples in your weblogic.properties file and the WebLogic Server documentation for more information.)

Another database feature frequently required in enterprise applications is support for transactions. A transaction is a group of statements that should be treated as a single statement to ensure data integrity. JDBC uses the auto-commit transaction mode by default. This can be overridden using the setAutoCommit() method of the Connection class.

Now that we have a sense of JDBC, let's turn our attention to JNDI.

Java Naming and Directory Interface (JNDI)

The JNDI API is used to access naming and directory services. As such, it provides a consistent model for accessing and manipulating such enterprise-wide resources as DNS, LDAP, local filesystems, or objects in an application server.

In JNDI, every node in a directory structure is called a context. Every JNDI name is relative to a context; there is no notion of an absolute name. An application can obtain its first context using the InitialContext class:

Context ctx = new InitialContext();

From this initial context, the application can traverse the directory tree to locate the desired resources or objects. For example, assume that you have deployed an EJB within WebLogic Server and bound the home interface to the name myApp.myEJB. A client of this EJB, after obtaining an initial context, could then locate the home interface using:

MyEJBHome home = ctx.lookup( "myApp.myEJB" );

Once you have a reference to the acquired object -- in this case, the home interface of the EJB -- it is then possible to invoke methods on it. We will discuss this further in the section below entitled "Enterprise Java Beans."

The above discussion of JNDI is just the tip of the iceberg. In addition to looking up objects in a context, JNDI also provides methods to:

  • Insert, or bind, an object into a context. This is effectively what you do when you deploy an EJB.
  • Remove an object from a context.
  • List all objects within a context.
  • Create and delete subcontexts.

Next, let's turn our attention to EJBs.

Enterprise Java Beans (EJB)

One of the J2EE technologies to receive a great deal of media attention is EJBs. They provide a framework for developing and deploying distributed business logic to clients, thereby significantly easing the development of scalable, highly complex enterprise applications. The EJB specification defines how and when EJB components should interact with their container. It is the responsibility of the container to provide for common services, such as directory services, transaction management, security, resource pooling, and fault tolerance.

The EJBs specification defines three fundamental types of bean:

  • Stateless session beans: These provide a single-use service, do not maintain any state, do not survive server crashes, and are relatively short lived. For example, a stateless session bean may be used to perform temperature conversion.
  • Stateful session bean: These provide a conversational interaction with the client and, as such, store state on the behalf of the client. An online shopping cart is a classic example of a stateful session bean. Stateful session beans do not survive server crashes, are also relatively short lived, and each instance can be used only by a single thread.
  • Entity beans: These provide a representation of persistent data -- typically stored in a database -- and can therefore survive a server crash. Multiple clients can use EJBs that represent the same data. An example of an entity EJB: a customer's account information.

In spite of their differences, all EJBs have much in common. They all possess a home interface that defines how a client can create and destroy the EJB; a remote interface that defines the methods a client can invoke on the bean; and a bean class that implements the main business logic.

Describing how to develop an EJB is beyond the scope of this article. However, once an EJB has been developed or purchased from a third party, it must be deployed in your application server. WebLogic Server 5.1 comes with an EJB Deployer Tool to assist with deployment of EJBs. When you deploy an EJB using the EJB Deployer Tool, you specify the JNDI name used by clients to locate the EJB. The Deployer Tool will then generate wrapper classes to handle communications with the container and bundle the required Java classes together in a jar file.

Once an EJB has been deployed, a client can locate the EJB using its JNDI name. First, it must obtain a reference to the home interface. Then, using that interface, the client can invoke one of the bean's create() methods to obtain a handle to a bean instance running on the server. Finally, the client may use this handle to invoke methods on the bean.

From EJBs, we shift to JSPs.

JavaServer Pages (JSPs)

Some of you may already be familiar with Microsoft's Active Server Pages (ASPs); JSPs are the platform-independent equivalent. They were designed to help Web content developers create dynamic Webpages with relatively little coding. Web designers who don't know how to program can use JSPs to create dynamic pages. A JavaServer Page consists of HTML code interspersed with Java code. The server processes the Java code when the page is requested by the client, returning the generated HTML page to the browser.

Let's look at a simple example of a JSP that displays the server's current date and time. An explanation of the details of this is beyond the scope of this article; however, note the Java code between the <% and %> symbols, followed by the Java expression between the <%= and %> symbols.

<html>
<head>
 <title>Sample JSP Page</title>
</head>
<body>
<h1>Date JSP sample</h1>
<h2>
<% response.setHeader("Refresh", 5); %>
The current date is <%= new Date()  %>.
</h2>
</body>
</html>

You may occasionally hear reference to JHTML, an older standard since superseded by JSPs. WebLogic Server can support JSPs as well as JHTML. Note that, by default, JSPs are not enabled within WebLogic Server. To enable them, you must edit the weblogic.properties file and enable the Web server -- if it hasn't already been enabled -- as well as the JSPServlet.

Next up: Java servlets

Java servlets

A servlet provides much the same functionality as a JSP, albeit by taking a somewhat different approach. Whereas JSPs typically consist mostly of HTML code interspersed with small amounts of Java code, servlets, on the other hand, are written totally in Java and produce HTML code.

A servlet is a small Java program that extends the functionality of a Web server. It is a server-side application dynamically executed when requested, much like CGI Perl scripts in more traditional Web servers. One of the major differences between CGI scripts and servlets: CGI scripts require a whole new process to be started -- incurring additional overhead -- whereas servlets are executed as a separate thread within the servlet engine. Servlets therefore tend to offer improved scalability.

When developing servlets, you will generally want to extend the javax.servlet.http.HttpServlet class, and override some of its methods. The methods of most interest include:

  • service(): Acts as a dispatcher to command-specific methods
  • doGet(): Handles an HTTP GET request from a client
  • doPost(): Handles an HTTP POST request from a client

Other methods exist to handle different types of HTTP requests -- refer to the HttpServlet API documentation for more information (see Resources).

The methods described above are all part of the standard J2EE Servlet API. WebLogic Server provides a full implementation of this API. Once you have developed your servlet, you can deploy it in WebLogic Server by registering it in the weblogic.properties file.

With Java servlets, we've reached the end of J2EE's major technologies, but that's not the end to what J2EE has to offer. In the next sections, we'll take a brief look at the remaining technologies, including RMI, Java IDL and CORBA, JTA, and XML, to name a few.

Remote Method Invocation (RMI)

As its name suggests, the RMI protocol invokes methods on remote objects. It uses serialization to pass data between the client and the server. RMI is the underlying protocol used by EJBs.

Java IDL/CORBA

With Java's IDL support, developers can integrate Java with CORBA. They can create Java objects that can be deployed within a CORBA ORB, and they can create Java classes that act as clients to CORBA objects deployed within other ORBs. The latter approach provides another way in which Java can be used to integrate your new application with legacy systems.

Java Transaction Architecture (JTA)/Java Transaction Service (JTS)

JTA defines a standard API that applications can use to access transaction monitors.

JTS is a basic implementation of a CORBA OTS transaction monitor. JTS specifies the implementation of a Transaction Manager that supports the Java Transaction API (JTA) specification at a high level and implements the Java mapping of the OMG OTS specification at a low level. A JTS Transaction Manager provides transaction services to the application server, the resource manager, standalone applications, and the Communications Resource Manager.

JavaMail and JavaBeans Activation Framework

JavaMail is an API for accessing mail servers. The JavaMail API provides a set of abstract classes that model a mail system. Both SMTP and IMAP servers are supported.

JavaMail makes use of the JavaBeans Activation Framework (JAF) to handle MIME-encoded mail attachments. MIME byte streams can be converted to and from Java objects. Most applications will not have to use JAF directly.

Java Messaging Service (JMS)

JMS is an API for communicating with message-oriented middleware. It supports both the point-to-point domain and the publish/subscribe domain, and provides support for guaranteed message delivery, transactional message delivery, persistent messages, and durable subscribers. JMS provides another way of integrating your application with legacy backend systems.

Extensible Markup Language (XML)

XML is a language for defining other markup languages. It can be used to share data between businesses. XML was developed independently from Java; however, it shares similar goals in that it is platform independent. By combining Java with XML, you have a completely platform-independent solution. Various companies are working on developing a tight integration between Java and XML. For more information, visit Sun's Java-XML page, or the XML Zone at IBM's developerWorks (see Resources for the URLs).

Conclusion

In this article, we introduced distributed architectures built upon J2EE, and we described WebLogic Server's support for J2EE. This, however, is just the tip of the iceberg, as no 3,000 word article could begin to do justice to J2EE's potential impact on your enterprise applications.

We focused our attention on the technologies that you are most likely to encounter when you begin working with J2EE: JDBC, JNDI, EJBs, JSPs, and servlets. We also provided you with some background information on the less well-known J2EE technologies. Whether you are a developer, business analyst, or project manager, you now should have a good idea of what J2EE and WebLogic Server have to offer you, your enterprise, and your enterprise applications.

Acknowledgements

Thanks to Shari L. Jones and Bill Dunklau for their contributions to this article.

Learn more about this topic

  • JavaWorld resources
  • Other resources

Join the discussion
Be the first to comment on this article. Our Commenting Policies
See more