EJB programming & troubleshooting: Caching in Entity EJBs
I'm kinda new to EJBs but have been tasked with looking into EJBs as a solution for our problem. Currently, we using ATG Dynamo as our application server and running our application on 2 app servers with 2 drps each (drps are like clusters in WebLogic). Our application is basically a search engine which returns a list of items queried from the database. As a way of limiting the number of DB queries, everytime a user searches for items, those items are place in a static Hashtable. That way other users who search for those same items don't need to do another DB lookup. The problem is that since we are implementing this cache as a static Hashtable, it is only global across each JVM or each drp (cluster). So we actually have 4 copies of this exact same Hashtable in 4 different drps. And this eats up memory fast.
Would it be possible for us to use an Entity EJB instead to implement this? Is there a way to keep data in some kind of collection object within the EJB (like a Hashtable) and have the EJB look up data in that object instead of querying the database each time? So the ejbLoad() method would load the Hashtable initially from the database. But after that, each call to ejbFindByPrimaryKey() would simply look it up in the Hashtable. The benefit of something like this is of course there is only one copy of this large Hashtable, instead of a copy in each cluster.
Is this a viable solution? Any feedback would be greatly appreciated. Thanks!
- Caching in Entity EJBs by Henrik Engstrom on September 19 2002 06:41 EDT
- Caching in Entity EJBs by Rob Misek on September 19 2002 09:19 EDT
The question is two folded:
Q1. Is it possible to use entity beans as "read only" beans,
Q2. How do we guarantee that there is only one instance of entity bean in a cluster?
A1: Yes, it's possible. I even think there is a pattern called "read only entity bean" or something similar. Just let the EB cache the data in a HashMap. I have tried it in production and it works fine.
A2: This is a tricky one. I cannot think of a viable solution preventing each app.server to create at least one instance in its container... Anyone who can help us out here?
Just my 2c
I only have experiance with Weblogic, so I can only talk about it. You can limit the number of beans to 1 in an instance by setting "max-beans-in-free-pool" to 1. This will cause requests to be queued if the instance is not freed untill they either get served or thier transaction times out.
This is how to do, but do you really wanna do that ??? :-) I guess this is another issue all togather :-)
As for other Containers, probably each one has its own "max-beans-in-free-pool" equivalent.
Another solution that you might want to look at is Tangosol's Coherence product. It includes a distributed cache that allows you to distribute the data in a cache equally over each JVM. This combined with the concept of a "near" or "write-through" cache which keeps a size limited "local" cache of data Most Frequently Used (MFU) on the JVM to decrease the amount of "get" operations over the wire.
I just browsed your Web Site in order to get some information on your Coherence product. I still can't understand what is the main use of your product if most of Application Servers already have "active replication" capabilities for most types of the EJBs. I understand, that working a replicated cache would be faster than storing shared objects in JNDI, but is performance an only issue?
Alex: "I just browsed your Web Site in order to get some information on your Coherence product."
Great! You can also download a free evaluation copy from http://www.tangosol.com/coherence.jsp. If you decide to use the software, we provide free developer licenses as well.
Alex: "I still can't understand what is the main use of your product if most of Application Servers already have "active replication" capabilities for most types of the EJBs."
What servers do? WebLogic does not, except for *stateful* session EJBs, and that is not a global cache but just one backup server for the EJB. WebSphere does not even cluster until version 5 (not released yet). No other server provides a guaranteed coherent clustered cache, and if you want to be cross-server portable you have no other potential solution than Coherence.
Alex: "I understand, that working a replicated cache would be faster than storing shared objects in JNDI, but is performance an only issue?"
JNDI is not guaranteed to be clustered either. Note that WebLogic, for example, can have different JNDI values on different servers even if the JNDI is clustered! You cannot (should not, must not) rely on JNDI as a reliable clustered service.
The main purpose of Coherence is to provide a reliable, concurrent, high performance facility for storing data across a cluster of JVMs (e.g. J2EE Application Servers). Coherence is also the only Java clustered data store that can distribute (partition) data across the cluster (using the Distributed Cache), lock key/value pairs cluster-wide (pessimistic concurrency control API), and provide JavaBean events to "listen" to updates, inserts and removals of data in the cluster.