Oracle® Containers for J2EE Resource Adapter Administrator's Guide 10g (10.1.3.1.0) Part Number B28956-01 |
|
|
View PDF |
A typical enterprise application must access data on some sort of backend information system. A problem encountered by businesses today, when they want to adapt their applications to Web-based technology, is that their data is on older, legacy systems that were not designed to be Web-accessible.
For enterprise application integration, application servers are a natural point of integration between Web-based applications and legacy systems. J2EE Connector Architecture (J2CA) offers a standard framework for accessing these legacy systems through J2EE-compliant application servers such as Oracle Containers for J2EE (OC4J). Oracle J2CA, the OC4J 10.1.3 implementation of J2CA, supports version 1.5 of the connector architecture.
This chapter offers an overview of key J2CA concepts and issues, including the following topics:
What Are the Scenarios for Communication Through Resource Adapters?
What Are the Security Features of the J2EE Connector Architecture?
What Are the Interface Libraries of the J2EE Connector Architecture?
Note: For further information about topics discussed here and elsewhere in this manual, refer to the J2EE Connector Architecture Specification. Version 1.5 is current as of the OC4J 10.1.3 implementation and is available at the following location:http://java.sun.com/j2ee/1.4/docs/ |
The J2EE Connector Architecture defines a standard architecture for bidirectional connectivity between the J2EE platform and heterogeneous legacy systems, referred to as enterprise information systems. This is accomplished through components known as resource adapters. These terms are more fully defined shortly. The basic architecture is shown in Figure 1-1.
The architecture supplies a mechanism for an enterprise information system vendor (or third party) to provide a standard resource adapter to be used by J2EE applications in accessing the information system, and for an application server vendor to provide the support that allows a standard resource adapter to be plugged in to the application server.
The rest of this section covers the following topics:
An enterprise information system, or EIS, is a heterogeneous storage and retrieval system for enterprise data. Examples include enterprise resource planning (ERP) systems, customer relationship management (CRM) systems, mainframe transaction processing (TP) systems, other databases, and legacy applications that are not written in the Java programming language.
Legacy EISs have typically evolved over a significant amount of time through a significant amount of effort. Replacing these systems is usually not viable, so a mechanism is required to connect to them as is, preferably in a standard, reusable way.
A resource adapter is a software driver that an application server or an application client uses to connect to a specific EIS. An example of a resource adapter is a JDBC driver to connect to a relational database. Similarly, an ERP system or CRM system might include a resource adapter.
Initial solutions to the need for resource adapters involved technologies that were proprietary and nonportable. Without the J2EE Connector Architecture, there would have to be a custom resource adapter to connect each type of application server to each type of EIS vendor.
With the J2EE Connector Architecture acting as a standard resource adapter framework, each application server requires just a single implementation supporting the connector architecture specification, and each EIS requires just a single resource adapter that can plug in to any compliant application server.
In addition, the initial proprietary solutions did not necessarily support services such as connection management and pooling, transaction management, and security. The J2EE Connector Architecture supports all these services and more, using standard mechanisms.
Speaking in a little more detail now, we define a resource adapter as the aggregate of classes and meta data necessary for communication between a particular EIS and a compliant J2EE application server. A resource adapter plugs into an application server, running within the application server address space.
For those who are familiar with previous OC4J implementations of the connector architecture, this section summarizes enhancements in version 1.5 of the architecture and in the OC4J implementation.
Version 1.5 of the J2EE Connector Architecture represents a significant upgrade from version 1.0, including the addition of features for inbound communication. (Only outbound communication was supported in version 1.0.) Specifically, these new features, supported by the OC4J 10.1.3 implementation, include the following:
Lifecycle management contract
Work management contract
Message inflow contract
Transaction inflow contract
Support for multiple implementation classes for managed connection factories
These and other contracts are summarized in "What Are the J2EE Connector Architecture System Contracts?".
In addition to supporting the new J2EE Connector Architecture version 1.5 features, the OC4J 10.1.3 implementation provides the following enhancements:
Connection pooling enhancements
New connection-sharing features
Support for updates to the OC4J-specific configuration files without stopping the server
Closer integration with the JAAS security implementation for runtime permissions of resource adapters and for container-managed sign-on.
Two-phase commit for resource adapters
New metrics for connections and work management thread pools
Deployment of multiple versions of the same resource adapter, with each version available as a shared library to all applications. An application can be configured to import a specific version of the resource adapter and load all classes from the resource adapter
Deployment, undeployment, or reployment of a resource adapter without restarting the default
application
In the J2EE Connector Architecture, J2EE components communicate with resource adapters using system contracts that specify standard support in several key areas of functionality. Each of these contracts is partly implemented by an application server and partly implemented by a resource adapter so they can interact and collaborate in a standard way. (These contracts are also referred to as quality of service contracts.)
Here is a summary of the contracts:
Connection management enables an application component to connect to an EIS and enables an application server to use connection pooling for these connections. (Do not confuse this with JDBC connection pooling, which is a separate mechanism.) See Chapter 3, "Connection Management" for details.
Transaction management enables an application server to use a transaction manager to handle transactions across multiple EISs or resource managers. (A resource manager manages shared EIS resources). See Chapter 4, "Transaction Management" for details.
Security management provides authentication, authorization, and secure communication between an application server and an EIS. Also see "What Are the Security Features of the J2EE Connector Architecture?". For details about OC4J security for EIS connections, see the Oracle Containers for J2EE Security Guide.
Lifecycle management allows an application server to manage the startup and shutdown of a resource adapter, including a mechanism for bootstrapping a resource adapter when it is deployed or when the application server starts up, and for notifying a resource adapter when it is undeployed or when the application server shuts down. Also see "Resource Adapter Lifecycle: Startup and Shutdown" for related discussion.
Message inflow allows a resource adapter to deliver messages to endpoints (such as message-driven beans) in an application server. Message delivery is asynchronous. This support does not rely on any particular message provider and has a wide range of uses, including with Java Message Service (JMS) or Java API for XML Messaging (JAXM), for example. Also see "Introduction to the Message Inflow Contract".
Transaction inflow allows an imported transaction to be propagated to an application server by a resource adapter. Also see "Introduction to Imported Transactions and the Transaction Inflow Contract".
Work management allows a resource adapter to perform tasks through the use of units of work submitted to an application server and executed by a work manager. Such tasks may include calling application components or monitoring network endpoints, for example. The application server uses separate threads to execute different work units, and the resource adapter is spared from having to manage the threads itself. See Chapter 5, "Work Management" for additional information.
In the J2EE Connector Architecture, communication between an application component and an EIS can originate from either party, and a resource adapter may support either or both of the following:
Outbound communication—communication initiated by the application component
Inbound communication—communication initiated by the EIS
This section compares outbound and inbound communication and briefly discusses messaging systems as they are relevant to inbound communication.
In outbound communication, the resource adapter simply allows an application to connect to the EIS and communicate with it through some API—perhaps using an EIS-specific API, or perhaps through the standard Common Client Interface (CCI) described later in this chapter. The resource adapter is a passive library in this case; communication is synchronous and is initiated by the application. An application component can use the API (EIS-specific or CCI) to synchronously execute an EIS function or retrieve the results of one. (The resource adapter itself might use some proprietary mechanism behind the scenes to make this possible.) The application server enforces the transactional semantics associated with the connection.
In inbound communication, the resource adapter allows an entity or event outside the application server to initiate activity. An EIS might accomplish this by writing a message to a queue, for example. Communication is asynchronous and is initiated by the EIS. A resource adapter supporting inbound communication will typically use the work management contract and message inflow contract. A work unit associated with the resource adapter coordinates receipt of incoming communication from the EIS, delivery of this communication to an appropriate recipient (message endpoint) within the J2EE container, and then delivery of a response with desired results to the EIS, as appropriate. The application server creates and manages threads that are assigned to the work units, assigns message endpoint instances to handle communication delivery, and enforces the transactional semantics associated with delivery.
Most EISs use a messaging system for initiating communication with applications that reside outside the EIS, such as an application running in OC4J. For this reason, inbound resource adapters are typically associated with a messaging system, although it is possible for an inbound adapter to use some proprietary mechanism such as a simple socket connection to listen for communication initiated by an EIS.
There is more information about messaging systems, and message endpoints, in the next section, "Message Provider Pluggability Using the J2EE Connector Architecture".
Figure 1-2 depicts the communication flow for outbound communication, also indicating where the relevant system contracts govern.
Figure 1-3 depicts the communication flow for inbound communication, also showing where the relevant system contracts govern.
The J2EE 1.4 specification supports pluggability for a range of messaging systems, including JMS, through J2CA. A resource adapter intended for use with messaging typically supports one messaging system, or message provider, although there is no restriction on the number.
An outbound resource adapter provides the capability to send and receive messages in a synchronous manner using outbound communication. An inbound resource adapter provides the capability to asynchronously deliver messages from the message provider to a message endpoint, which is a message-driven bean (MDB) component in the application server. A bidirectional resource adapter provides both functions.
Note that most resource adapters that support inbound communication are based on a standard messaging system, such as a JMS implementation, so that the EIS can initiate communication in a standard manner.
For a brief introduction to a generic JMS resource adapter provided by Oracle, see "Introducing Oracle JMS Support and Generic JMS Resource Adapter".
Note: Resource adapters are now the recommended vehicle for plugging a messaging system into an application server. |
There are two separate aspects of security in a J2EE application that uses resource adapters:
The J2CA security contract controls access to an EIS.
Security permissions control access to application server resources, such as classloaders, threads, and sockets. These permissions appropriately restrict the behavior of an application running within OC4J.
The following sections summarize these topics:
To ensure secure interactions between a J2EE application and an EIS, the J2EE Connector Architecture allows application components to associate a security context with connections established to the EIS. This is accomplished through the J2CA security contract, between an application server and a resource adapter. This contract extends the connection management contract with functionality relating to secure connections. It also works in conjunction with the standard Java Authentication and Authorization Service (JAAS), supporting standard JAAS interfaces.
The security contract includes features for the following:
Propagating a security context, or subject, directly from a J2EE component to a resource adapter (for component-managed sign-on)
Propagating a security context, or subject, from an application server to a resource adapter (for container-managed sign-on)
The security contract supports two particular authentication mechanisms:
The commonly used "basic password" mechanism relies on a user name / password pair, contained together in a password credential object. The application server passes this object to the resource adapter for authentication.
The Kerberos version 5 mechanism ("Kerbv5" for short) is an authentication protocol distributed by the Massachusetts Institute of Technology. This mechanism uses a "generic credential" object that encapsulates credential information such as a Kerberos ticket. The application server passes this object to the resource adapter for verification.
Sign-on from a J2EE application to an EIS can be managed either by the application component or by the J2EE container (OC4J). Component-managed sign-on must be set up programmatically and does not involve OC4J-specific configuration. Container-managed sign-on can be set up either declaratively, through OC4J-specific configuration without any programming requirements, or programmatically, involving a combination of OC4J-specific configuration and programming requirements. Programmatic container-managed sign-on can use either a "principal mapping class" or a JAAS login module.
See the Oracle Containers for J2EE Security Guide for details about all these features.
An application server, such as OC4J, must provide a set of security permissions for use by a resource adapter executing in the managed runtime environment. The resource adapter must have appropriate and explicit permission to perform any sensitive operations, such as accessing resources that the application server controls (a classloader, for example).
If a resource adapter will require specific permissions, they must be indicated through <security-permission>
elements in the ra.xml
file. These permissions, however, can be overridden in an OC4J environment through <security-permission>
elements in the oc4j-connectors.xml
file. See "<security-permission>".
See version 1.5 of the J2EE Connector Architecture Specification for additional information.
The J2EE Connector Architecture includes the following interface libraries:
Common Client Interface (CCI)
This is a set of interfaces that can optionally be implemented by a resource adapter to provide a standard client-facing interface to use in accessing the associated EIS from J2EE components. If implemented, it is essentially a contract between a J2EE application and a resource adapter. Its use is not mandated by the connector architecture specification—a vendor-specific API can be implemented instead (such as a JDBC API for access to a database). However, to simplify access to a range of EISs from a range of J2EE components, support of the CCI by resource adapters is recommended. Such support guarantees that a resource adapter can be plugged into any J2EE-compliant development tool or enterprise application integration framework.
Service Provider Interface (SPI)
This is a set of interfaces, partly implemented by an application server and partly by a resource adapter, to provide the interface between the application server and resource adapter to manage physical connections to the EIS and to support the J2CA system contracts. The SPI interfaces are discussed throughout this book as appropriate, in the course of discussing the contracts.
The CCI and SPI interface libraries are in the packages javax.resource.cci
and javax.resource.spi
, respectively.
A resource adapter that implements the CCI provides a standard way for J2EE components to access the associated EIS. This simplifies the task of accessing multiple EISs from a single J2EE component.
The CCI can be used directly in a client application to access an EIS; however, it is more typical for a tools vendor to expose the CCI in the form of software developer kits (for runtime) or wizards (for design time) and for client applications to access an EIS through the tool. A resource adapter that supports the CCI can be plugged in to enterprise tools and other enterprise application integration frameworks in a standard way.
Communication through the CCI entails creating and executing an interaction to execute functions in the EIS. The sequence is to get a connection to the EIS, create an interaction, then execute the interaction. An interaction is represented by a class, provided with the resource adapter, that implements the CCI Interaction
interface. This interface specifies an overloaded execute()
method for performing operations on the EIS. An interaction object is obtained through an EIS connection and maintains an association with that connection. There are three kinds of interactions:
SYNC_SEND_RECEIVE
: Send a synchronous request to the EIS and receive an associated synchronous response. This is a standard request/response mechanism.
SYNC_SEND
: Send a synchronous request to the EIS, but without there being an associated synchronous response.
SYNC_RECEIVE
: Receive a synchronous response from the EIS, but without there having been an associated synchronous request. One scenario would be to use a SYNC_SEND
interaction to start a long job, then use a SYNC_RECEIVE
interaction sometime later, by which time the results should be ready.
The CCI InteractionSpec
interface provides the mechanism for holding properties for interactions. (Also see "Example: What Is an Interaction Spec?".)
Notes:
|
The classes, interfaces, descriptors, and other resources that compose a resource adapter are packaged in a RAR file—a Java archive file with the .rar
extension—for deployment. A RAR file must include at least the following:
The ra.xml
configuration file for the resource adapter
One or more JAR files containing the resource adapter implementation
It can be deployed in either of two ways:
Within an EAR file, in which case the resource adapter is available only to applications within the EAR file
By itself, in which case the resource adapter is referred to as standalone and is associated with the OC4J default application and available to all applications in the server instance
(OC4J is installed with a default configuration that includes a default application, also known as the global application. The default
application is, by default, the parent of all other J2EE applications in OC4J, except Application Server Control Console.)
Each standalone resource adapter is represented as a shared library, which, by default, is available to all applications. All code sources of a standalone resource adapter are added to a dedicated, shared loader that will be imported by all applications unless they are explicitly configured otherwise. When multiple versions of a standalone resource adapter are deployed, an application can be configured to import a specific resource adapter, so all resource adapter classes are loaded from the same adapter.
In addition to an ra.xml
file, there must be an oc4j-ra.xml
configuration file for each deployed resource adapter. This is an OC4J-specific file that you can include in the RAR file, or OC4J will create it automatically during deployment. Finally, the oc4j-connectors.xml
file, also OC4J-specific, is an enumeration of all resource adapters associated with an application, and may contain some additional configuration as well. For resource adapters deployed in an EAR file, there is a single oc4j-connectors.xml
file to enumerate the resource adapters, and OC4J will create it automatically if it is not found in the EAR file. For standalone resource adapters, there is a single oc4j-connectors.xml
file in the OC4J configuration directory and associated with the OC4J default application to enumerate the standalone resource adapters. OC4J will also create this file if it does not already exist. (See Appendix A, "OC4J Resource Adapter Configuration Files", for information about the OC4J-specific configuration files.)
Here are the contents of a sample RAR file:
META-INF/ra.xml META-INF/oc4j-ra.xml howto.html images/icon.jpg ra.jar cci.jar
For this example, assume the following:
The ra.jar
file contains the resource adapter implementation.
The resource adapter exposes the CCI APIs, contained in cci.jar
, for its client interface.
Applications may need to access adapter-specific classes that are bundled in the RAR file. In the case of standalone resource adapters, these classes are available to all applications that are deployed within OC4J. In the case of resource adapters deployed in an EAR file, the classes are available only to modules deployed in the same EAR file.
Here are the contents of a sample EAR file (with only oc4j-connectors.xml
and myRar.rar
being related to resource adapters):
META-INF/application.xml META-INF/oc4j-connectors.xml myRar.rar myWar.war myEjb.jar
You can use any JSR-88-compliant tool to deploy resource adapters, including Application Server Control. (See "A Brief Overview of OC4J Administration" for additional information.) Use the Application Server Control Console deployment plan editor to specify OC4J-specific parameter settings.
During deployment, OC4J decompresses the RAR file and takes the following actions regarding OC4J-specific deployment descriptor files:
Creates a deployment directory for the resource adapter, of the following form:
j2ee/instance/application-deployments/app_name/ra_name
The OC4J instance, instance
, is always home
in a standalone environment and home
by default in an Oracle Application Server environment. For a standalone resource adapter, the application name, app_name
, is default
and the resource adapter name, ra_name
, is what you specify during deployment. For a resource adapter deployed in an EAR file, the application name is what you specify during deployment, and the resource adapter name is the RAR file name without the .rar
extension.
A RAR name must be unique within an OC4J instance. If you attempt to deploy a RAR that has the same file name as a RAR that was already deployed in an OC4J instance, the exception NullPointerException
occurs.
Generates an empty oc4j-ra.xml
file if you did not provide one in the RAR file, placing it in the resource adapter deployment directory (ra_name
).
For a standalone resource adapter, adds a <connector>
entry in the oc4j-connectors.xml
file that is associated with the OC4J default application, creating the file if it does not already exist.
For a resource adapter deployed in an EAR file, if you did not provide an oc4j-connectors.xml
file in the EAR file, creates oc4j-connectors.xml
in the application deployment directory (app_name
) and adds a <connector>
entry.
Each resource adapter must have a unique name when it is deployed:
Deploying, undeploying , or redeploying a resource adapter does not require a restart of the default
application.
The resource adapters within an application EAR file are deployed when the EAR file is deployed. If no name is specified in the oc4j-connectors.xml
file, then the name is the same as the RAR archive name.
A unique name must be provided for each standalone resource adapter during deployment.
See the Oracle Containers for J2EE Deployment Guide for further information.
When an application is deployed, the application imports all standalone resource adapters that were previously deployed, by default.
When a standalone resource adapter is deployed, all running applications that were previously deployed, except the default
application, are asked to import the resource adapter. So, an application that is dependent on a standalone resource adapter can be deployed before the resource adapter as long as the application does not attempt to use the resource adapter prior to its deployment. Take special care when you deploy a standalone resource adapter after a dependent application because the application might have already loaded classes. Unexpected exceptions will occur if importing the standalone resource adapter causes previously loaded classes to be subsequently loaded by a different loader.
A resource adapter can look up and use another resource adapter. Because each standalone resource adapter has it's own classloader, it is necessary for standalone resource adapters to import other deployed standalone resource adapters and shared libraries. By default, a standalone resource adapter will import all previously deployed standalone resource adapters and all shared libraries. A standalone resource adapter must be deployed before any dependent standalone resource adapters.
You can deploy multiple standalone resource adapters that contain classes of the same name. Because all standalone resource adapters are available to all applications by default, any application that uses a standalone resource adapter for which multiple versions are deployed must explicitly specify which of the versions it will use. The application must use only one version of a resource adapter for which there are multiple versions.
An application specifies which standalone resource adapters it will use in the configuration file orion-application.xml
. For example, two standalone resource adapters that contain some of the same classes are deployed with the names adapterA
and adapterB
. The following connector
elements are in J2EE_HOME
/config/oc4j-connectors.xml:
<connector name="adapterA" path="adapterAFileName.rar" > <connector name="adapterB" path="adapterBFileName.rar" >
To configure an application to use only adapterA
, you would add the following elements to the application's orion-application.xml
file:
<imported-shared-libraries> <remove-inherited name="adapterB"/> </imported-shared-libraries>
Because both standalone resource adapters are imported by default, it is not necessary to explicitly import adapterA
.
An alternative configuration follows:
<imported-shared-libraries> <import-shared-library name="adapterA"> <remove-inherited name="*"/> </imported-shared-libraries>
Note: While it is possible to version shared libraries using a version number, it is currently not possible to do this with standalone resource adapters. Each deployed resource adapter must have a unique name. |
Deploying a resource adapter to the default application will prevent the resource adapter from using any standalone resource adapter that is deployed as a shared library. Resources deployed as shared libraries are not imported by the default
application.
Resource adapters provided with Oracle Application Server include an Oracle generic JMS adapter and third-party adapters.
JMS specifies an enterprise messaging API that enables the use of portable, message-based applications for communication in a J2EE environment. There are a number of different JMS providers with a range of guarantees regarding reliability and quality of service. OC4J currently includes a proprietary resource provider mechanism for plugging in different JMS providers.
In Oracle Application Server 10g Release 3 (10.1.3.1.0), Oracle itself provides two JMS implementations. One, Oracle JMS (OJMS), is the JMS interface to the Oracle Database Streams Advanced Queueing (AQ) feature. The other, OracleAS JMS, is a native Java implementation that provides file-based persistence and is tightly integrated with OC4J.
Oracle also provides a J2CA 1.5-compliant JMS resource adapter that enables OC4J-managed applications to have a unified mechanism to access any JMS provider, regardless of whether their level of J2CA support is at version 1.5. This Oracle JMS resource adapter, referred to as the "generic JMS resource adapter", does not use any Oracle proprietary APIs. Supported JMS implementations include, for example, OJMS, OracleAS JMS, and third-party products such as IBM WebSphere MQ JMS, Tibco Enterprise for JMS, and SonicMQ JMS.
The Oracle generic JMS resource adapter is the recommended path for JMS usage in the OC4J 10.1.3 implementation. It is based on the J2CA 1.5 and JMS 1.1 and 1.02b standards and includes minimal customization for OC4J, and none for individual JMS providers. It is intended to seamlessly integrate any standard JMS implementation. (Note that the generic JMS resource adapter cannot typically provide optimal access to a particular JMS provider, given that many JMS providers support custom extensions.) It also has a number of distinguishing features in the following areas:
JNDI mapping
MDB integration (including dynamic adjustment to changing message load)
Global transaction support (including standards-based support for transaction recovery)
True generic JMS connection pooling
Deployment convenience (including order independence)
Lazy resolution of JMS operations (including start order independence, tolerance of dynamic management such as starts and stops of JMS providers, and connection retries in case of provider failure)
Performance
JSR-77 statistics
Typically, the Oracle generic JMS resource adapter is used in situations where the EIS being connected to is a JMS resource provider. However, it can also be used in situations where an EIS uses JMS messaging as a means of notifying J2EE application components. In this case, the JMS resource adapter (along with a JMS resource provider) can be used instead of the inbound communication features (if any) of the EIS-specific resource adapter. This two-adapter solution, where the EIS-specific adapter is used for outbound communication and the Oracle generic JMS resource adapter is used for inbound communication, enables bidirectional communication between the EIS and J2EE application where it may otherwise not be possible.
Refer to the Oracle Containers for J2EE Services Guide for details about the Oracle JMS implementation and JMS resource adapter.
You can use J2CA 1.5-compliant or 1.0-compliant third-party resource adapters with the OC4J 10.1.3 implementation, to connect to a variety of backend systems, such as SAP, PeopleSoft, J.D. Edwards, and Siebel.
Oracle provides some third-party resource adapters as part of the full Oracle Application Server suite of products.
This section discusses engineering and technician roles that are addressed by the J2CA specification, which of these roles represent target audiences for this book, and which topics of this book are of interest to each target audience.
The J2CA specification is addressed to the following roles:
Resource adapter provider
This is an expert in the technology relating to a particular EIS.
J2EE application server provider and container provider
These roles are addressed separately in the connector architecture specification, but Oracle fills both functions with Oracle Application Server, which includes the OC4J containers and related services.
J2EE application component provider
This is for J2EE components that access one or more EISs. Ideally, the component provider is programming against convenient Java interfaces produced by a software development tools vendor, based on the CCI.
Enterprise tools vendor
Products from tools vendors may include data-mining and function-mining tools to analyze the scope and structure of EIS data; analysis and design tools for design based on EIS data and functions; code generation tools to produce Java classes to access EIS data and functions; and deployment tools.
Application assembler
The assembler packages application components into deployable entities.
Application deployer
The deployer loads a deployable entity into a target environment, such as an OC4J instance.
System administrator
The administrator manages and configures the environment of J2EE containers, resource adapters, and EISs.
Of the roles introduced in the preceding section, the primary audience for this document is system administrators—individuals who will administer the OC4J environment, including resource adapter configuration. Application component providers and resource adapter providers are secondary audiences.
Topics in this book may be of interest to these audiences as indicated in Table 1-1.
Table 1-1 Audiences and Topics of Interest