5 Replies Latest reply on Nov 6, 2006 1:49 PM by jack1

    Bug when transaction rollback ocurrs and caching relationshi

    Javier Pedrido Newbie

      Hi,

      I think I have found and error in Jboss when transaction rollback ocurrs and JBoss is caching entity relationships. I'm using JBoss 4.0.4 GA, EJB3 RC7 and JBoss cache 1.2.4.SP2.

      This is the code of the test application:

      Entities

      package org.jboss.tutorial.relationships.bean;
      
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      
      import org.hibernate.annotations.Cache;
      import org.hibernate.annotations.CacheConcurrencyStrategy;
      
      @Entity
      @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
      public class Address implements java.io.Serializable {
       private Long id;
      
       private String city;
      
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       public Long getId() {
       return id;
       }
      
       public void setId(Long id) {
       this.id = id;
       }
      
       public String getCity() {
       return city;
       }
      
       public void setCity(String city) {
       this.city = city;
       }
      
       public boolean equals(Object o) {
       if(o instanceof Address) {
       return id.equals(((Address)o).getId());
       }
       return false;
       }
      
       public int hashCode() {
       return id.hashCode();
       }
      }
      
      package org.jboss.tutorial.relationships.bean;
      
      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 org.hibernate.annotations.Cache;
      import org.hibernate.annotations.CacheConcurrencyStrategy;
      
      @Entity
      @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
      public class Customer implements java.io.Serializable {
       Long id;
      
       String name;
      
       Set<Address> address;
      
       public Customer() {
       }
      
       @Id
       @GeneratedValue(strategy = GenerationType.IDENTITY)
       public Long getId() {
       return id;
       }
      
       public String getName() {
       return name;
       }
      
       public void setId(Long long1) {
       id = long1;
       }
      
       public void setName(String string) {
       name = string;
       }
      
       @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
       @OneToMany(targetEntity = Address.class, cascade = CascadeType.ALL)
       public Set<Address> getAddresses() {
       return address;
       }
      
       public void setAddresses(Set<Address> address) {
       this.address = address;
       }
      
       public boolean equals(Object o) {
       if(o instanceof Customer) {
       return id.equals(((Customer)o).getId());
       }
       return false;
       }
      
       public int hashCode() {
       return id.hashCode();
       }
      }
      


      Session bean

      package org.jboss.tutorial.relationships.bean;
      
      import java.util.HashSet;
      import java.util.Set;
      
      import javax.ejb.Remote;
      import javax.ejb.Stateless;
      import javax.persistence.EntityManager;
      import javax.persistence.PersistenceContext;
      import javax.persistence.Query;
      
      @Stateless
      @Remote(EntityTest.class)
      public class EntityTestBean implements EntityTest {
       private @PersistenceContext
       EntityManager manager;
      
       public void createCustomer() throws Exception {
      
       Customer bill = new Customer();
       bill.setName("Bill");
      
       Address address = new Address();
       address.setCity("Boston");
       manager.persist(address);
      
       Set<Address> addresses = new HashSet<Address>();
       addresses.add(address);
       bill.setAddresses(addresses);
      
       manager.persist(bill);
       manager.flush();
       }
      
       public void listCustomers() throws Exception {
       Query q = manager.createQuery("SELECT N FROM Customer N");
       for (Object o : q.getResultList()) {
       Customer c = (Customer) o;
       System.out.println(c.getName());
       for (Address a : c.getAddresses()) {
       System.out.println("---" + a.getCity());
       }
       }
       }
      
       public void editAddresses() throws Exception {
       Query q = manager.createQuery("SELECT N FROM Customer N");
       for (Object o : q.getResultList()) {
       Customer c = (Customer) o;
       c.setName("Javier");
       for (Address a : c.getAddresses()) {
       a.setCity("Buenos Aires");
       }
       }
       manager.flush();
      
       // Simulate error
       throw new MyException("Error rolling back changes");
       }
      
      }
      


      Exception
      package org.jboss.tutorial.relationships.bean;
      
      import javax.ejb.ApplicationException;
      
      @ApplicationException(rollback=true)
      public class MyException extends Exception {
      
       public MyException(String arg0) {
       super(arg0);
       }
      
      }
      


      Client application

      package org.jboss.tutorial.relationships.client;
      
      import javax.naming.InitialContext;
      
      import org.jboss.tutorial.relationships.bean.EntityTest;
      
      public class Client {
      
       public static void main(String[] args) throws Exception {
       InitialContext ctx = new InitialContext();
       EntityTest test = (EntityTest) ctx.lookup("EntityTestBean/remote");
      
       test.createCustomer();
       test.listCustomers();
      
       try {
       test.editAddresses();
       } catch(Exception e) {
       System.out.println(e.getMessage());
       }
      
       test.listCustomers();
       }
      }
      


      If I use the @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) annotation in the Customer.getAddress() the ouput is:


      [STDOUT] Bill
      [STDOUT] ---Boston
      [STDOUT] Error rolling back changes
      [STDOUT] Bill
      [STDOUT] ---Buenos Aires


      See that Customer entity rolls back OK, but the cached relationship doesn't
      If I don't use the cache, it works fine (in my opinion). The output is


      [STDOUT] Bill
      [STDOUT] ---Boston
      [STDOUT] Error rolling back changes
      [STDOUT] Bill
      [STDOUT] ---Boston


      Am I doing something wrong or is this a JBoss bug?

      Thanks in advance,
      Javier