[jboss-user] [EJB 3.0] - Is there an EntityListener equivalent for when assocaitions

benc do-not-reply at jboss.com
Thu Apr 10 16:59:13 EDT 2008


I have a scenario where I need to know when an association between two entities is changed in the same fashion as @PostUpdate and @PostPersist in EntityListener.  My original assumption was that EntityListener would do what I wanted; but, it seems to only be called for fields that are stored directly in the backing table of an entity... So when I change collections defined by @OneToMany or @ManyToMany with @JoinTable the EntityListener is not called.

I can force the EntityListener to be called by setting another field in the Entity (labeled dirty in the attached code example) but I can't help but think there is a better solution than this.

I've created as simple an ear as I could to demonstrate this behavior.  EntityA contains a list of EntityB objects.  A servlet has two methods it can call.  The first creates an instance of EntityA with 3 instances of EntityB, persists them, then adds another instance of EntityB and persists them.  The second method called by the servlet does the same thing except it also sets the dirty field on EntityA when it adds the fourth EntityB instance.

Output from non-dirty servlet run

  | 15:39:30,077 INFO  [STDOUT] Entity Listener Called for EntityA : 1
  | 15:39:30,077 INFO  [STDOUT] Dirty : false
  | 15:39:30,077 INFO  [STDOUT] EntityB list : [1, 2, 3]
  | 

Output from dirty servlet run

  | 15:39:47,241 INFO  [STDOUT] Entity Listener Called for EntityA : 2
  | 15:39:47,241 INFO  [STDOUT] Dirty : false
  | 15:39:47,241 INFO  [STDOUT] EntityB list : [5, 6, 7]
  | 15:39:47,255 INFO  [STDOUT] Entity Listener Called for EntityA : 2
  | 15:39:47,255 INFO  [STDOUT] Dirty : true
  | 15:39:47,256 INFO  [STDOUT] EntityB list : [5, 6, 7, 8]
  | 

Source Code:

EntityA.java

  | package test;
  | 
  | import java.util.Collection;
  | 
  | import javax.persistence.Entity;
  | import javax.persistence.EntityListeners;
  | import javax.persistence.GeneratedValue;
  | import javax.persistence.Id;
  | import javax.persistence.JoinColumn;
  | import javax.persistence.JoinTable;
  | import javax.persistence.OneToMany;
  | 
  | @Entity
  | @EntityListeners(AssociationTestEntityListener.class)
  | public class EntityA
  | {
  | 	protected int id;
  | 	protected boolean dirty;
  | 	protected Collection<EntityB> b;
  | 	
  | 	@Id
  | 	@GeneratedValue
  | 	public int getId()
  | 	{
  | 		return id;
  | 	}
  | 	public void setId(int id)
  | 	{
  | 		this.id = id;
  | 	}
  | 
  | 	public boolean isDirty()
  | 	{
  | 		return dirty;
  | 	}
  | 	public void setDirty(boolean dirty)
  | 	{
  | 		this.dirty = dirty;
  | 	}
  | 	
  | 	
  | 	@OneToMany
  | 	@JoinTable(
  | 	           name = "a_b", 
  | 	           joinColumns = {@JoinColumn(name = "b_id")}, 
  | 	           inverseJoinColumns = @JoinColumn(name = "a_id")
  | 	           )
  | 	public Collection<EntityB> getB()
  | 	{
  | 		return b;
  | 	}
  | 	public void setB(Collection<EntityB> b)
  | 	{
  | 		this.b = b;
  | 	}
  | }
  | 

EntityB.java

  | package test;
  | 
  | import javax.persistence.Entity;
  | import javax.persistence.GeneratedValue;
  | import javax.persistence.Id;
  | 
  | @Entity
  | public class EntityB
  | {
  | 	protected int id;
  | 	
  | 	@Id
  | 	@GeneratedValue
  | 	public int getId()
  | 	{
  | 		return id;
  | 	}
  | 	public void setId(int id)
  | 	{
  | 		this.id = id;
  | 	}
  | }
  | 

AssociationTestEntityListener.java

  | package test;
  | 
  | import javax.persistence.PostPersist;
  | import javax.persistence.PostUpdate;
  | 
  | public class AssociationTestEntityListener
  | {
  | 	@PostPersist
  | 	@PostUpdate
  | 	public void postEvent(EntityA a)
  | 	{
  | 		StringBuffer bstr = new StringBuffer("EntityB list : [");
  | 		for( EntityB b: a.getB())
  | 		{
  | 			bstr.append(b.getId());
  | 			bstr.append(", ");
  | 		}
  | 		bstr.replace(bstr.lastIndexOf(", "), bstr.length(), "]");
  | 		
  | 		System.out.println();
  | 		System.out.println("Entity Listener Called for EntityA : " + a.getId());
  | 		System.out.println("Dirty : " + a.isDirty());
  | 		System.out.println(bstr.toString());
  | 		System.out.println();
  | 		a.setDirty(false);
  | 	}
  | }
  | 

