Problem description
Following process gets a org.hibernate.cache.CacheException after hotdeploy/redeploy:
- start JBoss AS and deploying my ear-file
- get some information stored in db (ejb3 entity) using the web interface
Here's everything fine.
Now, starting a hotdeployment of my ear file
and get the same entity like above. (exactly the same entity with the same primary key)
The server throws a org.hibernate.cache.CacheException. I think there is a invalidation problem, but I didn't found a way to handle this.
The problem only occurs if the entity has a composite primary key like below and attribute override.
Hibernate version: 3.2GA
JBoss version: 4.0.5 GA + EJB3 + JBoss Cache 1.4GA
Mapping documents: using Hibernate Annotations 3.2GA / EntityManager 3.2GA
Code between sessionFactory.openSession() and session.close():
Code:
@Stateless
public class InventoryBean implements Inventory {   
   private static final Log LOG = LogFactory.getLog(InventoryBean.class);
   private static final boolean DEBUG = LOG.isDebugEnabled(); 
   @PersistenceContext
   private EntityManager em;
   
   @PostConstruct
   public void postConstruct() {
      if (DEBUG) 
         LOG.debug("InventoryBean created. EntityManager: " + em != null);
   }
   @PreDestroy
   public void preDestroy() {
      if (DEBUG) 
         LOG.debug("InventoryBean destroyed.");
   }
[...]
Code:
public class InventoryDAO {
   private static final Log LOG = LogFactory.getLog(InventoryDAO.class);
   private static final boolean DEBUG = LOG.isDebugEnabled();   
   private static InventoryDAO dao = null;
   private EntityManager em;
   
   public static synchronized InventoryDAO getInstance(EntityManager em) {
         if (dao == null)
            dao = new InventoryDAO(em);
         return dao;
   }
   private InventoryDAO(EntityManager em) {
      super();
      this.em = em;
   }
   public StockInventory getStockInventoryById(int inventoryId){
      if (DEBUG) LOG.debug(Constants.BEGIN + "getStockInventoryById(): " + inventoryId);
      StockInventory stockInventory = em.find(StockInventory.class, inventoryId);
         
      if (DEBUG) LOG.debug(Constants.END + "getStockInventoryById(): " + inventoryId);
      return stockInventory;
   }
[...]
Full stack trace of any exception that occurs / TRACE Log:Code:
2006-11-10 19:39:23,031 DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 11631839630
2006-11-10 19:39:23,031 DEBUG org.hibernate.ejb.AbstractEntityManagerImpl - Looking for a JTA transaction to join
2006-11-10 19:39:23,031 DEBUG org.hibernate.jdbc.JDBCContext - successfully registered Synchronization
2006-11-10 19:39:23,031 DEBUG org.hibernate.ejb.AbstractEntityManagerImpl - Looking for a JTA transaction to join
2006-11-10 19:39:23,031 DEBUG org.hibernate.ejb.AbstractEntityManagerImpl - Transaction already joined
2006-11-10 19:39:23,031 DEBUG org.hibernate.cache.TransactionalCache - cache lookup: de.aep.inventory.db.Stock#de.aep.inventory.db.StockPK@cd5b2e27
2006-11-10 19:39:23,046 INFO  org.hibernate.event.def.DefaultLoadEventListener - Error performing load command
org.hibernate.cache.CacheException: java.lang.RuntimeException: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of de.aep.inventory.db.StockPK.stockId
   at org.hibernate.cache.TreeCache.read(TreeCache.java:57)
   at org.hibernate.cache.TransactionalCache.get(TransactionalCache.java:31)
   at org.hibernate.event.def.DefaultLoadEventListener.loadFromSecondLevelCache(DefaultLoadEventListener.java:472)
   at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:356)
   at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:137)
   at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:193)
   at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:101)
   at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
   at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
   at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
   at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:174)
   at org.jboss.ejb3.entity.TransactionScopedEntityManager.find(TransactionScopedEntityManager.java:164)
   at de.aep.inventory.db.InventoryDAO.getStockById(InventoryDAO.java:39)
   at de.aep.inventory.InventoryBean.getStockById(InventoryBean.java:58)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
   at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
   at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManagerInterceptor.java:54)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
   at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:197)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:77)
   at org.jboss.ejb3.security.Ejb3AuthenticationInterceptor.invoke(Ejb3AuthenticationInterceptor.java:131)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:263)
   at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:58)
   at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
   at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:102)
   at $Proxy106.getStockById(Unknown Source)
   at de.aep.inventory.ui.InventoryAction.stockEdit(InventoryAction.java:135)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at org.apache.struts.actions.ActionDispatcher.dispatchMethod(ActionDispatcher.java:359)
   at org.apache.struts.actions.ActionDispatcher.dispatchMethod(ActionDispatcher.java:333)
   at org.apache.struts.actions.ActionDispatcher.execute(ActionDispatcher.java:220)
   at de.aep.inventory.ui.InventoryAction.execute(InventoryAction.java:47)
   at org.apache.struts.chain.commands.servlet.ExecuteAction.execute(ExecuteAction.java:53)
   at org.apache.struts.chain.commands.AbstractExecuteAction.execute(AbstractExecuteAction.java:64)
   at org.apache.struts.chain.commands.ActionCommandBase.execute(ActionCommandBase.java:48)
   at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
   at org.apache.commons.chain.generic.LookupCommand.execute(LookupCommand.java:304)
   at org.apache.commons.chain.impl.ChainBase.execute(ChainBase.java:190)
   at org.apache.struts.chain.ComposableRequestProcessor.process(ComposableRequestProcessor.java:280)
   at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1858)
   at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:459)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:810)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
   at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
   at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175)
   at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
   at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
   at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
   at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
   at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112)
   at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.RuntimeException: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of de.aep.inventory.db.StockPK.stockId
   at org.jboss.cache.TreeCache.invokeMethod(TreeCache.java:5526)
   at org.jboss.cache.TreeCache.get(TreeCache.java:3469)
   at org.jboss.cache.TreeCache.get(TreeCache.java:3450)
   at org.hibernate.cache.TreeCache.read(TreeCache.java:54)
   ... 83 more
