The J2EE Application Programming Model


The previous section provided you with a contextual overview of the J2EE architecture, which is an excellent jumping-off point for a discussion of the J2EE architecture. However, to understand how to implement a J2EE solution, you do need to understand the J2EE Application Programming Model, which is shown in Figure 5.3.

Figure 5.3. The elements of the J2EE Application Programming Model.

graphics/05fig03.gif

The objective of the J2EE Application Programming Model is to provide an understanding of the technical scope of the J2EE services and technology components that can constitute a J2EE solution and hence provide guidance on how they can be used. The following sections of this chapter will reference this model and focus on explaining each of its constituent elements.

Note

Because the technical details of a J2EE client have already been explained in the previous section of this chapter, they will not be discussed in the remaining sections of this chapter.


The J2EE Application Server Layer

All J2EE solutions are developed, tested , and deployed in the context of application servers that are certified with the J2EE platform, such as WebLogic Server. If you are learning to develop J2EE solutions, inarguably you will need to become familiar with a J2EE server.

Note

The term J2EE server can also be used instead of J2EE server.


As illustrated in Figure 5.3, the J2EE server is effectively the nucleus of all J2EE solutions. Depending on the context in which it is used, it either serves as the operating system for a J2EE application, or, if it is part of an application infrastructure solution, as in the case of WebLogic Platform, it serves as an Internet platform/operating system for Web-based solutions.

For more information on WebLogic Platform 7.0, which includes WebLogic Server 7.0, see "Employing BEA's Unified, Simplified, and Extensible Formula for Application Infrastructure: WebLogic Platform 7," p. 268 .


The primary role of an application server is to provide an environment, through the employment of the Web and EJB containers, for the execution and management of J2EE components (Servlets, JavaServer Pages, and EJBs). The J2EE server containers are the interface between a J2EE component and the low-level platform-specific functionality that supports that component.

J2EE containers are configurable based on the deployment requirements of a J2EE component or application, which can customize the underlying support services provided by the J2EE server, for example security, transaction management, Java Naming and Directory Interface (JNDI) lookups, and remote database connectivity. The J2EE containers can also provide non-configurable services such as enterprise bean and servlet life cycle management, database connection pooling, data persistence management, and access to the J2EE platform APIs.

Note

What sets apart the best J2EE servers from the rest is how well a vendor can implement a highly available, performance-oriented, and scalable J2EE container architecture.


The Operating System Layer

The bottom layer of a J2EE server is the native operating system (OS) on which it runs. The OS ultimately controls the memory, I/O, and CPU resources assigned to the J2EE server. Even though all J2EE servers are configurable, they generally consume large amounts of these resources, so the OS may have to be configured to accommodate this.

Note

Before installing any J2EE server, please review its platform-specific documentation regarding installation and configuration.


Java Virtual Machine (JVM) Layer

The objective of the JVM layer is to make the choice of the OS development and deployment environments transparent to the Java developer. To enable this transparency to the developer, JVMs are hardware- and OS-dependent because they must interface with the native OS APIs.

At a high-level, the primary job of the JVM is to load Java class files that contain pre-execution Java byte code and translate them into native machine instructions, which are then executed by the respective operating system. The JVM controls memory management by garbage collecting unreferenced memory and providing heap and stack memory allocation. The JVM also provides classes that the application developer uses to interact with the OS.

Note

All JVMs are configurable to the type of OS and hardware they are running on, as well as the applications they are supporting.


There are many JVMs that are available in the marketplace today providing different techniques in the compilation and execution of Java code and the overall management of the loaded Java class files. The most popular JVM is the Java HotSpot VM provided by Sun, which is installed with most J2EE servers. However, BEA has opted to select the WebLogic jRockit JVM, which is more performance-oriented in its design and architecture to support enterprise applications.

For more information on the WebLogic jRockit JVM, see "An Introduction to the WebLogic Platform 7.0," p. xxx . (Chapter 9)


The J2EE Application Server Execution Environment

The execution environment uses the JVM to control applications running within the J2EE server, which are primarily Web-based EJB applications. These applications require resources and services such as memory, threads, database connections, and network connections, which are controlled by the J2EE server execution environment. The server execution environment is also responsible for bootstrapping the system, handling failover, and the clustering of Web and EJB containers.

Note

Clustering is a mechanism to share resources and information across two or more computers.


The J2EE Services Layer

The J2EE Application Programming Model shown in Figure 5.3 essentially wraps the application tiers in the context of containers (Application Client, Web, and EJB containers) through the use of interfaces and APIs. This approach implies that you need only communicate with the container through a familiar interface or API rather than attempting to manage the complexities of the enterprise environment.