TestListenerStatelessSession.java

  | package test;
  | 
  | import java.util.ArrayList;
  | import java.util.Collection;
  | 
  | import javax.ejb.Stateless;
  | import javax.persistence.EntityManager;
  | import javax.persistence.PersistenceContext;
  | 
  | import org.jboss.annotation.ejb.LocalBinding;
  | 
  | @Stateless (name="TestListener")
  | @LocalBinding(jndiBinding="AT/TestListener")
  | public class TestListenerStatelessSesssion implements TestListenerSession
  | {
  | 	@PersistenceContext(unitName="defaultPU")
  | 	EntityManager em;
  | 	
  | 	/* (non-Javadoc)
  | 	 * @see test.TestListenerSession#doStuff()
  | 	 */
  | 	public void testWithDirty()
  | 	{
  | 		Collection<EntityB> bList = new ArrayList<EntityB>(3);
  | 		bList.add(getNewB());
  | 		bList.add(getNewB());
  | 		bList.add(getNewB());
  | 		
  | 		EntityA a = new EntityA();
  | 		a.setB(bList);
  | 		em.persist(a);
  | 		
  | 		a.setDirty(true);
  | 		bList = a.getB();
  | 		bList.add(getNewB());
  | 		a.setB(bList);
  | 		em.merge(a);
  | 	}
  | 	
  | 	/* (non-Javadoc)
  | 	 * @see test.TestListenerSession#doStuff()
  | 	 */
  | 	public void testWithoutDirty()
  | 	{
  | 		Collection<EntityB> bList = new ArrayList<EntityB>(3);
  | 		bList.add(getNewB());
  | 		bList.add(getNewB());
  | 		bList.add(getNewB());
  | 		
  | 		EntityA a = new EntityA();
  | 		a.setB(bList);
  | 		em.persist(a);
  | 		
  | 		bList = a.getB();
  | 		bList.add(getNewB());
  | 		a.setB(bList);
  | 		em.merge(a);
  | 	}
  | 
  | 	private EntityB getNewB()
  | 	{
  | 		EntityB rc = new EntityB();
  | 		em.persist(rc);
  | 		return rc;
  | 	}
  | }
  | 

TestListenerSession.java

  | package test;
  | 
  | import javax.ejb.Local;
  | 
  | 
  | @Local
  | public interface TestListenerSession
  | {
  | 
  | 	public abstract void testWithDirty();
  | 	public abstract void testWithoutDirty();
  | 
  | }
  | 

AT.jsp

  | <%@ page import="test.*, javax.naming.*, java.text.*"%>
  | 
  | <%!
  |    private TestListenerSession tls = null;
  |    public void jspInit ()
  |    {
  |      try 
  |      {
  |        InitialContext ctx = new InitialContext();
  |        tls = (TestListenerSession) ctx.lookup("AT/TestListener");
  |      }
  |      catch (Exception e) 
  |      {
  |        e.printStackTrace ();
  |      }
  |    }
  | %>
  | 
  | <%
  |    try
  |    {
  | 	   if (request.getParameter("TestWithoutDirty") != null) 
  | 	   {
  | 		   tls.testWithoutDirty();
  | 	   } 
  | 	   else if (request.getParameter("TestWithDirty") != null) 
  | 	   {
  | 		   tls.testWithDirty();
  | 	   }
  |    }
  |    catch (Exception e) 
  |    {
  |      e.printStackTrace ();
  |    }
  |  %>
  | 
  | <html>
  | <body>
  | 
  | <p>Test Listener<br />
  | <form action="AT.jsp" method="POST">
  | 	<input type="submit" value="TestWithoutDirty" name="TestWithoutDirty">
  | 	<input type="submit" value="TestWithDirty" name="TestWithDirty">
  | </form>
  | </p>
  | 
  | </body>
  | </html>
  | 

Application.xml

  | <?xml version="1.0" encoding="UTF-8"?>
  | <application 
  |     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  |     xmlns="http://java.sun.com/xml/ns/javaee" 
  |     xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" 
  |     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  |     http://java.sun.com/xml/ns/javaee/application_5.xsd" 
  |     id="Application_ID" 
  |     version="5">
  |  <module>
  |         <web>
  |                 <web-uri>ROOT.war</web-uri>
  |                 <context-root>/</context-root>
  |         </web>
  |   </module>
  |   <module>
  |     <ejb>AssociationTest.jar</ejb>
  |   </module>
  | </application>
  | 

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

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



More information about the jboss-user mailing list