Thursday, October 18, 2007

Investigating CacheFullException for Entity

Why does the problem occur?
A CacheFullException will be thrown when no more beans can be inserted into the cache. This is because the cache is full with beans which are currently participating in a transaction, or the instances cannot be removed from cache because of other reasons. If any bean in the cache can be found that is not active in a transaction, it will be replaced by the current one. The index for the beans in cache is (primary key, transaction).

CacheFullException - for Entity Beans
There are different reasons that can lead to a CacheFullException for Entity beans:

1. The property is set too small to hold all the number of beans that are simultaneously active.
Note that for WLS 6.1, after upgrading to a service pack equal or higher than SP4, this can be an issue, as the setting has not been considered before for Database concurrency.

2.The implementation of the primary key class is incorrect. The related methods equals() and hashcode() need to return unique values for each and every possible primary key value. If this is not the case, there may be instances in the cache that are not reused and not removed from the cache even though they are no longer participating in a transaction. This means the cache may contain instances of entity beans that are not active in a transaction, but cannot be removed, as the index into the cache is not working because of the primary key (PK) class that is improperly implemented.

Note: It is good practice to ensure that all PK classes have been implemented correctly in your code. See sample below where a small coding error caused a problem:

public boolean equals(Object o){
if (o instanceof AbcPK) {
AbcPK otherKey = (AbcPK)o;
return (companyId.equals(otherKey.string1)&& string1.equals(otherKey.companyId));
} else
return false;
}

The code is comparing the wrong fields as follows:

companyId.equals(otherKey.string1)

should be:

companyId.equals(otherKey.companyId)

and

string1.equals(otherKey.companyId)

should be:

string1.equals(otherKey.string1)

3. If the property is set to true, an EJB instance is created and put into the cache for every value that is returned from a finder method.The cache needs to be sized large enough to hold all those EJBs simultaneously, as the finder runs in one transaction. Alternatively, set to false so that EJBs are instantiated only if needed.
4. For WebLogic Server version 6.1, please ensure that the property is set, because otherwise the beans in the cache may not be re-used.
For versions greater or equal than WLS 7.0 SP5 or 8.1 SP3, the property can be used to specify the maximum length of time an entity bean stays in the cache before it is removed. This helps to free memory used by the cache in peak times.
5. For EJBs that use container managed relationships, relationship-caching can be turned on in order to improve performance. Please check the related tag in the weblogic-cmp-rdbms-jar.xml Deployment Descriptor to find out if you use this feature. The settings need to consider the possible sizes of result sets for relationships. This may be relatively large compared to the number of parent beans used.

No comments: