I am using Wildfly 8.2 with its included Infinispan (6.0.2) and I am trying to cache all values from some Oracle database table in an Infispan cache. In most cases, it seems to work, but sometimes it does not. When accessing the cache.values()
(which also may not be a good idea for performance, but is an example) it appears sometime to be empty, sometimes it contains the values correctly. Therefore I think it might a problem with the configuration of the transactions. When making the Infinispan cache non-transactional, the problem disappears.
The service which accesses the cache and the DB is an EJB bean with container-managed transactions. On initialzation of the Service, all data is loaded from the DB (it does not contain many entries).
According to what's new in ejb 3.2 it should be possible to access the DB transactionally in a EJB Singleton
bean.
Is the configuration of the data source and the Infinispan cache correct? Can I use a non-XA datasource with Infinispan and expect it work consistently? According to the Infinispan doc, NON_XA
means that Infinispan is registering as a Synchronization, which should be ok, shouldn't it?
The cache is configured in the standalone-full.xml as follows (when removing <transaction mode="NON_XA" locking="PESSIMISTIC"/>
the problem disappears, at the price of having no transactional cache):
<cache-container name="cacheContainer" start="EAGER">
<local-cache name="my_table_cache">
<locking isolation="REPEATABLE_READ"/>
<transaction mode="NON_XA" locking="PESSIMISTIC"/>
</local-cache>
</cache-container>
The Oracle DS is defined as follows
<datasource jndi-name="java:jboss/datasources/myDataSource" pool-name="dataSource" enabled="true">
<connection-url>jdbc:oracle:thin:@127.0.0.1:1523:orcl</connection-url>
<driver>ojdbc7.jar</driver>
<pool>
<max-pool-size>25</max-pool-size>
</pool>
<security>
<user-name>myuser</user-name>
<password>myuser</password>
</security>
<timeout>
<blocking-timeout-millis>5000</blocking-timeout-millis>
</timeout>
</datasource>
My Service (the dao is using simple JDBC operations, not Hibernate or similar)
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class MyService {
@Resource(lookup = "java:jboss/infinispan/container/cacheContainer")
protected EmbeddedCacheManager cm;
protected Cache<String, MyEntity> cache;
@PostConstruct
private void init() {
try {
cache = getCache();
} catch (SQLException ex) {
log.fatal("could not initialize caches", ex);
throw new IllegalStateException(ex);
}
}
public Cache<String, MyEntity> getCache() {
Cache<String, MyEntity> cache = cm.getCache(getCacheName(), true);
fillCache(cache);
return cache;
}
protected void fillCache(Cache<String, MyEntity> cache) {
List<MyEntity> entities = myDao.getEntities();
for (MyEntity e : entities) {
cache.put(e.getKey, e);
}
}
public MyEntity getEntity(String key) {
return cache.get(key);
}
public void insert(MyEntity entity) {
myDao.insert(entity);
cache.put(entity.getKey(), entity);
}
public void debug() {
log.debug(cache.values());
}
}
When using NON_XA transactions, failure to commit TX in cache may let the transaction to commit, and you would not get any exception that would tell you that the cache is inconsistent.
As for
cache.values()
, prior to Infinispan 7.0 it returns only local entries, however that should not matter in your case - with local cache all entries are local. The transactional consistency of this operation should hold. I don't see anything wrong in your configuration.Generally I would recommend to use Infinispan module in Hibernate ORM rather than trying to do the caching on your own, as you show here.