The J2EE containers have access to this J2EE service layer, which consists of two parts : the API and the service implementation. The APIs are the interfaces or contracts used by the application programmer to use the services. The service implementation is the underlying Java software classes, such as JDBC and JMS, providing the service, which is provided by a J2EE server vendor as long as it adheres to the J2EE service API specification.

In this section only the J2EE APIs in the J2EE Services Layers will be discussed because the service provider classes are only relevant to J2EE software vendors .

The Remote Method Invocation (RMI) Service

Remote Method Interface (RMI) is Java's native mechanism for object-oriented JVM to JVM synchronous communication. RMI enables an object in one JVM to access an object in another JVM using the same semantics for accessing local Java objects, with the exception that RMI-based objects must catch exceptions associated with network failures (that is, java.rmi.RemoteException ).

Where Is RMI Used in J2EE?

RMI is the principle mechanism used by clients to access EJBs. Clients are usually servlets, JSPs, or Java applications, but they can also be CORBA applications and Java applets. The EJB container does not support HTTP and cannot be accessed directly over the Web. RMI is also used by Web containers and EJB container components to access CORBA or RMI-based services external to a J2EE server.

Note

EJB services can be deployed as Web Services automatically in WebLogic Server 7.0; therefore they can be accessed over the Web via HTTP.


Because J2EE is a distributed architecture, RMI is critical to its inner workings. However, the use of RMI is concealed by the EJB container, which generates RMI code and makes RMI calls without the explicit involvement of the application developer.

How Is RMI Used in J2EE?

The RMI service is an environment used by Java applications when performing distributed object computing.

According to the RMI specification from Sun, RMI has the following features:

  • Stubs and skeletons allow transparent communication with a J2EE component outside the local JVM. The stub and skeleton classes handle all data marshalling and network transmission issues. The transport protocol used by RMI is either Internet-Inter-Orb-Protocol (IIOP) or Java Remote Method Protocol (JRMP).

  • The RMI object registry or RMI naming service maps a name to a remote object. An RMI client program passes the name of the requested RMI object to the Registry. If the name is found, a remote object reference is returned to the client. The client uses the reference to connect to the RMI object.

  • Dynamic class loading, which allows objects transmitted over RMI to be loaded when they are discovered .

  • HTTP tunneling, which embeds RMI calls within the body of an HTTP post request, and receives the return information in the body of an HTTP response.

  • Object activation in RMI allows objects to execute on an as-needed basis. That is, RMI objects that are registered as such can be activated if they are not currently executing. RMI objects can also be set up to be started manually.

  • Distributed Garbage Collection (DGC) provides a way for an RMI server to remove unused objects from its address space hence providing lifecycle management for RMI objects. DGC maintains reference counts for objects so that when an object is not referenced it is moved into the JVM garbage collection bin. DGC also performs polling and maintains timers to determine whether connections are alive . If a connection times out, reference counts are decremented and the RMI server object may become eligible for garbage collection.

J2EE servers must implement these features to provide a J2EE-compliant RMI service. The following list shows how a J2EE server uses these RMI features:

  • Stubs and skeletons. The J2EE server generates stubs and skeletons for internal use in various places (EJBs, JNDI, and so on).

  • RMI object registry. A J2EE server uses JNDI for object reference lookup and persistent storage.

  • Dynamic class loading. A J2EE server has its own class loaders for dynamically loading classes.

  • HTTP tunneling. A J2EE server provides HTTP tunneling for RMI.

  • Object activation. The J2EE server provides object activation for EJB objects by loading them at startup time or by dynamically loading them during live deployment.

  • Distributed Garbage Collection (DGC). Object life cycle is controlled by the J2EE server. In particular, DGC lifecycle management is not used by the EJB container.

RMI is implemented using a number of underlying data transfer protocols. The most commonly used protocols are IIOP and JRMP, which do have their differences as follows :

  • Both protocols provide the basic stub/skeleton data marshalling and network communication, but JRMP has a timeout mechanism, used with DGC, which is not present in IIOP.

  • You cannot use DGC with IIOP.

  • IIOP cannot use the RMI object registry and instead must use another mechanism, such as JNDI.

  • JRMP uses Java object serialization for data marshalling.

  • IIOP uses the Common Data Representation (CDR) standard for data marshalling, which is defined by Object Management Group (OMG).

Because the J2EE server does not explicitly use JRMP features or provides a replacement, it can use IIOP and JRMP interchangeably.

The Details of an RMI Method Call

