Brett mclaughlin in this article
EJB Best Practices Columns have studied JNDI lookups, which is an indispensable and common part of almost all EJB interactions. Unfortunately, JNDI operations have almost always need performance overhead. In this skill article, Brett shows you how the HOME interface factory reduces JNDI lookup overhead in your EJB application.
Each EJB component (session, entity, and messaging) has a HOME interface. The HOME interface is the BEAN's operational basis; once you find it, you can use the ability of this bean. The EJB application rely on JNDI lookup to access its bean's HOME interface. Because EJB applications are often running multiple beans, and because many components often use JNDI search, most of the performance overhead of application is spent on these findings.
In this technique, we will study some of the most common JNDI optimizations. In particular, we will show you how to use cache and general assistant classes to create factory-style solutions for JNDI overhead.
Reducing the context instance Listing 1 shows a typical EJB code, which requires multiple JNDI to find. Take a little time to study the code, then we will optimize it for better performance.
Listing 1. Typical EJB Find
Public Boolean Buyitems (PaymentInfo PaymentInfo, String Storename,
List items {
// load up the initial context
Context ctx = new initialContext ();
// Look Up a bean's home interface
Object obj = ctx.lookup ("java: comp / env / ejb / purchasehome");
PurchaseHome PurchaseHome =
(Purchasehome) PortableremoteObject.narrow (Obj, purchasehome.class);
Purchase purchase = purchasehome.create (paymentinfo);
// Work on the bean
Iterator i = items.iterator (); I.hasnext ();) {
Purchase.addItem ((item) i.next ());
}
// Look Up Another Bean
Object obj = ctx.lookup ("java: comp / env / ejb / inventoryhome");
InventoryHome InventoryHOME =
(InventoryHome) PortableremoteObject.narrow (Obj, InventoryHome.Class);
Inventory Inventory = InventoryHome.findbyStoreName (StoreName);
// Work on the bean
Iterator i = items.iterator (); i.hasnext ();)
Inventory.markassold ((item) i.next ());
}
// do some Other stuff
}
Although this example is a bit deliberate, it does reveal some of the most obvious issues when using JNDI. For beginners, you should ask yourself, new InitialContext object is required. It is likely that this context has been installed in other parts of the application code, and we have created a new one here. Cache InitialContext instances will immediately enhance performance, such as Listing 2: Listing 2. Cache InitialContext instance
Public static context getInitialContext () {
IF (InitialContext == NULL) {
InitialContext = new initialContext ();
}
Return INIALCONTEXT;
}
By using a helper class for GetInitialContext () instead of instanting a new InitialContext for each operation, we will decrease the number of contexts in the application as one.
Oh - how is the thread? If you are worried about the thread of the solution proposed here, it is not necessary. Two threads simultaneously becoming the getIitialContext () is absolutely possible (thus creating two contexts at a time), but such errors will only occur when calling the method for the first time. Because the problem is only once, synchronization is unnecessary. In fact, the complexity of synchronous introduction is more complex than it solves more.
Optimizing Finding Cache Context The direction of this step is correct, but doing so only, it is not enough to complete optimization. Each time we call the Lookup () method, we will perform a new lookup and return to the new instance of the Home interface. At least, JNDI lookup is usually encoded like this. But if each bean has only one HOME interface, sharing this interface on multiple components, isn't it better?
We can cache each individual bean reference, rather than repeatedly find the HOME interface of the PurchaseHome or InventoryHome; this is a solution. But we really want is a more common mechanism: Cache HOME interface in the EJB application.
The answer is to create a universal assistant class, which can get the initial context for each bean in the application, but also look for the Home interface. In addition, this class should also be able to manage the context of each bean for a variety of application components. The general assistant class shown in Listing 3 will act as the factory of the EJB HOME interface:
Listing 3. EJB Home Interface Factory
Package com.ibm.ejb;
Import java.util.map;
Import javax.ejb.ejbhome;
Import javax.naming.context;
Import javax.naming.initialcontext;
Import javax.naming.namingexception;
Public class ejbhomefactory {
Private static ejbhomefactory;
PRIVATE MAP HOMEINTERFCES;
PRIVATE CONTEXT Context;
// this is private, and can't be instantiated directly
Private ejbhomefactory () throws namingexception {
HomeInterfaces = new hashmap ();
// Get the context for caching purposes
Context = new initialContext (); / **
* In non-j2ee coplications, you might need to load up
* a Properties File and get this context manually. I'VE
* Kept this Simple for Demonstration Purposes.
* /
}
Public static ejbhomefactory getinstance () throws namingexception {
// Not Completely Thread-Safe, But Good Enough
// (See Note In Article)
IF (instance == null) {
Instance = new ejbhomefactory ();
}
Return Instance;
}
Public EjBhome Lookup (String Jndiname, Class HomeInterfaceClass)
Throws namingexception {
// See IF we already have this interface cached
Ejbhome homeInterface = (ejbhome) HOMEINTERFACES.GET (HOMECLASS);
// if not, Look Up with the support jndi name
IF (homeInterface == null) {
Object obj = context.lookup (jndiname);
HomeInterface =
(Ejbhome) PortableRemoteObject.Narrow (Obj, HomeInterfaceClass);
// if this is a new ref, save for caching purposes
HomeInterfaces.Put (HomeInterfaceClass, HomeInterface);
}
Return HOMEINTERFACE;
}
}
The key to the EJBHOMEFACTORY Class At Home Interface Factory is in the HomeInterfaces map. This mapping stores the Home interface for each bean for use; this, the Home interface instance can be used repeatedly. You should also note that the key in the mapping is not a JNDI name that passes to the Lookup () method. Binding the same HOME interface to a different JNDI name is very common, but this will generate a copy in your mapping. By relying on the class itself, you can ensure that you will eventually create multiple HOME interfaces for the same bean.
Insert the new home interface factory class into the original code of the list 1, which will generate an optimized EJB lookup, such as Listing 4:
Listing 4. Improved EJB lookup
Public Boolean Buyitems (PaymentInfo PaymentInfo, String Storename,
List items {
Ejbhomefactory f = ejbhomefactory.getinstance ();
PurchaseHome PurchaseHome =
(Purchasehome) F.Lookup ("Java: Comp / ENV / EJB / PURCHASEHOME",
Purchasehome.class;
Purchase purchase = purchasehome.create (paymentinfo);
// Work on the bean
Item I = items.ITerator (); I.hasNext ();) {purchase.addItem ((item) i.next ());
}
InventoryHome InventoryHOME =
(InventoryHome) F.Lookup ("Java: Comp / ENV / EJB / InventoryHome",
InventoryHome.Class;
Inventory Inventory = InventoryHome.findbyStoreName (StoreName);
// Work on the bean
Iterator i = items.iterator (); I.hasnext ();) {
Inventory.markassold ((item) i.next ());
}
// do some Other stuff
}
Over time, except for clearer (at least my point of view), the above factory optimized EJB lookup will be implemented faster. When you use this new class for the first time, you will spend all normal lookup overhead (assuming that other parts of the application does not pay this overhead), but all JNDI findings will continue to use the original lookup results. It is also necessary to point out that the Home Interface Factory does not interfere with Bean management of your container. The container is managed by a bean instance instead of the Home interface of these bean instances. Your container also manages instance exchange, and other optimizations you want to do.
In the next article of EJB Best Practices, I will show you how to enable management access to entity beans, and you don't have to expose them directly to your application's Web layer. In that time, we saw it online.
Reference
Sun Microsystems EJB Technology Homepage is a good reference for all related content related to EJB technology. TheServerside provides many articles and information about J2EE. The JGuru EJB Fundamentals tutorial (DeveloperWorks, March 2001) provides a comprehensive introduction to Enterprise JavaBeans technology, and special attention to the role of EJB components in distributed computing cases, architecture, expansion API, and the basis of using EJB technology. Access the developerWorks Java tutorial page to get other free EJB and J2EE related tutorials. In the developerWorks Java technology area you can find hundreds of articles about Java programming.
About the author BRETT MCLAUGHLIN from the LOGO era (Remember that small triangle?) Started working in a computer. He is now specializing in building an application infrastructure with Java and Java related technologies. In the past few years he has been committed to achieving these infrastructure in NEXTEL COMMUNICATIONS and Allegiance Telecom, Inc. Brett is one of the common founders of the Java Apache project Turbine, which uses Java Servlet to develop a reusable component architecture for web applications. He is also one of the participants of the EJBoss project (an open source EJB application server) and Cocoon's participant.