Trouble with transactions
knaveofhearts Jul 11, 2006 1:11 PMI am missing something fundamental about transactions and the discussion of entity relationships in ch. 7 combined with inheritence, as in ch. 8. There are a client, a stateless session bean, and 3 entities: GeopolUnit, Planet, and Country. Planet and Country both inherit from GeopolUnit. Planet is supposed to contain a list of countries, in a one-to-many unidirectional relationship. In the client, I can create a planet and a country separately. But when I try to create the planet already containing a country by un-commenting the "planet.add(country);" line in the client code listing below, I get the error. I have tried various combinations of putting methods into transactions and flushing things, but so far have been unsuccessful. (I think I ought to be able to omit the "createCountry" call in the client because of the cascade PERSIST constraint, but I get the same kind of error regardless of whether that call is in or out.)
Any help is appreciated.
K/H
[java] Exception in thread "main" java.lang.RuntimeException: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[Forma tId=257, GlobalId=mulder.vorticityCorp.com/24, BranchQual=, localId=24] status=STATUS_NO_TRANSACTION; - nested throwable: (javax.persistence.PersistenceEx ception: org.hibernate.TransientObjectException: com.ejbWB.geopolUnit.Country) [java] at org.jboss.aspects.tx.TxPolicy.handleEndTransactionException(TxPolicy.java:198) [java] at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:180) [java] at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87) [java] at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:197) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:225) [java] at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106) [java] at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82) [java] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:828) [java] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:681) [java] at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:358) [java] at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:412) [java] at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:239) [java] Caused by: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=mulder.vorticityCorp.com/2 4, BranchQual=, localId=24] status=STATUS_NO_TRANSACTION; - nested throwable: (javax.persistence.PersistenceException: org.hibernate.TransientObjectExcept ion: com.ejbWB.geopolUnit.Country) [java] at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:372) [java] at org.jboss.tm.TxManager.commit(TxManager.java:240) [java] at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175) [java] at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87) [java] at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:197) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:225) [java] at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106) [java] at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82) [java] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:828) [java] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:681) [java] at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:358) [java] at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:412) [java] at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:239) [java] at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInvoker.java:190) [java] at org.jboss.remoting.Client.invoke(Client.java:525) [java] at org.jboss.remoting.Client.invoke(Client.java:488) [java] at org.jboss.aspects.remoting.InvokeRemoteInterceptor.invoke(InvokeRemoteInterceptor.java:55) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.tx.ClientTxPropagationInterceptor.invoke(ClientTxPropagationInterceptor.java:61) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.security.SecurityClientInterceptor.invoke(SecurityClientInterceptor.java:55) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:65) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessRemoteProxy.invoke(StatelessRemoteProxy.java:102) [java] at $Proxy0.createPlanet(Unknown Source) [java] at com.ejbWB.clients.Client.main(Client.java:22) [java] Caused by: javax.persistence.PersistenceException: org.hibernate.TransientObjectException: com.ejbWB.geopolUnit.Country [java] at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:567) [java] at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:484) [java] at org.jboss.tm.TransactionImpl.doBeforeCompletion(TransactionImpl.java:1491) [java] at org.jboss.tm.TransactionImpl.beforePrepare(TransactionImpl.java:1110) [java] at org.jboss.tm.TransactionImpl.commit(TransactionImpl.java:324) [java] at org.jboss.tm.TxManager.commit(TxManager.java:240) [java] at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:175) [java] at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:87) [java] at org.jboss.aspects.tx.TxInterceptor$Required.invoke(TxInterceptor.java:197) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.tx.TxPropagationInterceptor.invoke(TxPropagationInterceptor.java:76) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessInstanceInterceptor.invoke(StatelessInstanceInterceptor.java:62) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.aspects.security.AuthenticationInterceptor.invoke(AuthenticationInterceptor.java:78) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.ENCPropagationInterceptor.invoke(ENCPropagationInterceptor.java:47) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.asynchronous.AsynchronousInterceptor.invoke(AsynchronousInterceptor.java:106) [java] at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101) [java] at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:225) [java] at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:106) [java] at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82) [java] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:828) [java] at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:681) [java] at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:358) [java] at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:412) [java] at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:239) [java] Caused by: org.hibernate.TransientObjectException: com.ejbWB.geopolUnit.Country [java] at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:216) [java] at org.hibernate.type.EntityType.getIdentifier(EntityType.java:108) [java] at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:71) [java] at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:732) [java] at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1080) [java] at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:26) [java] at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248) [java] at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232) [java] at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:143) [java] at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297) [java] at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) [java] at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:993) [java] at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:340) [java] at org.hibernate.ejb.AbstractEntityManagerImpl$1.beforeCompletion(AbstractEntityManagerImpl.java:475)
The client:
package com.ejbWB.clients; import com.ejbWB.admin.AdminRemote; import com.ejbWB.geopolUnit.*; import javax.naming.*; import javax.rmi.PortableRemoteObject; public class Client { public static void main(String [] args) { try { Context jndiContext = getInitialContext(); Object ref = jndiContext.lookup("AdminBean/remote"); AdminRemote admin = (AdminRemote)ref; Planet planet = new Planet(); Country country = new Country("Italy"); long c_id = admin.createCountry(country); System.out.println("country id=" + c_id); //planet.add(country); long p_id = admin.createPlanet(planet); System.out.println("planet id=" + p_id); } catch (javax.naming.NamingException ne) { ne.printStackTrace(); } } public static Context getInitialContext() throws javax.naming.NamingException { return new javax.naming.InitialContext(); } }
The session bean:
package com.ejbWB.admin; import javax.ejb.*; import javax.persistence.*; import java.util.*; import com.ejbWB.geopolUnit.*; @Stateless public class AdminBean implements AdminRemote { @PersistenceContext(unitName="ejbWB") private EntityManager manager; public long createPlanet(Planet planet) { manager.persist(planet); return planet.getId(); } public long createCountry(Country country) { manager.persist(country); return country.getId(); } /* I WOULD LIKE TO BE ABLE TO HAVE THIS METHOD WORK public Planet findPlanet(long pKey) { Planet planet = manager.find(Planet.class, pKey); List<Country> countries = planet.getCountries(); Iterator iter = countries.iterator(); while (iter.hasNext()) { Country c = (Country)iter.next(); String name = c.getName(); } return planet; } */ }[size]
The remote interface is obvious and is omitted.
The three entities:
package com.ejbWB.geopolUnit; import javax.persistence.*; @Entity @Inheritance(strategy=InheritanceType.JOINED) public abstract class GeopolUnit implements java.io.Serializable { public GeopolUnit(String name) { setName(name); } @Id @GeneratedValue public long getId() { return id; } public void setId(long id) { this.id = id; } @Column(nullable=false) public String getName() { return name; } public void setName(String name) { this.name = new String(name); } private String name; private long id; } //-------------- package com.ejbWB.geopolUnit; import javax.persistence.*; import java.util.List; import java.util.LinkedList; @Entity public class Planet extends GeopolUnit implements java.io.Serializable { public Planet() { super("Earth"); } public void add(Country country) { countries.add(country); } @OneToMany(cascade={CascadeType.PERSIST}) @OrderBy("name ASC") public List<Country> getCountries() { return countries; } public void setCountries(List<Country> countries) { this.countries = countries; } private List<Country> countries = new LinkedList<Country>(); } //-------------- package com.ejbWB.geopolUnit; import javax.persistence.*; @Entity public class Country extends GeopolUnit implements java.io.Serializable { public Country(String name) { super(name); } }