To make an RMI method call, the RMI developer must first define and create an interface on a remote object that extends the java.rmi.Remote interface, which will describe the methods available to remote client programs. The developer must also write the Java code to implement the methods for that remote interface. This code serves as the server-side RMI object.

The RMI interface and server-side files are compiled by the Java compiler. The class files created from the RMI interface compilation are used by the RMI compiler (rmic) to generate the stub and skeleton proxy object class files. RMI clients use these stub or proxy objects to access RMI objects.

Referencing Figure 5.4, the following steps describe a simple RMI method call:

Figure 5.4. A simple example of an RMI call.

graphics/05fig04.gif

  1. The client program obtains an object reference (proxy object) from the RMI object repository.

  2. The client program calls a method in the proxy object, passing arguments as native types or Java objects.

  3. The proxy object connects to the remote RMI server. Data is marshalled using CDR (for IIOP) or Java object serialization (for JRMP) and the data packet is shipped over the network to the waiting RMI server.

  4. The server proxy object unmarshals the data and issues a call down to the corresponding RMI object.

  5. The RMI object executes the application's code and returns the result to the server proxy object.

  6. The server's proxy object marshals the result and transmits it back to the waiting client's proxy object.

  7. The client's proxy object unmarshals the packet and returns the result to the client application.

  8. The client application continues processing as if the call were made in its own address space.

For technical information on RMI in the context of WebLogic Server 7.0, see "Distributed Processing Using RMI," p. 385 .


The Java Naming and Directory Interface (JNDI) API

The Java Naming and Directory Interface (JNDI) is an API that describes hierarchical structures. The "Naming" part associates names with objects. The "Directory" part associates attributes of those objects with the names . JNDI provides a way to store global information available to Web and EJB containers.

Where Is JNDI Used in J2EE?

JNDI is primarily used for looking up J2EE resources. JNDI stores important resources, such as JMS connection factories, JDBC data sources, J2EE resource adapters, environment variables , JavaMail drivers, RMI names, and JTA resource managers.

JNDI is also used for storing state information for session beans.

Tip

JNDI is a convenient place to store singleton objects because EJBs cannot store static objects.


How Is JNDI Used in J2EE?

There are three parts to the namespace hierarchy stored in JNDI, as shown in Figure 5.5.

Figure 5.5. A simple JNDI hierarchical tree presentation.

graphics/05fig05.gif

At the top of the tree is the root context. This defines the start of the namespace. The root context contains objects and subcontexts. A subcontext contains objects and other subcontexts. An object represents the leaf in a tree. This is the information that was stored in the tree; everything else is just organizational information.

For a Web or EJB component program to use JNDI it must first establish a connection to the J2EE server's JNDI service. The JNDI driver and root context are specified in two JVM system variables, java.naming.factory.initial and java.naming.provider.url . The initial factory context specifies the JNDI driver and the provider URL specifies the root context.

To connect to the JNDI service, the Web or EJB component must get the JNDI initial context. The javax.naming.InitialContext object contains the connection information for JNDI. Once connected to JNDI you can use the Context interface of the javax.naming package for looking up, binding, unbinding, and renaming objects as well as creating and destroying subcontexts.

For technical information on JNDI in the context of WebLogic Server 7.0, see "Locating Named Services Through JNDI," p. 447 .


The Java Database Connection (JDBC) API

The Java Database Connection (JDBC) is a Java API for accessing table data such as that usually found in relational databases. JDBC is a set of classes and interfaces that allows Java programs to use SQL statements against any data source written to the JDBC specifications.

The primary JDBC interfaces used with J2EE are the following:

  • javax.sql.DataSource is a factory for connection objects. The data source manages database resources and provides access to the database.

  • java.sql.Connection represents a connection to the underlying data source.

  • java.sql.Statement contains information necessary to issue an SQL request to the database. java.sql.PreparedStatement and java.sql.CallableStatement are subclasses of java.sql.Statement used for SQL prepared statements and stored procedures respectively.

  • java.sql.ResultSet contains the row results from an SQL query.

Where Is JDBC Used in J2EE?

JDBC is used when coding servlets, JSPs, session beans, and bean-managed persistence (BMP) entity beans that need to access relational databases from vendors such as Oracle or Sybase. JDBC is also used by the EJB container when writing container-managed persistence (CMP) entity beans. However, when CMP is used the developer does not write database code. Instead, the EJB container generates and executes the appropriate JDBC code to access the database.

Note

Both BMP and CMP are discussed later in this chapter in the section on Enterprise Java Beans.


How Is JDBC Used in J2EE?

When using JDBC, several steps are involved. First, a JDBC DataSource object must be registered with JNDI. A DataSource object represents a data repository, such as a file or a DBMS connection. The DataSource object typically supports connection pooling, distributed transactions, and access to the JDBC driver.

