-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Removing a detached instance in JPA
PostPosted: Thu Sep 09, 2010 5:13 am 
Newbie

Joined: Wed Jul 01, 2009 6:38 am
Posts: 11
No way to delete an instance when executing on a JEE server, it works fine in a junit test.
Env :
glassfish 3.0.1
hibernate 3.5.5
spring 3.0.4


Here is the exception
Code:
ava.lang.IllegalArgumentException: Removing a detached instance fr.tm.ima.metier.afo.exima.bo.ProfilCollaborateurBO#
   at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:65)
   at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:108)
   at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
   at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:948)
   at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:926)
   at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:698)
   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:597)
   at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
   at $Proxy175.remove(Unknown Source)
   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:597)
   at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
   at $Proxy175.remove(Unknown Source)
   at fr.tm.ima.metier.afo.exima.ba.collaborateur.UpdateCollaborateurBA.execute(UpdateCollaborateurBA.java:112)
...


Unlike the exception says, the object is not detached because i've just read it with the same entitymanager
Code:
Query req = em.createNamedQuery("getProfilByCollaborateurId");
req.setParameter("numCollaborateur", new Integer(pCollaborateur.getIdCollaborateur()));
List<ProfilCollaborateurBO> profilsBase = (List<ProfilCollaborateurBO>) req.getResultList();
for (ProfilCollaborateurBO profilCollaborateurBO : profilsBase) {
    em.remove(profilCollaborateurBO);
}


I even tried to re-read it,
Code:
Query req = em.createNamedQuery("getProfilByCollaborateurId");
req.setParameter("numCollaborateur", new Integer(pCollaborateur.getIdCollaborateur()));
List<ProfilCollaborateurBO> profilsBase = (List<ProfilCollaborateurBO>) req.getResultList();
for (ProfilCollaborateurBO profilCollaborateurBO : profilsBase) {
    ProfilCollaborateurBO bo = em.find(ProfilCollaborateurBO.class, profilCollaborateurBO.getId());
    em.remove(bo);
}

The transaction is supplied by the container via spring.
It 's like the entitymanager create a new connection or clean its session for each database access. It can't be the case because the transaction works fine for everything else (update, insert, commit/rollback).

It could be a spring configuration problem, so here is my spring configuration
Code:
<context:annotation-config />
<tx:annotation-driven/>
<jee:jndi-lookup id="dataSource" jndi-name="..."/>
   
   <bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
      <!-- utilise la version multiple même si ici ce n'est pas utile -->
      <property name="persistenceXmlLocations">
         <list>
            <value>classpath*:persistenceCUAD.xml</value>
         </list>
      </property>
      <property name="defaultDataSource" ref="dataSource" />
      <property name="persistenceUnitPostProcessors">
         <list>
            <bean class="...spring.config.MappingPostProcessor">
               <property name="mappings" ref="mappings" />
            </bean>
         </list>
      </property>
   </bean>

   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="persistenceUnitName" value="cuadPU"/>
      <property name="jpaVendorAdapter">
         <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
      </property>
      <property name="persistenceUnitManager" ref="persistenceUnitManager" />
      <property name="jpaProperties">
         <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.DB2400Dialect</prop>
               <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.SunONETransactionManagerLookup</prop>
            <prop key="hibernate.format_sql">false</prop>
         </props>
      </property>
   </bean>
   ...


and the persitence.xml
Code:
<persistence-unit name="cuadPU" transaction-type="JTA"> 
  </persistence-unit>


The main difference in the junit test is the transaction-type which is "RESOURCE_LOCAL" and the datasource which is local
Code:
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
      <property name="driverClass" value="com.ibm.as400.access.AS400JDBCDriver" />
      <property name="url" value="jdbc:as400://..." />
      <property name="username" value="..." />
      <property name="password" value="..." />
</bean>


Thanks for any help
Fred

Edit : same behaviour on a websphere 7.0

Edit2 : after a little debug, i noticed the entitymanager's persistenceContext was always empty even after a request. Using the underlying session (wth em.getDelegate()) with the same code above, the persistencecontext works correctly. So the question is why the entitymanager's persistenceContext is always empty ? is it normal ? i missed something in documentation, is there any flag to activate to use this persistencecontext ?
(I did not mentioned above: this code is inside an EJB3 stateless)


Top
 Profile  
 
 Post subject: Re: Removing a detached instance in JPA
PostPosted: Tue Sep 14, 2010 3:42 am 
Newbie

Joined: Wed Jul 01, 2009 6:38 am
Posts: 11
I found the answer, the spring conf was not good. To sum up, i wanted to use EJB3, Spring, Hibernate and JTA. In my configuration, spring did not use the container transaction manager, the tag <tx:jta-transaction-manager/> solved this issue

The correct configuration is (with simplified file)
persistence.xml
Code:
<persistence-unit name="yourPU" transaction-type="JTA">   
<jta-data-source>jdbc/DS_cuad</jta-data-source>   
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
            <property name="hibernate.dialect"
                      value="org.hibernate.dialect.DB2400Dialect" />
            <property name="hibernate.transaction.manager_lookup_class"
                      value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
...

The "hibernate.transaction.manager_lookup_class" depends on the JEE server (here is glassfish)

context spring
Code:
...
<context:annotation-config />
<tx:annotation-driven/>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="yourPU" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            </bean>
        </property>
    </bean>
    <tx:jta-transaction-manager/>
...


The file beanRefContext.xml points to your spring context
Code:
<bean id="businessBeanFactory"
          class="org.springframework.context.support.ClassPathXmlApplicationContext">
      <constructor-arg>
            <list>
                <value>your spring Context</value>
            </list>
        </constructor-arg>
     </bean>

Your EJB3 contains the following annotation to load the spring context
Code:
@Interceptors({SpringBeanAutowiringInterceptor.class})


Please note that the @Transactionnal (spring specific) can't annotate directly your EJB method (or the whole EJB) because the EJB is not a spring bean. You have to delegate calls on spring managed bean to use @Transactionnal


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.