[jboss-user] [JBoss Seam] - EntityManager and Conversation contex

Kruno do-not-reply at jboss.com
Sun Apr 8 10:25:05 EDT 2007


I read both books Seam Contextual components and JBoss® Seam: Simplicity and Power Beyond Java? EE from Safari but I can't  seem to find the answer.
I was under impression that persistence context is the same as hiberante session and that if @PersistenceContext(type = EXTENDED) that it would last during conversation, and that it would be shared between EntityManagers  from two different action beans if they are in the same conversation.
I hope sample code would explain better my question:
I made a little example.
first there are two entity beans directory and file 
directory has a set of files 
Directory:

  | package orka.test;
  | 
  | import java.util.LinkedHashSet;
  | import java.util.Set;
  | 
  | import javax.persistence.CascadeType;
  | import javax.persistence.Entity;
  | import javax.persistence.GeneratedValue;
  | import javax.persistence.GenerationType;
  | import javax.persistence.Id;
  | import javax.persistence.OneToMany;
  | import javax.persistence.Table;
  | 
  | import org.jboss.seam.annotations.Name;
  | 
  | @Entity
  | @Name("directory")
  | @Table(name="directory")
  | public class Directory {
  | 
  | 	@Id
  | 	@GeneratedValue(strategy=GenerationType.TABLE)
  | 	private long sifra;
  | 	
  | 	private String name;
  | 	
  | 	@OneToMany(cascade={CascadeType.ALL},mappedBy="directory")
  | 	private Set<File>files= new LinkedHashSet<File>();
  | 
  | 
  | 	
  | 	
  | 	public Set<File> getFiles() {
  | 		return files;
  | 	}
  | 
  | 
  | 	public void setFiles(Set<File> files) {
  | 		this.files = files;
  | 	}
  | 
  | 
  | 	public long getSifra() {
  | 		return sifra;
  | 	}
  | 
  | 
  | 	public void setSifra(long sifra) {
  | 		this.sifra = sifra;
  | 	}
  | 
  | 
  | 	public String getName() {
  | 		return name;
  | 	}
  | 
  | 
  | 	public void setName(String name) {
  | 		this.name = name;
  | 	}
  | 	
  | 	
  | 	
  | }
  | 
  | 

File:

  | package orka.test;
  | 
  | import javax.persistence.Entity;
  | import javax.persistence.GeneratedValue;
  | import javax.persistence.GenerationType;
  | import javax.persistence.Id;
  | import javax.persistence.JoinColumn;
  | import javax.persistence.ManyToOne;
  | import javax.persistence.Table;
  | 
  | import org.hibernate.validator.NotNull;
  | import org.jboss.seam.annotations.Name;
  | 
  | 
  | @Entity
  | @Name("file")
  | @Table(name="file")
  | public class File {
  | 	
  | 	@Id
  | 	@GeneratedValue(strategy = GenerationType.TABLE)
  | 	private long sifra;
  | 
  | 	@NotNull
  | 	private String name;
  | 	
  | 	
  | 	@ManyToOne
  | 	@JoinColumn(name="directory")
  | 	private Directory directory;
  | 	
  | 	
  | 	//geters seters
  | 
  | 	public String getName() {
  | 		return name;
  | 	}
  | 
  | 	public void setName(String name) {
  | 		this.name = name;
  | 	}
  | 
  | 	public long getSifra() {
  | 		return sifra;
  | 	}
  | 
  | 	public void setSifra(long sifra) {
  | 		this.sifra = sifra;
  | 	}
  | 
  | 	public Directory getDirectory() {
  | 		return directory;
  | 	}
  | 
  | 	public void setDirectory(Directory directory) {
  | 		this.directory = directory;
  | 	}
  | 
  | 	
  | 	
  | }
  | 
  | 

Then two action beans: DirectoryActionBean and FileActionBean
DirectoryActionBean:

  | package orka.test;
  | 
  | import static javax.persistence.PersistenceContextType.EXTENDED;
  | 
  | import javax.ejb.Remove;
  | import javax.ejb.Stateful;
  | import javax.persistence.EntityManager;
  | import javax.persistence.PersistenceContext;
  | 
  | import org.jboss.seam.annotations.Create;
  | import org.jboss.seam.annotations.Destroy;
  | import org.jboss.seam.annotations.In;
  | import org.jboss.seam.annotations.Name;
  | import org.jboss.seam.annotations.Out;
  | import org.jboss.seam.log.Log;
  | 
  | @Stateful
  | @Name("directoryAction")
  | public class DirectoryActionBean implements DirectoryAction {
  | 
  | 	@PersistenceContext(type = EXTENDED)
  | 	private EntityManager manager;
  | 
  | 	@SuppressWarnings("unused")
  | 	@org.jboss.seam.annotations.Logger
  | 	private Log log;
  | 
  | 	@In(required = false)
  | 	@Out
  | 	Directory directory;
  | 
  | 	public void saveDir() {
  | 		manager.persist(directory);
  | 	}
  | 
  | 	public String goFiles() {
  | 		return "files";
  | 	}
  | 
  | 	@Remove
  | 	@Destroy
  | 	public void destroy() {
  | 
  | 	}
  | 
  | 	@Create
  | 	public void create() {
  | 
  | 		directory = new Directory();
  | 		directory.setName("dirOne");
  | 		manager.persist(directory);
  | 
  | 	}
  | 
  | }
  | 
  | 