Caused by: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of de.aep.inventory.db.StockPK.stockId
   at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:35)
   at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:64)
   at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:70)
   at org.hibernate.tuple.component.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:83)
   at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:353)
   at org.hibernate.type.ComponentType.isEqual(ComponentType.java:123)
   at org.hibernate.cache.CacheKey.equals(CacheKey.java:51)
   at EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap.eq(ConcurrentReaderHashMap.java:309)
   at EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap.get(ConcurrentReaderHashMap.java:443)
   at org.jboss.cache.Node.getOrCreateChild(Node.java:263)
   at org.jboss.cache.interceptors.PessimisticLockInterceptor.lock(PessimisticLockInterceptor.java:214)
   at org.jboss.cache.interceptors.PessimisticLockInterceptor.invoke(PessimisticLockInterceptor.java:166)
   at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68)
   at org.jboss.cache.interceptors.UnlockInterceptor.invoke(UnlockInterceptor.java:32)
   at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68)
   at org.jboss.cache.interceptors.TxInterceptor.handleNonTxMethod(TxInterceptor.java:345)
   at org.jboss.cache.interceptors.TxInterceptor.invoke(TxInterceptor.java:156)
   at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68)
   at org.jboss.cache.interceptors.CacheMgmtInterceptor.invoke(CacheMgmtInterceptor.java:138)
   at org.jboss.cache.TreeCache.invokeMethod(TreeCache.java:5520)
   ... 86 more
Caused by: java.lang.IllegalArgumentException
   at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
   at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
   at java.lang.reflect.Field.get(Field.java:357)
   at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:32)
   ... 105 more
