I have two simple Entities ( see attachment ) and a simple SLSB with container managed transactions which is called by a trivial servlet.
Inside a UserTransaction I add a number of items then check to see that they have been added
long newTotal = -1; try { InitialContext context = new InitialContext(); javax.transaction.UserTransaction tx = (javax.transaction.UserTransaction) context .lookup("java:comp/UserTransaction"); tx.begin(); SLSBObjDbRemote bean = (SLSBObjDbRemote) context .lookup("SLSBObjDb"); long oldAmount = bean.countItems(); bean.addItems(howMany); newTotal = bean.countItems(); if(newTotal < (howMany+oldAmount)) { System.err.println("Only found " + newTotal + " items expected " + (howMany + oldAmount)); } tx.commit(); } catch
The problem is that the items that I add in the transaction are not visible when I go to count them;
TypedQuery<Long> q = em.createQuery("SELECT COUNT(x) FROM Item x", Long.class); try { return q.getSingleResult(); } catch (javax.persistence.NoResultException ex) { return -1; }
Here are the two Entities;
@Entity public class Item { @SuppressWarnings("unused") //used by JPA @ManyToOne private Singleton singleton; @Basic private String cachedKey; @Id private String id; @Version private int version; @Basic private Integer property; // Bonus empty constructor generated for JPA protected Item() { super(); } public Item(Singleton singleton, int intValue) { id = java.util.UUID.randomUUID().toString(); this.singleton = singleton; this.cachedKey = new Integer(intValue).toString(); setProperty(intValue); } public Integer getJPAVersion() { return version; } public String getCachedKey() { return cachedKey; } public void setProperty(Integer newValue) { property = newValue; } public Integer getProperty() { return property; } public String getInfo() { return "Item: id=" + id + ", version=" + version + ", key=" + cachedKey + ", property=" + property; } public String getId() { return id; } }
@Entity public class Singleton { public static Singleton getInstance(EntityManager em) { Singleton c = em.find(Singleton.class, "1"); if (c == null) { c = new Singleton(); em.persist(c); } return c; } @Id protected String id = "1"; @SuppressWarnings("unused") // used by JPA @Version private int version; @Basic protected java.lang.Integer lastInstance; public void generateItems(EntityManager em, int howMany) { if (lastInstance == null) { lastInstance = 0; } int endCnt = lastInstance + howMany; int startCnt = lastInstance; while (endCnt > startCnt) { startCnt++; Item item = new Item(this, startCnt); em.persist(item); lastInstance = startCnt; } } public long howManyItemsExist(EntityManager em) { TypedQuery<Long> q = em.createQuery("SELECT COUNT(x) FROM Item x", Long.class); try { return q.getSingleResult(); } catch (javax.persistence.NoResultException ex) { return -1; } } }
Here is the bean
@TransactionAttribute(TransactionAttributeType.REQUIRED) @Stateless(mappedName = "SLSBObjDb") public class SLSBObjDb implements SLSBObjDbRemote { @PersistenceContext(unitName = "Experiment8objPU" ) EntityManager emInj; /** * Default constructor. */ public SLSBObjDb() { } @Override public void addItems(int howMany) { Singleton singleton = Singleton.getInstance(emInj); singleton.generateItems(emInj, howMany); } @Override public long countItems() { Singleton singleton = Singleton.getInstance(emInj); long numItems = singleton.howManyItemsExist(emInj); return numItems; } }
and the persistence.xml
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="Experiment8objPU" transaction-type="JTA"> <provider>com.objectdb.jpa.Provider</provider> <class>objdbTest.Singleton</class> <class>objdbTest.Item</class> <properties> <property name="javax.persistence.jdbc.url" value="C:/development/ObjectDb/objectdb-2.2.9_04/db/ObjectTestApp.odb"/> <property name="javax.persistence.jdbc.user" value="admin"/> <property name="javax.persistence.jdbc.password" value="admin"/> </properties> </persistence-unit> </persistence>
Is there something I am doing wrong, or is this the intended behaviour?
I attach the Eclipse projects . The only complexity is that everything is structured into separate projects ( an EAR, The EJBs, the EJB interfaces, the JPA Model, and the Web tier ). The objectdbee.jar is added as a module to the EAR, and the persistence.xml is located where it is used in the EJB project ( this was the only way I could get things to work on glassfish for other JPA providers )
I am using glassfish 3.1 and java 1.6b24 on Windows Server 2008 SP2 32bit. I have not added any objectdb jars in any other location apart from the EAR