FileActionBean:

  | package orka.test;
  | 
  | import static javax.persistence.PersistenceContextType.EXTENDED;
  | 
  | import javax.ejb.Remove;
  | import javax.ejb.Stateful;
  | import javax.persistence.EntityManager;
  | import javax.persistence.PersistenceContext;
  | 
  | import org.jboss.seam.annotations.Destroy;
  | import org.jboss.seam.annotations.In;
  | import org.jboss.seam.annotations.Name;
  | import org.jboss.seam.annotations.Out;
  | import org.jboss.seam.log.Log;
  | 
  | 
  | 
  | 
  | @Stateful
  | @Name("fileAction")
  | public class FileActionBean implements FileAction {
  | 
  | 
  | 	@PersistenceContext(type = EXTENDED)
  | 	private EntityManager manager;
  | 
  | 	@SuppressWarnings("unused")
  | 	@org.jboss.seam.annotations.Logger
  | 	private Log log;
  | 
  | 	@In
  | 	@Out
  | 	Directory directory;
  | 	
  | 	public void newFile(){
  | 		File file= new File();
  | 		file.setName("fileOne");
  | 		file.setDirectory(directory);
  | 		directory.getFiles().add(file);
  | 		manager.persist(file);
  | 	}
  | 	
  | 	
  | 	public String backToDir(){
  | 		return "dir";
  | 	}
  | 	
  | 	@Remove
  | 	@Destroy
  | 	public void destroy() {
  | 
  | 	}
  | }
  | 
  | 

and at last part of pages.xml:

  | 
  |   <page view-id="/directory.jsp">
  |    	<begin-conversation join="true"/>
  |   	<navigation >
  |   		<rule if-outcome="files">
  |   			<redirect view-id="/file.jsp">
  |   		</redirect>
  |   		</rule>
  |   		
  |   	</navigation>	
  |   </page>
  |    
  |    <page view-id="/file.jsp">
  |    	<navigation >
  |   		<rule if-outcome="dir">
  |   			<redirect view-id="/directory.jsp">
  |   		</redirect>
  |   		</rule>
  |   		
  |   	</navigation>	
  |   </page>
  | 
I will not bother you with jsp pages let just say that directory.jsp references only directory entity bean a makes calls only to directoryActionBean it is the same pattern for file.jsp 
Now to explain what I do: At first 
I create one directory from directoryAction than go to file.jsp and create file, add him in directory and persist file.
After that I return focus to directory.jsp and invoke method save.
Then I get exception
 org.hibernate.PersistentObjectException: detached entity passed to persist: orka.test.File

  |  javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: orka.test.File
  | 	at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:647)
  | 	at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:218)
  | 	at org.jboss.ejb3.entity.ExtendedEntityManager.persist(ExtendedEntityManager.java:104)
  | 	at orka.test.DirectoryActionBean.saveDir(DirectoryActionBean.java:33)
  | 	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.seam.intercept.EJBInvocationContext.proceed(EJBInvocationContext.java:37)
  | 	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:55)
  | 	at org.jboss.seam.interceptors.BijectionInterceptor.bijectNonreentrantComponent(BijectionInterceptor.java:79)
  | 	at org.jboss.seam.interceptors.BijectionInterceptor.bijectComponent(BijectionInterceptor.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.seam.util.Reflections.invoke(Reflections.java:18)
  | 	at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
  | 	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
  | 	at org.jboss.seam.interceptors.ManagedEntityIdentityInterceptor.aroundInvoke(ManagedEntityIdentityInterceptor.java:36)
  | 	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.seam.util.Reflections.invoke(Reflections.java:18)
  | 	at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
  | 	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
  | 	at org.jboss.seam.interceptors.OutcomeInterceptor.interceptOutcome(OutcomeInterceptor.java:21)
  | 	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.seam.util.Reflections.invoke(Reflections.java:18)
  | 	at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
  | 	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
  | 	at org.jboss.seam.interceptors.ConversationInterceptor.endOrBeginLongRunningConversation(ConversationInterceptor.java:52)
  | 	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.seam.util.Reflections.invoke(Reflections.java:18)
  | 	at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
  | 	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
  | 	at org.jboss.seam.interceptors.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:27)
  | 	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.seam.util.Reflections.invoke(Reflections.java:18)
  | 	at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:169)
  | 	at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:64)
  | 	at org.jboss.seam.intercept.RootInterceptor.createSeamInvocationContext(RootInterceptor.java:144)
  | 	at org.jboss.seam.intercept.RootInterceptor.invokeInContexts(RootInterceptor.java:129)
  | 	at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:102)
  | 	at org.jboss.seam.intercept.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:50)
  | 	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.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:118)
  | 	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.ExtendedPersistenceContextPropagationInterceptor.invoke(ExtendedPersistenceContextPropagationInterceptor.java:71)
  | 	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:46)
  | 	at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
  | 	at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
  | 	... 68 more
  | 
It works fine if I merge directory before persist, but I don't understand why do I have to merge some thing if it was changed in side long running session and it should not have been detached. Maybe I am doing some thing wrong or I did not understand concept of conversation very well.
Like I sad at the beginning I understood that one session could span many request/response cycles and many action beans as long as they are in one conversation and session is long-running.
To merge some thing before persist in some situations is not a big deal, but I would really like to fully understand concepts behind seam
Please Explain!!!
Thanks in advance Kruno.

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4035595#4035595

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4035595




More information about the jboss-user mailing list