Using Domino Classes from J2EE EJBs

     

Now we'll look at using the Domino Java classes within an EJB. Access via an EJB may be appropriate if the Domino resources are accessed in the same way across different servlets or JSPs or the access is part of a larger transaction. The first question to address is what type of EJB to use. Out of the three EJB types now available ”session, entity, or message-driven ”we have only two practical choices: session or message-driven EJBs. Using Domino classes from entity EJBs would require us to provide Bean Managed Persistence using Domino databases, and would be difficult at best since the Domino database is document-oriented and not relational.

We first focus on accessing Domino from a session EJB. To avoid confusion with the use of the term "session," we will always qualify it as either "session EJB" or "Domino session."

There are two types of session EJBs, different in the way they are managed by the EJB container. We'll need to understand these differences so that we can incorporate the Domino Java classes appropriately. A session EJB can be either stateless or stateful. Architecturally, the difference between stateless and stateful session EJBs is the extent to which the session is tied to the client. Stateless session EJBs have no ties to the client and can be reused across many clients. A stateless session EJB usually offers only a single function such as a query or update function. Stateful session EJBs can be tied to a client and maintain a conversation state across EJB method invocations. A shopping cart function is often implemented using a stateful session EJB. Stateless session EJBs are created in pools by the EJB container and allocated to clients out of the pool. Stateful session EJBs are created and destroyed in response to client actions.

For stateless session EJBs, we can create the Domino session in the ejbCreate() method and attempt to reuse it in the business method(s) if the Domino session can be established under a single user identity not associated with the client (such as the server's identity or some identity representing all clients). There are two concerns with this approach. The first is that if a local Domino session is to be established via the NotesThread static methods , there is a serious issue with managing the NotesThread context across the threads used by the EJB container ”see the following section on NotesThread issues. The second concern applies to remote Domino sessions. The remote session might be timed out by the Domino server and so should be checked each time it is referenced (via lotus.domino.Session.isValid() ) to see if it needs to be reestablished. Avoiding these concerns implies using the less efficient approach of establishing the Domino session in every business method invocation. This approach also would be our only choice if the Domino session had to be established under the identity of the EJB client.

With stateful session EJBs, the concerns around establishing the Domino session would, at first glance, seem to be simplified because of the facts that the stateful EJB is created, used, and destroyed for each client and is single-threaded relative to the client. It should be a matter of just creating the Domino session during ejbCreate() and terminating it in ejbRemove() . Unfortunately, although the EJB container is required to " single-thread " the EJB methods from the client point of view, it may (and, in the case of WAS, does) run separate EJB method invocations on different threads within the application server. This makes it virtually impossible to establish a local Domino session for reuse across the EJB business methods. A remote Domino session can be established in ejbCreate() and terminated in ejbRemove() , but its use must be validated in case it is dropped by the Domino server.

In addition, establishing the Domino session within stateful session EJBs brings another set of concerns. Besides the two states of "Does Not Exist" and "Method Ready," which apply to both types of session EJBs, the stateful session EJB can be put into a "Passive" state via the ejbPassivate() method and returned to the "Method Ready" state via ejbActivate() . Because client state must be preserved across passivation/activation, client data within the EJB must be serialized. Since we can't serialize a Domino session object, it must be terminated before passivation and restored during activation.

After determining where and when we need to establish the Domino session, we next must consider the user identity under which to establish the session. The simple cases are those where we can establish the Domino session either anonymously under the Domino server's identity or under a single user identity for all clients. The not so simple case is where we want or need to establish the Domino session under a specific user identity, say for a stateful session EJB representing a shopping cart. Unfortunately for this case, we find that the J2EE and Domino client/user identity functions don't make it a simple matter of passing the EJB client identity to Domino. A full explanation of why this is so would take us far afield of our topic here, but basically the J2EE EJB container is architected to handle client identity authentication and authorization so that the EJB itself doesn't need to (and thus can be kept generic). Programatic authorization within the EJB is provided for but must be based on the rather minimal set of authenticated client information available to the EJB (namely, the authenticated caller name and role). We can't get the credentials used to authenticate the EJB client in order to pass them to Domino. Nevertheless, the situation is not hopeless, and we can take the following approach.

We'll call this technique the " handoff " approach: We can pass the user identity parameters needed to establish the Domino session directly to the EJB via a separate "business" method. Referring back to Table 10-2, we see that there are four ways to establish a specific user identity for the Domino session ” userid /password, LTPA token, org.omg.SecurityLevel2.Credentials , or HttpServletRequest objects. If the EJB is being invoked from a servlet, then any of these four can be readily used. The LTPA token string can be extracted from the HttpSession object (it is kept as a cookie on the client and we discuss it in detail in Chapter 12); the Credentials object can be obtained from the LoginHelper servlet provided by WAS; and the HttpServletRequest object can be passed directly (it contains the name and password information from an HTTP basic authentication). Unfortunately, if the EJB is invoked from a Java application or an EJB client container, then only the userid/password is easily passed.

NotesThread Issues with EJBs

For those interested in the details of the "serious" NotesThread issue with establishing local Domino session within EJBs, we attempt an explanation here. Otherwise, this section can be skipped .

From the Domino Designer Help database, we find the following caveats concerning multi-threading the Domino Java classes (we have numbered the points for reference). You should avoid multithreading unless you have good reason to use it, such as proceeding while file input/output and while Web requests are processing. Observe the following guidelines:

  1. Within a session, Domino objects are shared, synchronized, and recycled across threads. By using a different session on each thread, you lose these capabilities; you must explicitly manage synchronization and recycle on a per-thread basis.

  2. Do not use DbDirectory across threads.

  3. Accessing an existing document on multiple threads is permissible, but accessing it on just one thread simplifies memory management. Restricting accesses to one thread allows you to recycle without checking the other threads. Creating documents across threads is always safe, and these objects can be recycled without reference to the other threads.

  4. Profile documents are cached on a per-thread basis. In the event of an update contention , the last thread update wins.

  5. Take care not to delete a document needed for navigation by a view or collection on another thread.

  6. When child objects are used on threads rather than the parent, keep the parent thread alive until all child threads terminate. This is particularly important when using Domino objects in AWT event handlers.

The first five points could be managed with some careful programming. It is the sixth caveat that makes it virtually impossible to manage a NotesThread context within an EJB instance being run by an EJB container. If the NotesThread context is initialized and terminated around the Domino calls within every EJB method, we can't keep a "parent" thread context established ”and any Domino objects created in the method disappear when the NotesThread context is terminated. If we try (and we have) to keep a "parent" thread context active in ejbCreate() (at least for stateful EJBs), we won't be able to terminate that same thread context because there is no guarantee that the ejbRemove() is invoked on the same thread as the ejbCreate() .



IBM WebSphere and Lotus Implementing Collaborative Solutions
IBM(R) WebSphere(R) and Lotus: Implementing Collaborative Solutions
ISBN: 0131443305
EAN: 2147483647
Year: 2003
Pages: 169

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