The J2EE standard framework provides support for a number of the most commonly used distributed computing technologies and services. These APIs serve as building blocks for enterprise applications. In this section, we group them into rough functional categories and discuss how they are covered in this book. In the section that follows this one, we discuss some key, but nonstandard, enterprise APIs and tools that facilitate the assembly of these enterprise components into applications. At the end of the chapter, we describe an enterprise computing scenario that illustrates how these APIs and tools can be used together to produce an enterprise application.
Two essential technologies for enterprise application development are XML and security services.
XML is not strictly an enterprise-focused tool. XML is useful in all kinds of contexts, enterprise and otherwise. We’ve included it in this book, however, because XML is now such a fundamental, all-purpose tool that it touches nearly every level of enterprise application development, from basic datafile formats to interprocess communications to user interface representations.
The Java API for XML Processing (JAXP) (defined in JSR 005)[2] is the standard API for consuming and producing XML in Java. Application servers compliant with J2EE 1.3 and later must include a compliant JAXP implementation. JAXP provides a pluggable API that supports both SAX and DOM parsing of XML content, as well as XSLT-based transformations of XML. JAXP 1.2, the version specified in the J2EE 1.4 specification, supports the SAX 2 and DOM 2 parsing APIs, as well as the XSLT 1.0 transform API. JAXP is covered briefly in Chapter 7. The JAXP APIs are also covered in Java in a Nutshell by David Flanagan (O’Reilly).
Security is of paramount importance in enterprises today and is entrenched in many aspects of application development and deployment. In fact, security is a concern that must be considered in all aspects of the modern enterprise, well beyond the J2EE security APIs discussed in this book.
The J2EE security chapter (Chapter 10) provides a brief overview of fundamental security concepts such as authentication and authorization. Authentication refers to the process of a user identifying himself to an application, typically using a username and password. Authorization refers to granting the authenticated user access to the resources within the application, as appropriate to that user.
Chapter 10 explains security in the web tier as well as the Enterprise JavaBeans (EJB) tier with several examples. It elaborates on the important concept of identity propagation across tiers as well as within the EJB tier.
The chapter covers programmatic as well as declarative security approaches. In programmatic security, you program the security rules in the code, while in declarative security you specify the rules in the deployment descriptors and let the application server enforce the rules. The chapter explains the ways in which programmatic and declarative security in Java and J2EE can be used together to build effective security into your applications.
Chapter 10 also discusses single sign-on, a technique for sharing authentication credentials across various applications.
The J2EE framework supports web interfaces with the concept of
web components. These components run within
application servers and take advantage of several runtime services
provided by these servers, including user session management,
security services like authentication and encrypted communications,
and so on. Web components are also able to access other J2EE
resources and components, such as Java Database Connectivity (JDBC)
DataSources
and local and remote
EJB components.
J2EE supports the development of web components and web UIs with a family of three standards: Java servlets , JavaServer Pages (JSPs) and, more recently, JavaServer Faces (JSF). Each of these supports different programming models and runtime models, and each is important in different ways and in different contexts. Struts, a nonstandard but popular web interface technology, is described in a later section.
A servlet is a Java object that runs within a server to provide a service to a client. The name “servlet” was originally meant to be a takeoff on “applet”—a servlet can be thought of, roughly, as a server-side applet. The Java Servlet API (JSR 053 and JSR 154) provides a generic mechanism for extending the functionality of any kind of server that uses a protocol based on requests and responses.
For the most part, servlets are used behind web servers for dynamic generation of HTML content. But more generally, a servlet is a Java object that can receive HTTP requests and provide HTTP responses. The most typical scenario is a web browser that issues a request to a web server and a Java servlet that receives the request, performs some operations (perhaps JDBC calls to retrieve information or a call to an EJB component to invoke some business logic), and sends an HTML response back to the browser. But servlets can also serve in other ways in an enterprise application. A remote application can issue an HTTP request to a servlet, and the servlet can respond with an XML document in response, for example.
A key advantage of servlets over some other similar technologies, such as Microsoft Active Server Pages, is that servlets are portable among operating systems and among application servers. The advantage of servlets over some script-based web technologies, like Perl CGIs, is that servlets are also compiled objects that are persistent between invocations, which gives them major performance benefits over parsed scripts. Servlets also have full access to the rest of the Java platform, so features such as database access are automatically supported.
The Servlet API is a standard extension to the Java platform
and is part of the J2EE specifications. The API is implemented in
the javax.servlet
and javax.servlet.http
packages. The
javax.servlet
package defines
classes that represent generic client requests and server
responses, while the javax.servlet.http
package provides
specific support for the HTTP protocol, including classes for
tracking multiple client requests that are all part of a single
client session. See Chapter
3 for details on servlet programming.
JavaServer Pages (JSPs) (JSR 053 and JSR 152) are also part of the J2EE specifications family and closely related to Java servlets. You can think of JSPs as an alternative approach to creating servlets, in one sense. JSPs are similar to alternative technologies such as PHP and Microsoft Active Server Pages—they all provide a way to insert dynamic elements directly into HTML pages. In the case of JSPs, these dynamic elements invoke Java code using references and calls to Java beans, using custom tags that act as dynamic macros that are implemented by Java beans, or using raw Java code snippets. Chapter 4 provides details on writing JSPs. In addition, this chapter provides some details on using the Java Standard Tag Library (JSTL), a standard set of handy JSP tags that can be used in any compliant JSP engine.
JavaServer Faces (JSR 127) is a recently released Java standard for user interface (UI) components. JSF builds on the foundation provided by Java servlets and JSPs, providing a UI component model based on JSP tags. This UI component model allows you to create UIs for your application from a set of predefined components (similar to the role that Java Swing plays in the world of desktop GUIs). The JSF model also includes state management and page navigation facilities that help in the development of applications using customary design patterns like model-view-controller (MVC).
See Chapter 5 for a short tutorial on JSF, its tag libraries, and application configuration schemes.
Access to databases and distributed systems is essential for enterprise applications. APIs in this area include JDBC and Java Naming and Directory Interface (JNDI).
JDBC (JSR 054) is the Java API for working with relational database systems. JDBC allows a Java program to send SQL query and update statements to a database server and to retrieve and iterate through query results returned by the server. JDBC also allows you to get metadata about the database and its tables from the database server.
The JDBC API is independent of vendor-specific APIs defined
by particular database systems. The JDBC architecture relies upon
a Driver
class that hides the
details of communicating with a database server. Each database
server product requires a custom Driver
implementation to allow Java
programs to communicate with it. Major database vendors have made
JDBC drivers available for their products. In addition, a “bridge”
driver exists to enable Java programs to communicate with
databases through existing ODBC drivers.
The JDBC API is found in the java.sql
package, which was first
introduced in Java 1.1. Java 1.2 updated the core APIs to include
JDBC 2.0, which added a number of new classes to support advanced
database features. JDBC 2.0 also provides additional features in
the javax.sql
standard
extension package. JDBC includes classes for extracting data from
databases in the form of Java objects, for pooling database
connections, and for obtaining database connection information
from a JNDI name service. The extension package also supports
scrollable result sets, batch updates, and the storage of Java
objects in databases. The latest versions of the J2SE, 1.4 and
5.0, include the JDBC 3.0 API, whose specification was released in
February 2002. This version of JDBC adds support for transaction
“savepoints,” allowing you to programmatically roll back database
transactions to multiple checkpoints, as well as some enhancements
to connection pooling support. At this writing, however, driver
support for JDBC 3.0 is still somewhat limited, and in several
cases you may have only JDBC 2.x API support in your
drivers.
The JDBC API is simple and well designed. Programmers who are familiar with SQL and database programming in general should find working with databases in Java very easy. See Chapter 8 for a tutorial on JDBC and Appendix D for a quick reference to SQL.
JNDI is the Java Enterprise API for working with
networked naming and directory services. It allows Java programs
to use name servers and directory servers to look up objects or
data by name and search for objects or data according to a set of
specified attribute values. JNDI is implemented in the javax.naming
package and its subpackages
as a core API in the Java platform.
The JNDI API is not specific to any particular name or directory server protocol. Instead, it is a generic API that is general enough to work with any name or directory server. To support a particular protocol, plug a service provider for that protocol into a JNDI installation. Service providers have been implemented for the most common protocols, such as LDAP, Active Directory, and Novell’s NDS. Service providers have also been written to interact with the RMI and CORBA object registries.
JNDI also plays a key role in the J2EE framework since it is the API used to access runtime configuration information and resources by J2EE applications. Information specified in component deployment descriptors is made available to components by the application server through an internal name server, and the application components access this name server through JNDI.
JNDI is covered in detail in Chapter 9.
The JTA, or Java Transaction API, is a Java Enterprise API for managing distributed transactions. Distributed transactions are one of the things that make distributed systems more complicated than nondistributed programs. To understand distributed transactions, you must first understand simple, nondistributed transactions.
A transaction is a group of several operations that must behave atomically, as if they constitute a single, indivisible operation. Consider a banking application that allows a user to transfer money from a checking account to a savings account. If the two account balances are stored in a database, the application must perform two database updates to handle a transfer—it must subtract money from the checking account and add money to the savings account. These two operations must behave atomically. To see why, imagine what would happen if the database server crashed after money had been subtracted from the checking account but before it had been added to the savings account. The customer would lose money!
The JTA defines a Java binding for the standard XA API for distributed transactions (XA is a standard defined by the Open Group). Using the JTA, we can write a program that communicates with a distributed transaction service and uses that service to coordinate a distributed transaction that involves, for example, a transfer of money between database records in two different databases.
Chapter 16 provides a brief general tutorial on the JTA. Since EJBs and EJB containers provide direct support for distributed transactions using JTA, there is also brief coverage of the API (as it relates to EJB) in Chapter 6. JDBC drivers can also optionally support JTA-enabled distributed transactions, so JTA (as it relates to JDBC) is also briefly mentioned in Chapter 8.
Support for distributed computing is key to building enterprise applications. In this area, you’ll find APIs for web services, remote method invocation (RMI), object request brokers (like CORBA), and—last but far from least—Enterprise JavaBeans, a component architecture that brings it all together.
Web services have created quite a stir in the enterprise development domain by promising a new idiom for writing and using distributed services. Web services refer to services that are callable using an XML-based protocol and transmitted over HTTP, SMTP, and other communication protocols. Web services are exciting because, like CORBA, they provide a platform-independent approach to distributed computing; since they depend on ubiquitous formats and protocols (such as XML and HTTP), the endpoints in web service architectures can be implemented in any platform or language that supports these protocols. In other words, web services can be produced and consumed by nearly all modern programming languages and on all platforms.
But web services have some additional advantages that RMI and CORBA do not. Since the overall distributed computing architecture is generic and extensible, web services provide much more flexibility in terms of the physical implementation of the web services and their surrounding runtime support. A web service engine can be a full-blown application server with failover and load-balancing or a tiny runtime process on a handheld device. Programming models, APIs, object models, and the like are left up to the implementation platform, allowing them to be optimized for the particular environment.
The fundamental standard protocols used in web services today are SOAP (Simple Object Access Protocol) for interprocess communications and WSDL (Web Services Descriptor Language) for describing web services. In the Java community, a suite of standard Java APIs have been defined to help developers build and use web services. We discuss the two most important ones in this book: the Java API for XML Remote Procedure Calls (JAX-RPC) (JSR 101, JSR 224) and the SOAP with Attachments API for Java (SAAJ). SAAJ defines a standard API for basic, low-level messaging using SOAP. On top of this, JAX-RPC provides a standard API for interacting with web services using a remote method invocation paradigm in which a request to a web service is expected to result in an immediate response. Both of these APIs are covered in the web services tutorial in Chapter 12.
Remote method invocation (RMI) is a programming
model that provides a high-level, generic approach to distributed
computing. RMI extends the Java object-oriented programming
paradigm to distributed client/server programming: it allows a
client to communicate with a server by invoking methods on remote
objects that reside on the server. RMI is implemented in the
java.rmi
package and its
subpackages, which were introduced in Java 1.1 and were enhanced
in later versions of the Java platform.
The Java RMI implementation is full-featured but still
simple and easy to use. It gains much of its simplicity by
requiring both client and server to be implemented in Java. This
requirement ensures that both client and server share a common set
of data types and have access to the object serialization and
deserialization features of the java.io
package, for example. On the
other hand, this means that it is more difficult to use RMI with
distributed objects written in languages other than Java, such as
objects that exist on legacy servers. The default remote method
communication protocol used by RMI will allow only Java code to
interact with RMI objects. But you can also opt to use RMI/IIOP,
which was made a standard part of the core Java APIs in Version
1.3 of the Java platform. RMI/IIOP is an optional communication
protocol that allows RMI objects to interact with CORBA-based
remote objects. Since CORBA objects can be implemented in many
languages, this provides a bridge to systems implemented in other
languages.
The java.rmi
package
makes it easy to create networked, object-oriented programs.
Programmers who have spent time writing networked applications
using lower-level protocols are usually amazed by the power of
RMI. See Chapter 13 for
a tutorial on using RMI.
As we’ve just discussed, RMI is a distributed object solution that works especially well when both client and server are written in Java. It is more work, and therefore less attractive, in heterogeneous environments in which clients and servers may be written in arbitrary languages. For environments like these, the Java platform includes a CORBA-based solution for remote method invocation on distributed objects.
CORBA (Common Object Request Broker Architecture) is a
widely used standard defined by the Object Management Group (OMG).
The Java binding of this standard is implemented as a core part of
the Java platform in the org.omg.CORBA
package and its
subpackages. The implementation includes a simple Object Request
Broker (ORB) that a Java application can use to communicate (as
both a client and a server) with other ORBs, and thus with other
CORBA objects.
The interfaces to remote CORBA objects are described in a platform- and language-independent way with the Interface Definition Language (IDL). Sun provides an IDL compiler that translates an IDL declaration of a remote interface into the Java stub classes needed for implementing the IDL interface in Java or for connecting as a client to a remote implementation of the interface from your Java code.
A number of Java implementations of the CORBA standard are available from various vendors. This book documents Sun’s implementation, known as Java IDL. It is covered in detail in Chapter 14. The syntax of the IDL language itself is summarized in Appendix G, and the CORBA-related tools provided with Sun’s JVM are described in Appendix H.
Enterprise JavaBeans (EJB ) do for server-side enterprise programs what Java beans do for client-side GUIs. EJB is a component model for units of business logic and business data. Programming models that take business logic out of the client and put it on a server or in a middle tier have many advantages in enterprise applications. However, the task of writing this middleware has always been complicated by the fact that business logic must be mixed in with code for handling transactions, security, networking, and so on.
The EJB model attempts to separate high-level business logic from low-level housekeeping chores. And in the process, it attempts to leave the former to you, the enterprise developer, while the latter is delegated to the EJB server. A component in the EJB model is an object that implements business logic or represents business data. The difference between an enterprise bean and a run-of-the-mill RMI remote object or nonremote Java bean is that EJB components run within an EJB container, which in turn runs within an EJB server. The container and server provide features such as transaction management, resource pooling, lifecycle management, security, name services, distribution services, and so on. With all these services provided by the container and server, enterprise beans (and enterprise bean programmers) are free to focus purely on business logic.
The EJB specification is a document that specifies the contracts to be maintained and conventions to be followed by EJB servers, containers, and beans. Writing EJB components is straightforward: simply write code to implement your business logic, taking care to follow the rules and conventions imposed by the EJB model.
EJB components can also run within the larger J2EE framework. In addition to the standalone EJB component services, EJBs running within a J2EE server can be assembled with other components (like web components) into J2EE applications.
Unlike some of the other Java Enterprise APIs, the EJB API is just the beginning of understanding how EJB works. The key to understanding Enterprise JavaBeans lies in the interactions among beans, containers, and the EJB server. These interactions are described in detail in Chapter 6. In addition, the syntax for the abstract persistence language used in entity EJBs, EJB QL, is described in Appendix C.
Messaging provides an essential link for enterprise applications, and Java’s support for messaging includes Java Message Service (JMS ) and JavaMail for email-based messaging.
JMS (JSR 914) is the Java Enterprise API for working with networked messaging services and for writing message-oriented middleware (fondly referred to as MOM).
The word “message” means different things in different
contexts. In the context of JMS, a message is a chunk of data that
is sent from one system to another in an asynchronous manner. The
data serves as a kind of event notification and is almost always
intended to be read by a computer program, not by a human. In a
nondistributed system that uses the standard Java event model, an
Event
object notifies the
program that some important event (such as the user clicking a
mouse button) has occurred. In a distributed system, a message
serves a similar purpose: it notifies some part of the distributed
system that an interesting event has occurred. You can think of a
networked message service as a distributed event notification
system.
JMS is also a good complement to the synchronous communication provided by RMI, CORBA, and most web services built using JAX-RPC. When an RMI client, for example, makes a remote method call on a server object, the client will block until the remote method returns. JMS provides a way for you to communicate asynchronously with a remote process: you can send your message and carry on with useful work while the message is delivered and processed at the receiving end. If there’s a response from the receiver(s), a callback can be invoked on your end, and you can deal with it then.
Like JNDI and JDBC, JMS is an API layered on top of existing, vendor-specific messaging services. In order to use JMS in your application, you need to obtain a JMS provider implementation that supports your particular message server. Some J2EE application servers bundle their own JMS providers that you can use as message servers; some of them provide easy ways to bridge their application servers to other message services like IBM MQSeries or SonicMQ; others provide neither and leave it to you to obtain and install a JMS provider.
Chapter 11 provides a tutorial on using JMS, and Appendix E documents the syntax for JMS message selectors.
Email is another critical communication protocol for enterprise systems. Email is a widespread tool used for interpersonal messaging in a wide variety of contexts, from corporate communications to family reunion planning, as anyone reading this book is surely aware. In an enterprise application context, email can also be an important tool for end user event notifications (for example, a notice that a lower-priced flight has matched your travel profile), for content delivery (e.g., a weekly “ezine” delivered automatically from a content management system), and for system monitoring (e.g., a notice to a system administrator that connectivity to a critical information system has been lost).
J2EE’s tool for composing, sending, and receiving email is
the JavaMail API, contained in the javax.mail
package. For dealing with
various types of content in MIME-based email messages, a companion
API called the JavaBeans Activation Framework and provided in the
javax.activation
package is
used in conjunction with JavaMail (“activation” in the name refers
to activating a content handler to deal with a particular type of
content). Chapter 15 is
a tutorial on the use of these APIs.
[2] Java standards, called Java Specification Requests or JSRs, are defined through the Java Community Process. A complete list of JSRs can be found at http://www.jcp.org/en/jsr/all.
Get Java Enterprise in a Nutshell, Third Edition now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.