After a DataSource object is registered with JNDI, programs can access it, retrieve connections and issue SQL statements. However, to use a DataSource object, Web components and EJB components must define references to the JDBC resources in their deployment descriptors (ejb-jar.xml for EJBs and web.xml for Web components). Listing 5.1 shows JDBC resource references for a servlet and an EJB.

Listing 5.1 JDBC Resource References for an EJB and Servlet
 ejb-jar.xml <enterprise-beans>     <entity>      . . .       <resource-ref>         <res-ref-name>jdbc/myPool</res-ref-name>         <res-type>javax.sql.DataSource</res-type>         <res-auth>Container</res-auth>       </resource-ref>      . . . </enterprise-beans web.xml <web-app>     <servlet>      . . .     </servlet>     <resource-ref>         <res-ref-name>jdbc/myPool</res-ref-name>         <res-type>javax.sql.DataSource</res-type>         <res-auth>Container</res-auth>     </resource-ref>      . . . </servlet> 

Tip

DataSource objects are administered objects , which means they must be registered with the J2EE server. In WebLogic Server 7.0, this can be performed via the Web-based WebLogic Administration Console.


After the DataSource objects are registered and the Web and EJB components are deployed, they can be used by J2EE clients.

Listing 5.2 describes a simple JDBC example for accessing a table and retrieving a result set.

