14 Replies Latest reply on Nov 14, 2009 5:30 PM by Dean Hiller

    how to wrap EntityManager with a proxy???

    Dean Hiller Expert

      I would like to wrap EntityManager with a proxy EntityManager that is injected into every bean and that proxy has the real EntityManager.  This allows me to rewrite the mgr.flush method and the mgr.persist method. 


      ie. we would like flush to have a try catch and log any exceptions better as hibernate tends to throw exceptions but not log any of the getnextSqlException(and seam doesn't log them either and we need to know what happened in production but are losing that info).


      Also, on persist since mgr.merge hardly ever works, we want to change persist to behave like saveOrUpdate so we can stop typing if bean.getId() == null, mgr.persist.


      Any ideas on how to do this?
      thanks,
      Dean

        • 1. Re: how to wrap EntityManager with a proxy???
          Jean Luc Apprentice

          Dean Hiller wrote on Nov 02, 2009 18:32:


          I would like to wrap EntityManager with a proxy EntityManager that is injected into every bean and that proxy has the real EntityManager.  This allows me to rewrite the mgr.flush method and the mgr.persist method. 


          Some ideas:



          • look at JBoss AOP

          • if you only call the EM from services and they have a common superclass, you can replace calls to the EM to calls to similar methods defined in the superclass.




          ie. we would like flush to have a try catch and log any exceptions better as hibernate tends to throw exceptions but not log any of the getnextSqlException(and seam doesn't log them either and we need to know what happened in production but are losing that info).


          When doesn't Hibernate log that? I never had problems with Hibernate hiding exceptions. Can you be more specific?



          Also, on persist since mgr.merge hardly ever works, we want to change persist to behave like saveOrUpdate so we can stop typing if bean.getId() == null, mgr.persist.


          Again, can you be specific about how merge() hardly ever works? I've used it without problems. You do need to understand how it works: all non-transient fields from the entity to merge are first copied into an entity read from the db, then the first one, now updated, is saved. As for saveOrUpdate(), merge() is not far and it does support working with a new entity. To quote from section 3.2.4.1 of JPA specs: If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.
          . I do agree that Hibernate's saveOrUpdate() is more elegant.

          • 2. Re: how to wrap EntityManager with a proxy???
            Stuart Douglas Master

            It's pretty simple, have a look at seam's EntityManagerProxy class, It proxies the entity manager to allow EL to be used in queries. Then create a bean that injects the real entity manager and has a factory method that exposes your new EM proxy.






            
            
            /**
             * Proxies the EntityManager, and implements EL interpolation
             * in JPA-QL
             * 
             * @author Gavin King
             *
             */
            public class EntityManagerProxy implements EntityManager, Serializable
            {
               private EntityManager delegate;
            
               public EntityManagerProxy(EntityManager entityManager)
               {
                  delegate = entityManager;
               }
            
               public void clear()
               {
                  delegate.clear();
               }
            
               public void close()
               {
                  delegate.close();
               }
            
               public boolean contains(Object entity)
               {
                  return delegate.contains(entity);
               }
            
               public Query createNamedQuery(String name)
               {
                  return delegate.createNamedQuery(name);
               }
            
               public Query createNativeQuery(String sql, Class clazz)
               {
                  return delegate.createNativeQuery(sql, clazz);
               }
            
               public Query createNativeQuery(String sql, String lang)
               {
                  return delegate.createNativeQuery(sql, lang);
               }
            
               public Query createNativeQuery(String sql)
               {
                  return delegate.createNativeQuery(sql);
               }
            
               public Query createQuery(String ejbql)
               {
                  if ( ejbql.indexOf('#')>0 )
                  {
                     QueryParser qp = new QueryParser(ejbql);
                     Query query = delegate.createQuery( qp.getEjbql() );
                     for (int i=0; i<qp.getParameterValueBindings().size(); i++)
                     {
                        query.setParameter( 
                                 QueryParser.getParameterName(i), 
                                 qp.getParameterValueBindings().get(i).getValue() 
                              );
                     }
                     return query;
                  }
                  else
                  {
                     return delegate.createQuery(ejbql);
                  }
               }
            
               public <T> T find(Class<T> clazz, Object id)
               {
                  return delegate.find(clazz, id);
               }
            
               public void flush()
               {
                  delegate.flush();
               }
            
               public Object getDelegate()
               {
                  return PersistenceProvider.instance().proxyDelegate( delegate.getDelegate() );
               }
            
               public FlushModeType getFlushMode()
               {
                  return delegate.getFlushMode();
               }
            
               public <T> T getReference(Class<T> clazz, Object id)
               {
                  return delegate.getReference(clazz, id);
               }
            
               public EntityTransaction getTransaction()
               {
                  return delegate.getTransaction();
               }
            
               public boolean isOpen()
               {
                  return delegate.isOpen();
               }
            
               public void joinTransaction()
               {
                  delegate.joinTransaction();
               }
            
               public void lock(Object entity, LockModeType lm)
               {
                  delegate.lock(entity, lm);
               }
            
               public <T> T merge(T entity)
               {
                  return delegate.merge(entity);
               }
            
               public void persist(Object entity)
               {
                  delegate.persist(entity);
               }
            
               public void refresh(Object entity)
               {
                  delegate.refresh(entity);
               }
            
               public void remove(Object entity)
               {
                  delegate.remove(entity);
                  PermissionManager.instance().clearPermissions(entity);
               }
            
               public void setFlushMode(FlushModeType fm)
               {
                  delegate.setFlushMode(fm);
               }
            }
            
            

            • 3. Re: how to wrap EntityManager with a proxy???
              Dean Hiller Expert

              As far as hibernate not giving all the detail in it's exceptions...for 90% of it's exceptions it gives all the detail you need.  The last 10% are covered by code we wrote that digs deeper into the problem in the specific cases where it did not do that for us(and our code then throws a new exception with the more detailed report so you have it in production if it happens there or in QA)...


              I believe this will tell you exactly when it happens too....


                   protected void flushEntities() {
                        try {
                             entityManager.flush();
                        } catch (InvalidStateException e) {
                             String msg = "";
                             for (InvalidValue val : e.getInvalidValues()) {
                                  msg += "msg=" + val.getMessage() + " for field="
                                            + val.getPropertyName() + "\n";
                             }
                             throw new RuntimeException(msg, e);
                        } catch (PersistenceException e) {
                             decipherForLogs(e);
                             throw e;
                        }
                   }
              
                   private void decipherForLogs(Throwable e) {
                        // first, look for an SQL Exception
                        if (e instanceof SQLException)
                             logNextException((SQLException) e);
                        else if (e.getCause() != null)
                             decipherForLogs(e.getCause());
                   }
              
                   private void logNextException(SQLException e) {
                        log.error("Exception", e);
                        if (e.getNextException() != null)
                             logNextException(e.getNextException());
                   }
              



              I guess we just run into more bugs then the average user and add stuff like this so we can get more info ;).


              On the merge, there are all sorts of cases.  First because the merge returns a proxy object and not the instance, we end up with mismatches all the time in the object model and lists so that when we have


              List<Something> children = parent.getchildren(); //some of these children are instances and some are proxies.  The merge creates a proxy and if you have a pulldown list and the list has an instance but the selected value is a proxy, you get a mismatch and all sorts of problems.



              I remember recently, I tried to go back to a simple conversation with entityMgr.merge at the end, it failed with some exception that I can't remember ...let me try to dig it up and see if I posted about it...it was very simple though to create...something like....


              @In
              @Out
              private Bean bean;
              
              @Begin(flushType=MANUAL)
              public void addBean() {
                 bean = new Bean();
              }
              
              @Begin(flushType=MANUAL)
              public void editBean(Bean b) {
                 bean = mgr.find(Bean.class, b.getId());
              }
              
              public void save() {
              
                 bean = mgr.merge(bean); //exception occured when adding or editing though I can't remember which one, so we changed this line
                 mgr.flush();
              
              }
              
              



              The above mgr.merge(bean) was fixed by making a simple change to...


                 if(bean.getId() == null)
                    mgr.persist(bean);
              



              I think before that change, the edit was failing or something with some very weird unrelated seam exception or something.


              The whole proxy vs. actual instance thing has been a HUGE thorn in the side of the team, people run into this all the time...I had one person change bean.getchildren() to an HQL query to get the same entities and it FIXED the problem.  ALL of these issues have been related to proxy vs. instance and is like the equals on the proxy/instance does not work and dig deeper (clearly the instance won't and only the proxy can in that case so instance.equals(proxy) would fail while hibernate could make proxy.equals(instance) succeed and seam would have to do two checks then every time or do an isProxy or something to make sure it puts the proxy first if there is one.


              We have run into way too many mismatches.  If you give me an email, I can send you one when we run into it again(we ran into one a month or every 2 months related to this...and it was a pain to debug unless you knew how to and I have gotten quite used to it)




              • 4. Re: how to wrap EntityManager with a proxy???
                Dean Hiller Expert

                oh, here is my other post that was related to the damn mgr.merge .....


                http://seamframework.org/Community/StaleStateExceptionAfterUpdateSuccessAndTxIsDone


                changing mgr.merge to if(bean.getId()== null) mgr.persist(bean) FIXES the problem.  I have nothing but nightmares when it comes to mgr.merge.

                • 5. Re: how to wrap EntityManager with a proxy???
                  Stuart Douglas Master

                  Have you tried using bytecode instrumentation? I have run into the same problems with proxies, but bytecode instrumentation fixed most of them.

                  • 6. Re: how to wrap EntityManager with a proxy???
                    Dean Hiller Expert

                    I don't know if it will help, but here is the code (using the mgr.persist though, but if that is changed to mgr.merge, it all breaks!!!!)


                    There is Event, User, and EventUser(cross reference).


                    @Name("eventManager")
                    @Scope(ScopeType.CONVERSATION)
                    public class EventManager extends ActionBase {
                    
                         @In
                         private UserDBO signedInUser;
                    
                         @In(required=false)
                         @Out
                         private EventDBO editableEvent;
                         
                         @Begin(flushMode=FlushModeType.MANUAL)
                         public void createEvent() {
                              editableEvent = new EventDBO();
                         }
                         
                         @Begin(flushMode=FlushModeType.MANUAL)
                         public void editEvent(UserEventDBO evt) {
                              UserEventDBO userEvent = entityManager.find(UserEventDBO.class, evt.getId());
                              editableEvent = userEvent.getEvent();
                         }
                         
                         @End
                         public void save() {
                              isValid = false;
                              UserDBO user = entityManager.find(UserDBO.class, signedInUser.getId());
                              
                              boolean isAdd = editableEvent.getId() == null;
                              if(isAdd && !validationPasses())
                                   return;
                              if(isAdd) 
                                   entityManager.persist(editableEvent);
                              
                              if(isAdd) {
                                   UserEventDBO userEvt = new UserEventDBO(editableEvent, user);
                                   entityManager.persist(userEvt);
                              }
                              
                              flushEntities();
                              Conversation.instance().end();
                              isValid = true;
                         }
                    
                         private boolean validationPasses() {
                              EventDBO event = EventDBO.findByName(entityManager, editableEvent.getName());
                              if(event != null) {
                                   addToControl("name", "This name is already being used");
                                   return false;
                              }
                              event = EventDBO.findByName(entityManager, editableEvent.getUrlAlias());
                              if(event != null) {
                                   addToControl("alias", "This alias is already being used");
                                   return false;
                              }          
                              return true;
                         }
                         
                    }
                    



                    • 7. Re: how to wrap EntityManager with a proxy???
                      Dean Hiller Expert

                      tell me more on bytecode instrumentation!!!!  Is there a setting in hibernate to just flip it on?????


                      I am just using standard hibernate out of the box though I thought hibernate used some bcel by default so I am confused as I thought some of it was already on.....How do I turn it on????????  that would rock!!!!!  instead of this proxy stuff that is very annoying.


                      THANKS!!!
                      Dean

                      • 8. Re: how to wrap EntityManager with a proxy???
                        Stuart Douglas Master

                        In your build script:


                             <target name="instrument" depends="compile">
                                  <taskdef name="instrument" classname="org.hibernate.tool.instrument.javassist.InstrumentTask">
                                       <classpath>
                                            <fileset dir="lib/earlib">
                                                 <include name="*.jar" />
                                            </fileset>
                                            <fileset dir="lib">
                                                 <include name="thirdparty-all.jar" />
                                            </fileset>
                                       </classpath>
                                  </taskdef>
                        
                                  <instrument verbose="false" >
                                       <fileset dir="${jar.dir}/com/mydomain/myentities">
                                            <include name="*.class" />
                                       </fileset>
                                       
                                  </instrument>
                             </target>
                        



                        You can then control it using @LazyToOne and @Proxy, have a google to find out more details.


                        Using bytecode instrumentation is slightly less lazy than proxies, but if you are dealing with inheritance hierarchies it is a life saver.

                        • 9. Re: how to wrap EntityManager with a proxy???
                          Arbi Sookazian Master

                          This is a very interesting thread.


                          Quoting SiA:



                          Merging is a crude operation and should be avoided if possible.


                          If the conversation is long-running, then the peristence manager stretches to match it, termed the Open Session in Conversation pattern.  As a result, entities aren't detached prematurely, which means you can avoid merging and instead benefit from automatic dirty checking.

                          I have typically tried to exclusively use LRC, SMPC and Hibernate manual flush.  If you do this, you don't need to use merge().


                          As far as the bytecode instrumentation, that is new to me and not sure I've ever even had a need to do this (i.e. get away from proxies).  I'd to see an official JBoss core reply to this topic...

                          • 10. Re: how to wrap EntityManager with a proxy???
                            Stuart Douglas Master

                            You aren't likely to see any problems unless you make use of inheritance in your entities, then the use of proxies become a big problem as you get a proxy for the base class instead of the child entity.


                            The other thing bytecode instrumentation is needed for is lazy property fetching, which is not particularly useful but can make life easier in certain circumstances.

                            • 11. Re: how to wrap EntityManager with a proxy???
                              Dean Hiller Expert

                              Took me a while to get google to tell me, but looks like SiA is Spring in Action.  What is LRC?


                              Also, yeah, but by not using merge, one has to use if(bean.getId() == null) mgr.persist() which frankly I don't feel like doing.


                              I think I am going to try to proxy the EntityManager and have it's persist do that so I don't need to always check myself, but that is a bit of a pain as I don't know what type the id field of the bean is to begin with and probably would need to borrow from hibernate's code there...not sure it is worth it.  I wish to god they had saveOrUpdate...hmmm, I could do that instead....reroute EntityManager's persist call to get the delegate and call saveOrUpdate...I like that idea.

                              • 12. Re: how to wrap EntityManager with a proxy???
                                Dean Hiller Expert

                                oh yeah, please realize, my code for save action bean method is for saving an entity that is new and needs to be persisted AND for entities that are simply being edited both which is why I need the if.  Seemed like the typical pattern but if there is a better one, let me know.  I have the typical...




                                @Out @In
                                private Bean bean;
                                
                                @Begin(flushType=MANUAL)
                                public void create() {
                                   bean = new Bean();
                                }
                                @Begin(flushType=MANUAL)
                                public void edit(Bean bean) {
                                   bean = mgr.find(Bean.class, bean.getId());
                                }
                                
                                @End
                                public void save() {
                                 //here need to persist if new, and do nothing if already 
                                 //persistent when what I really want is saveOrUpdate method call.
                                
                                }
                                



                                • 13. Re: how to wrap EntityManager with a proxy???
                                  sai burgula Novice
                                  Hi Dean

                                  I am also encountering the same problem in updating an object.  Please let me know what changes I can make to get it to work.

                                  In my case the update works for some objects, those that I had added into the DB, but for exisiting objects, I get the following stack trace.

                                  Invalid State Exception
                                  -----------------------

                                  javax.persistence.PersistenceException: org.hibernate.validator.InvalidStateException: validation failed for: edu.cmu.heinz.hcis.entity.CourseOffering
                                       at
                                  org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:535) at

                                  com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:114)
                                       at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:247)
                                       at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:86)
                                       at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177)
                                       at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1406)
                                       at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
                                       at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
                                       at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:146)
                                       at org.jboss.seam.transaction.UTTransaction.commit(UTTransaction.java:52)
                                       at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:603)
                                       at org.jboss.seam.jsf.SeamPhaseListener.handleTransactionsAfterPhase(SeamPhaseListener.java:341)
                                       at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:241)
                                       at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:192)
                                       at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)
                                       at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)
                                       at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                                       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                                       at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
                                       at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
                                       at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
                                       at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
                                       at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                                       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:173)
                                       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
                                       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
                                       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                                       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
                                       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
                                       at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                                       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                                       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)
                                       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                                       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                                       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                                       at java.lang.Thread.run(Unknown Source)
                                  Caused by: org.hibernate.validator.InvalidStateException: validation failed for: edu.cmu.heinz.hcis.entity.CourseOffering
                                       at org.hibernate.validator.event.ValidateEventListener.validate(ValidateEventListener.java:148)
                                       at org.hibernate.validator.event.ValidateEventListener.onPreUpdate(ValidateEventListener.java:177)
                                       at org.hibernate.action.EntityUpdateAction.preUpdate(EntityUpdateAction.java:217)
                                       at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:65)
                                       at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
                                       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
                                       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
                                       at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
                                       at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
                                       at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
                                       at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
                                       at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:523)
                                       ... 56 more
                                  15:11:39,751 ERROR [SeamPhaseListener] uncaught exception
                                  java.lang.IllegalStateException: Could not commit transaction
                                       at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:613)
                                       at org.jboss.seam.jsf.SeamPhaseListener.handleTransactionsAfterPhase(SeamPhaseListener.java:341)
                                       at org.jboss.seam.jsf.SeamPhaseListener.afterServletPhase(SeamPhaseListener.java:241)
                                       at org.jboss.seam.jsf.SeamPhaseListener.afterPhase(SeamPhaseListener.java:192)
                                       at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:175)
                                       at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:114)
                                       at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
                                       at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                                       at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:177)
                                       at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:267)
                                       at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:380)
                                       at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:507)
                                       at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68)
                                       at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69)
                                       at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
                                       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                                       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                                       at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
                                       at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:173)
                                       at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
                                       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)
                                       at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
                                       at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
                                       at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
                                       at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
                                       at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                                       at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241)
                                       at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
                                       at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
                                       at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
                                       at java.lang.Thread.run(Unknown Source)
                                  Caused by: javax.transaction.RollbackException: [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] [com.arjuna.ats.internal.jta.transaction.arjunacore.commitwhenaborted] Can't commit because the transaction is in aborted state
                                       at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1418)
                                       at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:135)
                                       at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:87)
                                       at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.commit(ServerVMClientUserTransaction.java:146)
                                       at org.jboss.seam.transaction.UTTransaction.commit(UTTransaction.java:52)
                                       at org.jboss.seam.jsf.SeamPhaseListener.commitOrRollback(SeamPhaseListener.java:603)
                                       ... 46 more
                                  Caused by: javax.persistence.PersistenceException: org.hibernate.validator.InvalidStateException: validation failed for: edu.cmu.heinz.hcis.entity.CourseOffering
                                       at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:535)
                                       at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:114)
                                       at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:247)
                                       at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:86)
                                       at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:177)
                                       at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1406)
                                       ... 51 more
                                  Caused by: org.hibernate.validator.InvalidStateException: validation failed for: edu.cmu.heinz.hcis.entity.CourseOffering
                                       at org.hibernate.validator.event.ValidateEventListener.validate(ValidateEventListener.java:148)
                                       at org.hibernate.validator.event.ValidateEventListener.onPreUpdate(ValidateEventListener.java:177)
                                       at org.hibernate.action.EntityUpdateAction.preUpdate(EntityUpdateAction.java:217)
                                       at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:65)
                                       at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
                                       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:234)
                                       at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142)
                                       at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
                                       at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
                                       at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
                                       at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
                                       at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:523)
                                  --------------------------------------------------------------

                                  I noticed that you said use persist instead of merge.

                                  I even made that change but the exception does not seem to go away.


                                  I also noticed a strange behavior

                                  For objects that I had added and updated, it(Hibernate save) works fine.

                                  But for objects that are existing, I get a invalid state exception.

                                  I tried refreshing the DB and checking if the DB is able to access the object, and it does it successfully

                                  Please give me an insight into this.
                                  • 14. Re: how to wrap EntityManager with a proxy???
                                    Dean Hiller Expert

                                    should be simple enough.  check the hibernate documentation out first...


                                    http://www.redhat.com/docs/manuals/jboss/jboss-eap-4.2/doc/hibernate/api/hibernate-annotations/org/hibernate/validator/InvalidStateException.html


                                    notice that this dumb part of hibernate does not put the info you want in the exception and says call this method to get the info on the failure(ie. which property failed validation).  So you basically, should do a entityManager.flush() in action mathod so it throws the exception earlier so you have a chance to catch it.  then with your try...catch.. around the flush you can then rethrow a NEW Exception filling in the message with which property was invalid.  The only reason for the flush is so you can catch the exception instead of seam catching it(ie. if seam catches it, how do you add code to seam).


                                    Hibernate should really fix those so we don't all have to add that code or even if seam added it as a work around, I would be ecstatic.  There are a few other instances where hibernate does not put all info you need in the exception message too!!!  very very annoying!!


                                    We have an ActionBase.java with a flush method that all action methods call so when these exceptions popup, it is in the logs correctly.  though we would like to convert to this proxy method so if someone accidentally uses mgr.flush, it is okay.


                                    later,
                                    Dean