2006-11-10 19:39:23,062 DEBUG org.hibernate.ejb.AbstractEntityManagerImpl - mark transaction for rollback
Name and version of the database you are using: PostgreSQL 8.1.5 (same error with 8.1.4)
Code of the entity class:Code:
@Entity
@Cache (usage=CacheConcurrencyStrategy.TRANSACTIONAL)
@Table(name="stock")
public class Stock implements Serializable {
   private static final long serialVersionUID = 5210755493607362380L;
   @Version
   private int version = 0;
    @EmbeddedId  
    @AttributeOverrides( 
         {
           @AttributeOverride   (   name="stockid",
                             column=@Column(name="stockid", unique=false, nullable=false,
                                       insertable=true, updatable=true, length=7)
                          ), 
           @AttributeOverride   (   name="stockpos",
                             column=@Column(name="stockpos", unique=false, nullable=false,
                                       insertable=true, updatable=true)
                          ) 
       }
      )
   private StockPK pk = new StockPK();
   
    @Column(name="geometricbool", unique=false, nullable=false, insertable=true, updatable=true)
   private boolean geometricBool = false;
    @Column(name="contractid", unique=false, nullable=true, insertable=true, updatable=true)
   private long contractId = 0;;
   @Column(name="qty", unique=false, nullable=false, insertable=true, updatable=true, precision=9)    
   private double qty = 0.0;
   
    @ManyToOne(cascade={}, fetch=FetchType.EAGER)
    @JoinColumn(name="unitid", unique=false, nullable=false, insertable=true, updatable=true)
   private StockUnit unitId;
   
    @ManyToOne(cascade={}, fetch=FetchType.EAGER)
    @JoinColumn(name="matid", unique=false, nullable=false, insertable=true, updatable=true)
   private Mat matId = new Mat();
    @ManyToOne(cascade={}, fetch=FetchType.EAGER)
    @JoinColumn(name="areaid", unique=false, nullable=false, insertable=true, updatable=true)
   private StockArea areaId = new StockArea();
   
    @Column(name="inventorylock", unique=false, nullable=false, insertable=true, updatable=true)    
   private boolean inventoryLock = false;
   
    @ManyToOne(cascade={}, fetch=FetchType.LAZY)
    @JoinColumn(name="inventoryid", unique=false, nullable=true, insertable=true, updatable=true)
   private StockInventory inventoryId = new StockInventory();
    @OneToMany(cascade={}, fetch=FetchType.EAGER, mappedBy="stock")
    private List<StockGeometric> stockGeometric = new ArrayList<StockGeometric>();
[...] getters and setters [...]
Code of the embedded class:Code:
@Embeddable
public class StockPK implements Serializable {
   private static final long serialVersionUID = 4040974111182621373L;
   @Column(name="stockid", unique=false, nullable=false, insertable=true, updatable=true, length=7)
   private String stockId = "";
   
   @Column(name="stockpos", unique=false, nullable=false, insertable=true, updatable=true)
   private int stockPos = 0;
   
   public StockPK( ) {}
   public StockPK(String stockId, int StockPos){
      this.stockId = stockId;
      this.stockPos = StockPos;
   }
   public String getStockId() {
      return stockId;
   }
   public void setStockId(String stockId) {
      this.stockId = stockId;
   }
   public int getStockPos() {
      return stockPos;
   }
   public void setStockPos(int stockPos) {
      this.stockPos = stockPos;
   }
   @Override
   public boolean equals(Object obj){
         if (obj == this)
            return true;
         if (!(obj instanceof StockPK))
            return false;
         StockPK pk = (StockPK)obj;
         if (!(stockId.equals(pk.getStockId())))
            return false;
         if (stockPos != pk.getStockPos())
            return false;
         return true;
   }
   @Override
   public int hashCode( ){
       return stockId.hashCode() + stockPos;
   }
      
}
I appreciate for every kind of help / ideas.
Thank you.
christian