Listing 5.2 A Simple JDBC Example for Accessing a Table and Retrieving a Result Set
 Connection con=null; try {      InitialContext ic = new InitialContext();      //Look up the DataSource in JNDI      DataSource ds = (DataSource) ic.lookup("myDataPool");      //Obtain a connection to the database      con =  ds.getConnection();      //Create and prepare a statement to access the database      PreparedStatement ps = con.prepareStatement(          "select * from MyTable where id=?");      ps.setString(1,"999");      //Execute the query and receive the results      ResultSet rs = ps.executeQuery();      //Read the ID from the MyTable table in the database      int id = rs.getInt("id"); } catch (Exception ex) { . . . } 

For technical information on JDBC in the context of the WebLogic Server 7.0, see "Accessing Data Repositories Using JDBC," p. 403 .


The Java Transaction (JTA) API

Transactions are used to cause a set of related operations to perform like a single isolated operationSingle Unit of Work. A single operation either succeeds (it is committed) or fails (it is rolled back). There are no partial successes or failures. For isolated operations, data used by the operation is not changed by other programs.

Because J2EE is a distributed architecture, transactions can span multiple J2EE servers, databases, or other resources. For local transactions, which do not span resources, J2EE resources can manage their own transactions. For distributed transactions, J2EE requires a transaction manager to control the two-phase commit protocol. The two-phase commit protocol is used to guarantee that all participants in a distributed transaction agree to either commit or rollback an operation. Resources participating in a distributed transaction must be XA-compliant.

Where Are Transactions Used in J2EE?

Referencing the J2EE Architecture diagram shown in Figure 5.2, transactions are typically requested from the client tier and then executed and managed by the server-side business tier .

Transactions are controlled either programmatically or declaratively using statements in a deployment descriptor. Because multiple components can be part of a transaction, the J2EE container must forward the transactional context to each participant. JDBC and the Java Transactional API (JTA) provide methods for programmatic transactional control. JDBC transactions are controlled using a java.sql.Connection interface, obtained by calling the getConnection method from the JDBC DataSource. JTA transactions are controlled using an object implementing the javax.UserTransaction interface. These objects are either retrieved from JNDI under the name javax.transaction.UserTransaction , or from the session context of a session bean or from the message context of a message bean.

Entity beans cannot use programmatic transaction controls. Declarative or container-managed transactions are used by session, message, or entity beans. An EJB must be identified as using container-managed transactions in its deployment descriptor. For this style of transaction, each method is assigned a transaction attribute. There are six types of transaction attributes, but the most commonly used value is "Required." Setting a transactional attribute "Required" for a method implies the method will always run in the context of a transaction. If a transaction is already in effect, the method will use it. If a transaction is not in effect, the method's entry and exit points demarcate a new transaction. Figure 5.6 illustrates the transaction options available to the J2EE components.

Figure 5.6. The transaction options available to the J2EE components.

graphics/05fig06.gif

These options operate as follows:

  • Servlets, JSP, and Java application and applet clients must use programmatic transactions.

  • Session and Message beans can use either programmatic transactions or use declarative transactions.

  • Entity beans must use declarative transactions.

  • Transactions can be programmed using JDBC transactions or the Java Transaction API. JTA supports distributed transactions.

  • Declarative transactions, controlled by the EJB container, and programmatic transactions pass transactional context to EIS systems.

Listing 5.3 describes a simple deployment descriptor declaring an EJB that uses container-managed transactions for all its methods. The transaction attributed is set to "Required." The EJB first has to have its transaction type set to "Container" or "Bean."

Note

Bean-managed transactions use JDBC or JTA explicitly.


Listing 5.3 Transaction Elements in the ejb-jar.xml
 <ejb-jar>   <enterprise-beans>      <entity>        <ejb-name>MyBean</ejb-name> . . .       <transaction-type>Container</transaction-type> . . .     </entity>   </enterprise-beans>   <assembly-descriptor>     <container-transaction>       <method>         <ejb-name>MyBean</ejb-name>         <method-name>*</method-name>       </method>       <trans-attribute>Required</trans-attribute>     </container-transaction> </assembly-descriptor> 

In Listing 5.3, the <container-transaction> keyword defines the method level transaction for EJBs described by the deployment descriptor. The <trans-attribute> keyword describes how the container should manage transactions when executing a method.

Listing 5.4 describes a skeleton Servlet class using programmatic transactions. First an object implementing the UserTransaction is retrieved from JNDI. Next the begin method is called on the object, which starts the transaction. At this point, you can add business logic relating to a transaction, such as an SQL statement. If the business transaction is successful, the commit method is called, which causes all changes to be permanent. If an exception occurs the transaction is rolled back.

Listing 5.4 Programming Transactions in J2EE
 public class MyBusiness extends HTTPServlet {     public void getPost(HttpServletRequest req,             HttpServletResponse res)     {         UserTransaction ut=null;         try         {             Context c = new InitialContext();             ut = (UserTransaction)c.lookup(                     "javax.transaction.UserTransaction");             ut.begin()             /...do business             ut.commit();         }         catch (Exception e)         {             ut.rollback();         }     } } 

Container-managed transactions do not require special coding to start and commit or rollback transactions as this is managed by the EJB. However, if a transaction must be aborted, EJBs must call the setRollbackOnly method of the EJBContext object to notify the EJB container. The container will mark the transaction and it will be rolled back at the earliest opportunity.

For technical information on JTA in the context of WebLogic Server 7.0, see "Managing Java Transactions Using JTA," p. 527 .


The Java Messaging Service (JMS)

The Java Messaging Service (JMS) API provides J2EE programs with loosely coupled , loosely typed distributed communication. There are two types of users of JMS: consumers and producers . Producers send messages to a repository where they can later be retrieved by a consumer. This is in contrast to the synchronous, strongly typed mechanism used in remote procedures calls (RPC), such as with RMI. With JMS, the producer only needs to know the message format and the message destination. With RPC, the caller must know the argument data types and the lifecycle of the caller's methods is intertwined with the receiver's methods.

The primary functions provided by JMS are as follows:

  • Persistent and non-persistent messages: Messages are always delivered unless the provider fails. If persistent messages are sent, messages are written to a reliable data store. If a provider fails, it will retransmit the messages upon restart.

  • Asynchronous and synchronous transmission and delivery of messages: Messages are transmitted either using synchronous messaging where the producer waits for the message to be consumed or asynchronous messaging where the producer posts the message to a repository and continues processing. Similarly, the consumer can either wait for incoming messages or specify a receiver thread to be notified when messages arrive .

  • Message filtering: Filtering is done using message selectors. Properties are associated with a message and consumers wait for messages matching those properties. Consumers can also specify fields in the message header and only receive messages matching those values.

  • Message types: JMS messages consist of a header, optional properties, and an optional body. The header holds the message destination, creation time, priority, and so on. The properties are set by the developer when message filtering is used. The main content of the message is in the body. The consumer receives the message and extracts the header, properties, and body of the message. JMS supports five message types: text, keyword and value pairs, byte streams, mixed primitive data type streams, and Java objects.

  • Transactions: JMS supports both local and distributed transactions. Local transactions enable a producer or consumer to identify a group of messages that must be processed as a whole. However, the consumer and producer do not share the transaction. The transaction is only on the producer's or consumer's end. The developer must call the commit or rollback methods explicitly. With distributed transactions using JTA or container-managed transactions for EJBs, the message consumer can associate message consumption with database updates and communications with other transaction-aware components.

The JMS API has a number of basic components. The starting point is the connection factory. The connection factory allows a J2EE client to connect to a JMS provider. The connection factory is stored in JNDI. Using the connection factory a developer obtains a connection, which is a virtual link to a JMS provider. Using the connection, a session is created that serves as a single-threaded context for producing and consuming messages as well as maintaining transactional and reliability controls. Using a session, message producers and consumers are created to send and receive messages to a particular destination. After this set-up is complete, messages are exchanged.

JMS supports two models for delivering messages, Point-to-Point (PTP) and Publish/Subscribe (pub/sub).

PTP messages are delivered to one consumer. JMS stores PTP messages in a queue that reside there until a consumer removes them. The receiver sends an acknowledgment to the provider after successfully processing the message.

Publish and subscribe messages are delivered to all consumers who have registered to receive messages. JMS stores pub/sub messages in a topic, which is a subject identity in the message queue. A topic consumer can only receive messages after it subscribes to a topic. A topic consumer must also be active to receive messages, unless it is using a durable subscription.

Topics are commonly used in systems with multiple consumers and a single producer. Queues are commonly used when a single or multiple producers send messages to a single consumer. These scenarios are illustrated in Figure 5.7:

Figure 5.7. A simple illustration of a JMS Provider scenario.

graphics/05fig07.gif

  • Several JMS applications send messages to Queue #1.

  • Messages for Queue #1 are written to persistent storage so they can be recovered and delivered in case of a system or application failure.

  • Messages are delivered to single application handling Queue #1 processing.

  • A single producer sends messages to Topic #1. The producer broadcasts messages to all listeners of the topic.

  • Messages for Topic #1 are written to persistent storage so they can be recovered and delivered in case of a system or application failure.

  • A copy of the topic message is delivered to each listening consumer.

Note

Persisting the messages to a persistent store is optional.


Where JMS Is Used in J2EE?

JMS is primarily used to deliver messages to message-driven beans (MDB). MDBs reside in EJB containers and receive messages asynchronously. MDBs can use container-managed transactions and interact with other J2EE components, such as entity beans, as part of their transactions. They can also participate in distributed transactions.

JMS is also used to integrate legacy applications with J2EE applications. Many legacy applications use messaging products, such as MQSeries and TIBCO that have JMS interfaces. JMS is also used for event notification, where a J2EE component is a producer and a number of client applications are consumers.

How JMS Is Used in J2EE?

To use JMS in a J2EE, a JMS connection factory and destination (queue or topic) must be registered with the J2EE server. This usually is done using a vendor-specific tool. The connection factory and destination objects are stored in JNDI.

After JMS is configured, producers and consumers can exchange messages. Producers, such as servlets and EJBs, deliver messages to a destination. Listing 5.5 shows the code of a producer that connects to a JMS queue and sends a PTP message.

Listing 5.5 PTP JMS Producer
 //Use JNDI to look up connection factory and destination Context context = new InitialContext(); QueueConnectionFactory qcf =     (QueueConnectionFactory)context.         lookup("weblogic.mydomain.jms.QueueConnectionFactory"); Queue q = (Queue)context.lookup(     "weblogic.mydomain.jms.MyQueue"); //Set up the message using the following components //    Connection <== ConnectionFactory //    Session    <== Connection //    Producer   <== Session //    Message    <== Session // Get connection to JMS service Connection c = qcf.createQueueConnection(); // Create a session QueueSession s = c.createQueueSession(false,         Session.AUTO_ACKNOWLEDGE); // Create a producer. Create a QueueSender for queues and TopicPublisher for topics. QueueSender qs = s.createSender(q); // Create a message. TextMessage tm = s.createTextMessage("This is a message); // Send the message. For topics, a message is published qs.send(tm) ; 

There are two types of consumers, synchronous and asynchronous. There is no difference in the administrative set up for each consumer type and the programmatic set up is also similar. Listing 5.6 shows the code for a synchronous PTP receiver.

Listing 5.6 JMS PTP Receiver
 //Use JNDI to look up connection factory and destination Context context = new InitialContext(); QueueConnectionFactory qcf =     (QueueConnectionFactory)context.         lookup("weblogic.mydomain.jms.QueueConnectionFactory"); Queue q = (Queue)context.lookup(     "weblogic.mydomain.jms.MyQueue"); //Set up the message using the following components //    Connection <== ConnectionFactory //    Session    <== Connection //    Consumer   <== Session //    Start the session using the Connection // Get connection to JMS service Connection c = qcf.createQueueConnection(); // Create a session QueueSession s = c.createQueueSession(false,         Session.AUTO_ACKNOWLEDGE); // Create a consumer. Create a QueueReceiver for queues and TopicSubscriber for topics QueueReceiver qr = s.createReceiver(q); // Start listening on the connection c.start(); // Wait for a message by issuing a receive method call Message m = qr.receive(); 

When using an asynchronous receiver, the following changes must be made:

  • Create a class that implements the javax.jms.MessageListener interface. OnMessage is the only method to be implemented.

  • Before calling the start method on the connection, call the setMessageListener method on the consumer object, passing an instance of the class created in step 1.

  • Remove the receive method call from the consumer object because the onMessage method will now receive all incoming messages.

Message beans are asynchronous message consumers. Most of the programmatic steps to use JMS are performed by the EJB container. The ejb-jar.xml deployment descriptor describes how the message's bean is going to use JMS. The message bean must implement the Message Listener interface to receive messages in the onMessage method.

For technical information on JMS in the context of the WebLogic Server 7.0, see "The Java Messaging Service (JMS)," p. 471 .


J2EE Security

J2EE server security concerns itself with authentication (the users are who they claim to be) and authorization (the users can do what they are trying to do). J2EE Security is enforced at three levels:

  • Web container

  • EJB container

  • EIS component

Note

The Java Authentication and Authorization Service (JAAS) could be used to provide programmatic security services for client applications and J2EE components.


The Web container enables Web components (such as JSP pages, HTML pages, or servlets) to be protected by authentication and authorization constraints. Identifying a constraint with a Web component causes access to the container to be qualified by an authentication sequence. There are three authentication mechanisms used for the Web container: HTTP basic authentication, form-based authentication, and public key certification.

When HTTP basic authentication is used, the browser client must provide a valid username and password to the J2EE server before any resources can be accessed. Form-based authentication is similar to Web-based authentication, but the application program must supply an HTML form to be filled out by the user and the application developer must write the Java code to authenticate users. With public key certification, a browser client passes a certificate that is validated on the server side. If it is valid, encrypted messages are passed between the client and J2EE server using the Secure Socket Layer (SSL) protocol. Messages that are passed in this manner use the secure HTTPS protocol.

The Web container also supports programmatic authorization security checking using the HttpServletRequest interface. In particular, the methods getRemoteUser , isUserInRole , and getUserPrincipal provide information about who is trying to use a Web component.

The EJB container provides method-level protection for its components. The user of an EJB component is called the principal. The accesses allowed to a principal are determined by the bean's ejb-jar.xml deployment descriptor. Listing 5.7 shows the <method-permission> keyword for a method in an EJB. In this example, only the users who have been assigned the boss or manager role have access to any of the methods in the BigBean EJB. The <role-name> keyword defines principals who are allowed access to the BigBean EJB.

Note

Use of the wildcard character, *, indicates all methods.


Listing 5.7 Usage of the Method Permission in ejb-jar.xml
 <assembly-descriptor>     <method-permission>         <role-name>manager</role-name>         <role-name>boss</role-name>     <method>          <ejb-name>BigBean</ejb-name>          <method-name>*</method-name>     </method>     </method-permission> . . . 

Listing 5.8 shows how those roles are defined for EJBs using this deployment descriptor.

Listing 5.8 Usage of the Security Role Definitions in ejb-jar.xml
 <security-role>     <description>         This role represents everyone who is allowed         to access the big bean     </description>     <role-name>boss</role-name>     <role-name>manager</role-name> </security-role> 

Roles determine who can access a given resource. Principals are assigned roles in a vendor-specific manner. J2EE has adopted the concept of users and groups where a user is a specific principal and a group is a set of specific users. A user-assigned role implies the user can perform the activities related to that specific role. When a group is assigned a role, all users of that group can perform the activities related to that role.

For technical information on J2EE application security in the context of WebLogic Server 7.0, see Chapter 26.

The JavaMail API

JavaMail is an optional API package included in J2EE. It enables the developer to create, receive, and send electronic mail messages using a vendor-neutral interface. The JavaMail API interacts with an underlying mail system using protocols such as SMTP and POP, which provide the actual delivery of the messages. The specific mail driver is stored in the JNDI tree and is used when creating a mail session. Because JavaMail requires the Java Activation Framework API (JAF), JAF is also included in J2EE.

The capability to access enterprise mail systems, such as Lotus Notes and Microsoft Outlook, is becoming a very popular requirement for Web-based applications. Even though most mail system vendors provide their own Web-based interfaces, the requirement and business emphasis for most J2EE solutions is to provide a consistent Web-based interface to the mail systems, for example, via a portal application that can also provide a seamless and transparent mechanism for workflow type operations. To ease the development effort and provide a cost-effective solution to your J2EE application and mail system integration requirements, it is advisable to first perform a due diligence on the vendor-based software/component solutions that already exist and are proven to demonstrate success with as little customization as possible. For example, Compoze provides an out-of-the-box proven solution for integrating J2EE applications with Microsoft Outlook and Lotus Notes mail systems.

Java Connector Architecture (J2C)

J2EE Connectors allow J2EE application components to integrate with Enterprise Information Systems (EIS). Connectors can be purchased from application server vendors such as BEA, or from the EIS vendors that have developed proprietary connectors for their systems to enable communication with J2EE components and systems. The more difficult route when existing connector solutions do not exist is to develop your own EIS connector using the J2C Adapter Development Kit, which is an integral part of the WebLogic Integration product.

Connectors work by abstracting EIS components into resource adapters that are plugged into the J2EE server. A resource adapter is a system-level software driver that exposes an API. This is similar to how a JDBC driver is used to access a database.

How Connectors Are Used in J2EE

A resource adapter is added to the J2EE server configuration using a descriptor ( rar.xml ) and a set of classes or other executable files, which are loaded by the J2EE server. Each resource adapter defines a client API. This client API can use any API required to communicate with the EIS. A Common Client Interface (CCI) can also be defined so applications can treat disparate resources using the same API; however, this is not always required because the resource adapter's client API could be the JDBC API, which can be used to access a non-standard DBMS.

In addition to the client API, there are three system contracts between the J2CA container in the J2EE server and the Resource Adapter: connection management, transaction management, and security management.

Connection management provides connection pooling and lifecycle operations for the application components. The connection pooling allows limited resources to be shared across many users. The lifecycle operations create and destroy connections when necessary and prevent the application developer from having to know the idiosyncrasies of the specific EIS.

Three types of transactions can be supported by a resource adapter:

  • No Transactions: In this case the resource adapter cannot support transactions. For this reason, it is important not to interact with the EIS in a transactional manner if the completion of a transaction is critical to the application's integrity and operation.

  • Local Transactions: For local transactions, the J2EE server starts a transaction dependent on the current transactional context and issues a commit when the connection is closed.

  • XA Transactions: This type of transaction allows an EIS component to participate with other EIS components or XA-compliant resources using the two-phase commit (2PC) mechanism.

J2EE connectors support both container and application managed sign-on. Security information, usually in the form of a principal's username and a password is sent to an EIS system. After the principal is authenticated by the EIS, a connection is returned which can be used by the application component for the EIS services.

For technical information on J2CA in the context of the WebLogic Integration 7.0 product, see "Understanding J2CA Through the WLI Application Integration Framework," p. 1277 .


The EJB Container

The EJB container provides a runtime environment for distributed Java objects, which includes the following features:

  • Declarative security: Method-level authorization for EJBs is based on users and user-groups. Security declarations are part of the EJB deployment descriptors.

    Note

    An EJB component is described using a deployment descriptor. The standard deployment descriptor for EJBs is an XML file named ejb-jar.xml . In addition, there are vendor-specific deployment descriptors for describing vendor-specific features.


  • Concurrency control: All EJBs are single-threaded. The container creates multiple instances of EJBs to simulate concurrent access.

  • Lifecycle management: EJBs are created, destroyed , and allocated for use by the container. The container can also maintain the persistent state for an EJB if needed.

  • Request dispatching: The EJB container receives all EJB requests and dispatches them to the appropriate component. It also forwards results back to the requestor .

  • Declarative transactional control: Transactional controls are specified in the EJB deployment descriptors.

  • Container-managed persistence (CMP): With CMP persistence, all data store calls (JDBC) are performed by the EJB container. The mapping of the data in the EJB to the data store is specified in EJB deployment descriptors.

    Note

    CMP is also referred to as declarative persistence .


  • Resource management: The EJB container maintains free object pools and in-memory caches to manage EJB loads. The container can also swap EJBs between disk and memory when memory resources are constrained.

Figure 5.8 illustrates a simple scenario on how EJBs are used inside an EJB container, where:

Figure 5.8. A simple interaction scenario of EJBs inside an EJB container.

graphics/05fig08.gif

  • A Java client application or a J2EE component (JSP or Servlet) uses RMI or a local method to call into a session bean (1).

  • The session bean method performs application-specific steps, including calling methods on two entity beans. The entity beans then update the database in the context (2).

    Note

    The method calls related to (1) and (2) are part of the same single transaction.


  • Java programs use JMS to deliver a message to a JMS queue inside the EJB container (3).

  • A message-driven bean receives messages from the JMS queue and uses an entity bean to update the database.

    Note

    The method calls related to (3) and (4) are part of the same single transaction.




BEA WebLogic Platform 7
BEA WebLogic Platform 7
ISBN: 0789727129
EAN: 2147483647
Year: 2003
Pages: 360

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net