Hi, I am using Apache Geronimo for my JPA applications. I am using oracle 10G database for my entities.
I have an EAR application with an EJB and a WEB module. EJB module has an SLSB that uses Container Managed Transactions and uses Container Managed Persistence Manager (EntityManager injected by container). The code is as follows. ************ package sample.jpa; import javax.ejb.EJBException; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; @Stateless @Remote(AccountInterface.class) public class AccountBean implements AccountInterface { @PersistenceContext(type=PersistenceContextType.TRANSACTION) private EntityManager manager; @TransactionAttribute(TransactionAttributeType.REQUIRED) public Account open(int accountNumber) { Account account = manager.find(Account.class, accountNumber); if(account == null){ account = new Account(); account.ownerName = "anonymous"; account.accountNumber = accountNumber; manager.persist(account); manager.flush(); return account; }else{ throw new EJBException("Account already exists..!!. Account Number = "+accountNumber); } } @TransactionAttribute(TransactionAttributeType.REQUIRED) public double getBalance(int accountNumber) { Account account = manager.find(Account.class, accountNumber); if(account==null) throw new EJBException("Account not found..!!. Account Number = "+accountNumber); return account.balance; } @TransactionAttribute(TransactionAttributeType.REQUIRED) public void deposit(int accountNumber, double amount) { Account account = manager.find(Account.class, accountNumber); if(account==null) throw new EJBException("Account not found..!!. Account Number = "+accountNumber); double new_balance = account.getBalance() + amount; account.setBalance(new_balance); manager.flush(); } @TransactionAttribute(TransactionAttributeType.REQUIRED) public double withdraw(int accountNumber, double amount) { Account account = manager.find(Account.class, accountNumber); if(account==null) throw new EJBException("Account not found..!!. Account Number = "+accountNumber); if (amount > account.getBalance()) { return 0; } else { double new_balance = account.getBalance() - amount; account.setBalance(new_balance); manager.flush(); return amount; } } } ************** The Account.java is an entity. The WEB module has a servlet that looks up EJB to perform amount transfer from one account to another. The code is as follows. ****************** package sample.jpa; import java.io.IOException; import java.io.PrintWriter; import javax.ejb.EJB; import javax.naming.Context; import javax.naming.InitialContext; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.transaction.UserTransaction; /** * Servlet implementation class for Servlet: Test * */ public class Test extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { static final long serialVersionUID = 1L; @PersistenceContext(unitName="AccountUnit") private EntityManager em; @EJB AccountInterface accountBean; /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#HttpServlet() */ public Test() { super(); } /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub PrintWriter out = response.getWriter(); int accNo1 = Integer.parseInt(request.getParameter("account1")); int accNo2 = Integer.parseInt(request.getParameter("account2")); double amount = Double.parseDouble(request.getParameter("amount")); try{ Context ctx = new InitialContext(); UserTransaction ut = (UserTransaction)ctx.lookup("java:comp/UserTransaction"); ut.begin(); Account account = em.find(Account.class, accNo1); if(account.getBalance() < amount){ throw new Exception("Account "+accNo1+" does not have enough balance "+amount); }else{ out.println("Account ="+accNo1+" : Current balance "+account.getBalance()); accountBean.withdraw(accNo1, amount); out.println("Account ="+accNo1+" : Withdrawn "+amount); double balance = account.getBalance(); out.println("Account ="+accNo1+" : After withdrawing the balance is "+balance); Account account2 = em.find(Account.class, accNo2); out.println("Account ="+accNo2+" : Current balance "+account2.getBalance()); accountBean.deposit(accNo2, amount); out.println("Account ="+accNo2+" : After depositing the balance is "+account2.getBalance()); } em.flush(); ut.commit(); }catch(Exception e){ throw new ServletException(e); } } /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub } } **************** The persistence.xml file is as follows. ****************** <?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="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="AccountUnit" transaction-type="JTA"> <description>ContainerManagedJPA</description> <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> <jta-data-source>PhaniOraclePool</jta-data-source> <class>sample.jpa.Account</class> </persistence-unit> </persistence> *************** The "PhaniOraclePool" is the datasource deployed on the Geronimo server over Oracle database. Problems : ********** 1. When the servlet is executed, the committed values are not flushing to Oracle database. After a transaction, when I query the database on SQLPLUS prompt, I still get the old values. I have used all possible methods like enititymanager.flush etc. It did not work. 2. Only when I shutdown the geronimo server, I am able to see the data being flushed to the database. 3. I have even redeployed the app to see if the EntityManager is flushing the data to the base. But no luck. The question is, how can we flush the data to the database in a controlled fashion from OpenJPA cache as sometimes we need the committed values to be available in the database. ?? Thanks in advance. Phani