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); }
}