[jboss-cvs] JBossAS SVN: r104828 - in projects/ejb-book/trunk/chxx-poker/src: main/java/org/jboss/ejb3/examples/chxx/transactions/entity and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sat May 15 16:46:25 EDT 2010


Author: ALRubinger
Date: 2010-05-15 16:46:25 -0400 (Sat, 15 May 2010)
New Revision: 104828

Added:
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGameLocalBusiness.java
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerGameBean.java
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerServiceConstants.java
Removed:
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGame.java
Modified:
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BankLocalBusiness.java
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/entity/User.java
   projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BankBean.java
   projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalPokerGameIntegrationTest.java
   projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerBean.java
   projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerLocalBusiness.java
   projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbQueryBean.java
   projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/TxWrappingBean.java
Log:
[EJBBOOK-23] Flesh out more Tx examples, now all passing

Modified: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BankLocalBusiness.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BankLocalBusiness.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BankLocalBusiness.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -87,4 +87,17 @@
     */
    void transfer(long accountIdFrom, long accountIdTo, BigDecimal amount) throws IllegalArgumentException,
          InsufficientBalanceException;
+
+   /**
+    * Transfers the specified amount from one account to another
+    * @param accountFrom The account from which we'll withdraw
+    * @param accountTo The account to which we'll deposit
+    * @param amount The amount to be transferred
+    * @throws IllegalArgumentException If the amount is not specified, the amount is 
+    *   less that 0, or either account ID is invalid
+    * @throws InsufficientBalanceException If the amount is greater than the current 
+    *   balance of the "from" account
+    */
+   void transfer(Account accountFrom, Account accountTo, BigDecimal amount) throws IllegalArgumentException,
+         InsufficientBalanceException;
 }

Deleted: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGame.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGame.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGame.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -1,44 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2010, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
-  *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.ejb3.examples.chxx.transactions.api;
-
-import java.math.BigDecimal;
-
-import org.jboss.ejb3.examples.chxx.transactions.entity.User;
-
-/**
- * Contract of a service capable of simulating
- * a single game of poker.  The actual gameplay is not modeled,
- * only the inputs and outputs of a single trial. 
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
-public interface PokerGame
-{
-   //-------------------------------------------------------------------------------------||
-   // Contracts --------------------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
-   boolean bet(User user, BigDecimal amount);
-
-}

Copied: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGameLocalBusiness.java (from rev 104691, projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGame.java)
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGameLocalBusiness.java	                        (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGameLocalBusiness.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -0,0 +1,67 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.examples.chxx.transactions.api;
+
+import java.math.BigDecimal;
+
+import org.jboss.ejb3.examples.chxx.transactions.entity.User;
+
+/**
+ * Contract of a service capable of simulating
+ * a single game of poker.  The actual gameplay is not modeled,
+ * only the inputs and outputs of a single trial. 
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface PokerGameLocalBusiness
+{
+   //-------------------------------------------------------------------------------------||
+   // Constants --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Name to which we'll bind in JNDI
+    */
+   String JNDI_NAME = "PokerGameLocal";
+
+   //-------------------------------------------------------------------------------------||
+   // Contracts --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Places a single bet, returning if the bet won or lost.  If the result 
+    * is a win, the amount specified will be transferred from the Poker Service
+    * account to {@link User#getAccount()}, else it will be deducted from the user account
+    * and placed into the Poker Service account.
+    *   
+    * @return Whether the bet won or lost
+    * @param userId The ID of the user placing the bet
+    * @param amount The amount of the bet
+    * @throws IllegalArgumentException If either the user of the amount is not specified or
+    *   the amount is a negative number.
+    * @throws InsufficientBalanceException If the user does not have enough in his/her account
+    *       to cover the bet
+    */
+   boolean bet(long userId, BigDecimal amount) throws IllegalArgumentException, InsufficientBalanceException;
+
+}

Modified: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/entity/User.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/entity/User.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/entity/User.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -45,11 +45,6 @@
    private String name;
 
    /**
-    * Email address of the user
-    */
-   private String email;
-
-   /**
     * The user's poker account
     */
    @OneToOne(cascade = CascadeType.PERSIST)
@@ -76,22 +71,6 @@
    }
 
    /**
-    * @return the email
-    */
-   public String getEmail()
-   {
-      return email;
-   }
-
-   /**
-    * @param email the email to set
-    */
-   public void setEmail(final String email)
-   {
-      this.email = email;
-   }
-
-   /**
     * @return the account
     */
    public Account getAccount()
@@ -118,7 +97,7 @@
    @Override
    public String toString()
    {
-      return "User [id=" + this.getId() + ", email=" + email + ", name=" + name + ", pokerAccount=" + account + "]";
+      return "User [id=" + this.getId() + ", name=" + name + ", pokerAccount=" + account + "]";
    }
 
 }

Modified: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BankBean.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BankBean.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BankBean.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -39,10 +39,10 @@
 
 /**
  * The bank with which users and the Poker provider 
- * may interact with underlying accounts.  For instance users
- * may wish to make cash deposits into their personal account, 
- * or the Poker provider may transfer money from the user's account
- * to the poker account when the user places a bet.
+ * may interact with underlying accounts.  For instance 
+ * winning or losing a bet will result in an account
+ * transfer between the user account and te poker
+ * system account.
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
@@ -106,8 +106,14 @@
       // Get the account
       final Account account = this.getAccount(accountId);
 
+      // We don't expose this account object to callers at all; its changes
+      // elsewhere in the (optional) Tx should not be synchronized with the DB
+      // in case of a write
+      em.detach(account);
+
       // Return the current balance
       return account.getBalance();
+
    }
 
    /**
@@ -124,6 +130,31 @@
       final Account accountFrom = this.getAccount(accountIdFrom);
       final Account accountTo = this.getAccount(accountIdTo);
 
+      // Delegate
+      this.transfer(accountFrom, accountTo, amount);
+
+   }
+
+   /**
+    * {@inheritDoc}
+    * @see org.jboss.ejb3.examples.chxx.transactions.api.BankLocalBusiness#transfer(org.jboss.ejb3.examples.chxx.transactions.entity.Account, org.jboss.ejb3.examples.chxx.transactions.entity.Account, java.math.BigDecimal)
+    */
+   @Override
+   @TransactionAttribute(TransactionAttributeType.REQUIRED)
+   // Default Tx Attribute; create a new Tx if not present, else use the existing
+   public void transfer(final Account accountFrom, final Account accountTo, final BigDecimal amount)
+         throws IllegalArgumentException, InsufficientBalanceException
+   {
+      // Precondition checks
+      if (accountFrom == null)
+      {
+         throw new IllegalArgumentException("accountFrom must be specified");
+      }
+      if (accountTo == null)
+      {
+         throw new IllegalArgumentException("accountTo must be specified");
+      }
+
       // Withdraw (which will throw InsufficientBalance if that's the case)
       accountFrom.withdraw(amount);
 

Added: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerGameBean.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerGameBean.java	                        (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerGameBean.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -0,0 +1,141 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.examples.chxx.transactions.impl;
+
+import java.math.BigDecimal;
+
+import javax.ejb.EJB;
+import javax.ejb.Local;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+import org.jboss.ejb3.annotation.LocalBinding;
+import org.jboss.ejb3.examples.chxx.transactions.api.BankLocalBusiness;
+import org.jboss.ejb3.examples.chxx.transactions.api.InsufficientBalanceException;
+import org.jboss.ejb3.examples.chxx.transactions.api.PokerGameLocalBusiness;
+import org.jboss.ejb3.examples.chxx.transactions.entity.Account;
+import org.jboss.ejb3.examples.chxx.transactions.entity.User;
+
+/**
+ * Implementation of a service capable of placing single 
+ * bets upon a poker game.  Though the gameplay itself is not
+ * modeled, its inputs and outputs are done transactionally.
+ * Each game is to take place in its own Tx, suspending
+ * an existing Tx if one is in play.  This is to ensure
+ * that the output of each game is committed (you win or lose)
+ * regardless of if an error occurrs later within the caller's Tx.
+ * Once your money's on the table, there's no going back! :)
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+ at Stateless
+ at Local(PokerGameLocalBusiness.class)
+ at LocalBinding(jndiBinding = PokerGameLocalBusiness.JNDI_NAME)
+ at TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+// Each game must be in a new Tx, suspending the existing enclosing Tx if necessary;
+// At the class-level, this annotation now applied to all methods
+public class PokerGameBean implements PokerGameLocalBusiness
+{
+
+   //-------------------------------------------------------------------------------------||
+   // Class Members ----------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Zero value used for comparison
+    */
+   private static final BigDecimal ZERO = new BigDecimal(0);
+
+   //-------------------------------------------------------------------------------------||
+   // Instance Members -------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   /**
+    * Hook to JPA
+    */
+   @PersistenceContext
+   private EntityManager em;
+
+   /**
+    * The bank service which will handle account transfers
+    * during win/lose
+    */
+   @EJB
+   private BankLocalBusiness bank;
+
+   //-------------------------------------------------------------------------------------||
+   // Required Implementations -----------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+   /**
+    * @see org.jboss.ejb3.examples.chxx.transactions.api.PokerGameLocalBusiness#bet(long, java.math.BigDecimal)
+    */
+   @Override
+   public boolean bet(final long userId, final BigDecimal amount) throws IllegalArgumentException,
+         InsufficientBalanceException
+   {
+      // Precondition checks
+      if (userId < 0)
+      {
+         throw new IllegalArgumentException("userId must be valid (>0)");
+      }
+      if (amount == null)
+      {
+         throw new IllegalArgumentException("amount must be specified");
+      }
+      if (amount.compareTo(ZERO) < 0)
+      {
+         throw new IllegalArgumentException("amount must be greater than 0");
+      }
+
+      // Check the balance of the user account
+      final Account userAccount = em.find(User.class, new Long(userId)).getAccount();
+      final BigDecimal currentBalanceUserAccount = userAccount.getBalance();
+      if (amount.compareTo(currentBalanceUserAccount) > 0)
+      {
+         throw new InsufficientBalanceException("Cannot place bet of " + amount + " when the user account has only "
+               + currentBalanceUserAccount);
+      }
+
+      // Fake the game logic and just determine if the user wins
+      final boolean win = Math.random() > 0.5;
+
+      // Get the Poker Service account (assume we always have enough to back our bet, these are just tests :))
+      final Account pokerServiceAccount = em.find(Account.class, PokerServiceConstants.ACCOUNT_POKERGAME_ID);
+
+      // Transfer the money based upon the outcome
+      if (win)
+      {
+         bank.transfer(pokerServiceAccount, userAccount, amount);
+      }
+      else
+      {
+         bank.transfer(userAccount, pokerServiceAccount, amount);
+      }
+
+      // Return the outcome
+      return win;
+   }
+}

Added: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerServiceConstants.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerServiceConstants.java	                        (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerServiceConstants.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+  *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.examples.chxx.transactions.impl;
+
+import java.math.BigDecimal;
+
+/**
+ * Constants used by the implementation of the 
+ * {@link PokerGameBean}
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface PokerServiceConstants
+{
+   //-------------------------------------------------------------------------------------||
+   // Constants --------------------------------------------------------------------------||
+   //-------------------------------------------------------------------------------------||
+
+   long USER_POKERGAME_ID = 1L;
+
+   String USER_POKERGAME_NAME = "The Poker Game System";
+
+   long ACCOUNT_POKERGAME_ID = 1L;
+
+   BigDecimal INITIAL_ACCOUNT_BALANCE_POKERGAME = new BigDecimal(10000);
+}

Modified: projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalPokerGameIntegrationTest.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalPokerGameIntegrationTest.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalPokerGameIntegrationTest.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -36,6 +36,7 @@
 import org.jboss.arquillian.api.RunModeType;
 import org.jboss.arquillian.junit.Arquillian;
 import org.jboss.ejb3.examples.chxx.transactions.api.BankLocalBusiness;
+import org.jboss.ejb3.examples.chxx.transactions.api.PokerGameLocalBusiness;
 import org.jboss.ejb3.examples.chxx.transactions.ejb.DbInitializerBean;
 import org.jboss.ejb3.examples.chxx.transactions.ejb.DbInitializerLocalBusiness;
 import org.jboss.ejb3.examples.chxx.transactions.ejb.DbQueryLocalBusiness;
@@ -45,6 +46,7 @@
 import org.jboss.ejb3.examples.chxx.transactions.entity.Account;
 import org.jboss.ejb3.examples.chxx.transactions.entity.User;
 import org.jboss.ejb3.examples.chxx.transactions.impl.BankBean;
+import org.jboss.ejb3.examples.chxx.transactions.impl.PokerServiceConstants;
 import org.jboss.shrinkwrap.api.ShrinkWrap;
 import org.jboss.shrinkwrap.api.spec.JavaArchive;
 import org.junit.After;
@@ -54,7 +56,9 @@
 import org.junit.runner.RunWith;
 
 /**
- * Testing dev only 
+ * Test cases to ensure that the Poker Game
+ * is respecting transactional boundaries at the appropriate
+ * granularity.
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
@@ -75,7 +79,9 @@
 
    /**
     * Naming Context
+    * @deprecated Remove when Arquillian will inject the EJB proxies
     */
+   @Deprecated
    private static Context jndiContext;
 
    /**
@@ -120,6 +126,12 @@
    // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
    private BankLocalBusiness bank;
 
+   /**
+    * Poker Game EJB Proxy
+    */
+   // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
+   private PokerGameLocalBusiness pokerGame;
+
    //-------------------------------------------------------------------------------------||
    // Lifecycle --------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
@@ -143,15 +155,11 @@
    public void injectEjbs() throws Exception
    {
       // Fake injection by doing manual lookups for the time being
-      Object obj = jndiContext.lookup(DbInitializerLocalBusiness.JNDI_NAME);
-      log.info(obj.getClass().getClassLoader().toString());
-      log.info(DbInitializerLocalBusiness.class.getClassLoader().toString());
-      log.info((obj instanceof DbInitializerLocalBusiness) + "");
-
       dbInitializer = (DbInitializerLocalBusiness) jndiContext.lookup(DbInitializerLocalBusiness.JNDI_NAME);
       txWrapper = (TxWrappingLocalBusiness) jndiContext.lookup(TxWrappingLocalBusiness.JNDI_NAME);
       db = (DbQueryLocalBusiness) jndiContext.lookup(DbQueryLocalBusiness.JNDI_NAME);
       bank = (BankLocalBusiness) jndiContext.lookup(BankLocalBusiness.JNDI_NAME);
+      pokerGame = (PokerGameLocalBusiness) jndiContext.lookup(PokerGameLocalBusiness.JNDI_NAME);
    }
 
    /**
@@ -166,13 +174,9 @@
    }
 
    //-------------------------------------------------------------------------------------||
-   // Required Implementations -----------------------------------------------------------||
+   // Tests ------------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
-   //-------------------------------------------------------------------------------------||
-   // Functional Methods -----------------------------------------------------------------||
-   //-------------------------------------------------------------------------------------||
-
    /**
     * Ensures that Transfers between accounts obey the ACID properties of Transactions
     */
@@ -181,19 +185,22 @@
    {
 
       // Init
-      final long alrubingerAccountId = DbInitializerBean.ACCOUNT_ALRUBINGERL_ID;
-      final long pokerAccountId = DbInitializerBean.ACCOUNT_POKERGAME_ID;
+      final long alrubingerAccountId = DbInitializerBean.ACCOUNT_ALRUBINGER_ID;
+      final long pokerAccountId = PokerServiceConstants.ACCOUNT_POKERGAME_ID;
 
-      // Ensure there's $500 in the ALR account, and $0 in the poker account
-      this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, new BigDecimal(500)),
-            new CheckBalanceOfAccountTask(pokerAccountId, new BigDecimal(0)));
+      // Ensure there's the expected amounts in both the ALR and Poker accounts
+      final BigDecimal expectedinitialALR = DbInitializerLocalBusiness.INITIAL_ACCOUNT_BALANCE_ALR;
+      final BigDecimal expectedinitialPoker = PokerServiceConstants.INITIAL_ACCOUNT_BALANCE_POKERGAME;
+      this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR),
+            new CheckBalanceOfAccountTask(pokerAccountId, expectedinitialPoker));
 
-      // Transfer $100
-      bank.transfer(alrubingerAccountId, pokerAccountId, new BigDecimal(100));
+      // Transfer $100 from ALR to Poker
+      final BigDecimal oneHundred = new BigDecimal(100);
+      bank.transfer(alrubingerAccountId, pokerAccountId, oneHundred);
 
-      // Ensure there's $400 in the ALR account, and 100 in the poker account
-      this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, new BigDecimal(400)),
-            new CheckBalanceOfAccountTask(pokerAccountId, new BigDecimal(100)));
+      // Ensure there's $100 less in the ALR account, and $100 more in the poker account
+      this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR.subtract(oneHundred)),
+            new CheckBalanceOfAccountTask(pokerAccountId, expectedinitialPoker.add(oneHundred)));
 
       // Now make a transfer, check it succeeded within the context of a Transaction, then 
       // intentionally throw an exception.  The Tx should complete as rolled back, 
@@ -204,16 +211,15 @@
          @Override
          public Void call() throws Exception
          {
-            bank.transfer(alrubingerAccountId, pokerAccountId, new BigDecimal(100));
+            bank.transfer(alrubingerAccountId, pokerAccountId, oneHundred);
             return null;
          }
       };
       try
       {
-         this.executeInTx(transferTask,
-               new CheckBalanceOfAccountTask(alrubingerAccountId, new BigDecimal(300)),
-               new CheckBalanceOfAccountTask(pokerAccountId, new BigDecimal(200)),
-               ForcedTestExceptionTask.INSTANCE);
+         this.executeInTx(transferTask, new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR.subtract(
+               oneHundred).subtract(oneHundred)), new CheckBalanceOfAccountTask(pokerAccountId, expectedinitialPoker
+               .add(oneHundred).add(oneHundred)), ForcedTestExceptionTask.INSTANCE);
       }
       // Expected
       catch (final ForcedTestException fte)
@@ -223,18 +229,150 @@
       Assert.assertTrue("Did not receive expected exception as signaled from the test; was not rolled back",
             gotExpectedException);
 
-      // Now that we've checked the tranfer succeeded from within the Tx, then we threw an
+      // Now that we've checked the transfer succeeded from within the Tx, then we threw an
       // exception before committed, ensure the Tx rolled back and the transfer was reverted from the 
       // perspective of everyone outside the Tx.
-      this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, new BigDecimal(400)),
-            new CheckBalanceOfAccountTask(pokerAccountId, new BigDecimal(100)));
+      this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR.subtract(oneHundred)),
+            new CheckBalanceOfAccountTask(pokerAccountId, expectedinitialPoker.add(oneHundred)));
    }
 
+   /**
+    * Ensures that when we make a sequence of bets enclosed in a single Tx,
+    * some exceptional condition at the end doesn't roll back the prior
+    * history.  Once we've won/lost a bet, that bet's done.  This tests that 
+    * each bet takes place in its own isolated Tx. 
+    */
+   @Test
+   public void sequenceOfBetsDoesntRollBackAll() throws Throwable
+   {
+      // Get the original balance for ALR; this is done outside a Tx
+      final BigDecimal originalBalance = bank.getBalance(DbInitializerLocalBusiness.ACCOUNT_ALRUBINGER_ID);
+      log.info("Starting balance before playing poker: " + originalBalance);
+
+      // Execute 11 bets enclosed in a new Tx, and ensure that the account transfers
+      // took place as expected.  Then throw an exception to rollback the parent Tx.
+      final BigDecimal betAmount = new BigDecimal(20);
+      final Place11BetsThenForceExceptionTask task = new Place11BetsThenForceExceptionTask(betAmount);
+      boolean gotForcedException = false;
+      try
+      {
+         this.executeInTx(task);
+      }
+      catch (final ForcedTestException tfe)
+      {
+         // Expected
+         gotForcedException = true;
+      }
+      Assert.assertTrue("Did not obtain the test exception as expected", gotForcedException);
+
+      // Now we've ensured that from inside the calling Tx we saw the account balances 
+      // were as expected.  But we rolled back that enclosing Tx, so ensure that the outcome
+      // of the games was not ignored
+      final BigDecimal afterBetsBalance = bank.getBalance(DbInitializerLocalBusiness.ACCOUNT_ALRUBINGER_ID);
+      final int gameOutcomeCount = task.gameOutcomeCount;
+      new AssertGameOutcome(originalBalance, afterBetsBalance, gameOutcomeCount, betAmount).call();
+   }
+
    //-------------------------------------------------------------------------------------||
    // Internal Helpers -------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||
 
    /**
+    * Task which asserts given an account original balance, 
+    * ending balance, game outcome count, and bet amount, that funds 
+    * remaining are as expected.
+    */
+   private static final class AssertGameOutcome implements Callable<Void>
+   {
+      private final BigDecimal originalBalance;
+
+      private final int gameOutcomeCount;
+
+      private final BigDecimal betAmount;
+
+      private final BigDecimal afterBetsBalance;
+
+      AssertGameOutcome(final BigDecimal originalBalance, final BigDecimal afterBetsBalance,
+            final int gameOutcomeCount, final BigDecimal betAmount)
+      {
+         this.originalBalance = originalBalance;
+         this.gameOutcomeCount = gameOutcomeCount;
+         this.betAmount = betAmount;
+         this.afterBetsBalance = afterBetsBalance;
+      }
+
+      @Override
+      public Void call() throws Exception
+      {
+         // Calculate expected
+         final BigDecimal expectedGains = betAmount.multiply(new BigDecimal(gameOutcomeCount));
+         final BigDecimal expectedBalance = originalBalance.add(expectedGains);
+
+         // Assert
+         Assert.assertTrue("Balance after all bets was not as expected " + expectedBalance + " but was "
+               + afterBetsBalance, expectedBalance.compareTo(afterBetsBalance) == 0);
+
+         // Return
+         return null;
+      }
+
+   }
+
+   /**
+    * A task that places 11 bets, then manually throws a {@link ForcedTestException}.
+    * This is so we may check that the balance transfers happened as 
+    * expected from within the context of the Tx in which this task will run, but
+    * also such that we can ensure that even if an exceptional case happens after bets have taken
+    * place, the completed bets do not roll back.  Once the money's on the table, you can't take
+    * it back. ;)
+    */
+   private final class Place11BetsThenForceExceptionTask implements Callable<Void>
+   {
+      /**
+       * Tracks how many games won/lost.  A negative 
+       * number indicates games lost; positive: won.
+       */
+      private int gameOutcomeCount = 0;
+
+      private final BigDecimal betAmount;
+
+      Place11BetsThenForceExceptionTask(final BigDecimal betAmount)
+      {
+         this.betAmount = betAmount;
+      }
+
+      @Override
+      public Void call() throws Exception
+      {
+
+         // Find the starting balance
+         final long alrubingerAccountId = DbInitializerLocalBusiness.ACCOUNT_ALRUBINGER_ID;
+         final BigDecimal startingBalance = bank.getBalance(alrubingerAccountId);
+
+         // Now run 11 bets
+         for (int i = 0; i < 11; i++)
+         {
+            // Track whether we win or lose
+            final boolean win = pokerGame.bet(DbInitializerLocalBusiness.ACCOUNT_ALRUBINGER_ID, betAmount);
+            gameOutcomeCount += win ? 1 : -1;
+         }
+         log.info("Won " + gameOutcomeCount + " games at " + betAmount + "/game");
+
+         // Get the user's balance after the bets
+         final BigDecimal afterBetsBalance = bank.getBalance(alrubingerAccountId);
+
+         // Ensure that money's been allocated properly
+         new AssertGameOutcome(startingBalance, afterBetsBalance, gameOutcomeCount, betAmount).call();
+
+         // Now force an exception to get a Tx rollback.  This should *not* affect the 
+         // money already transferred during the bets, as they should have taken place
+         // in nested Txs and already committed.
+         throw new ForcedTestException();
+      }
+
+   }
+
+   /**
     * A task that checks that the account balance of an {@link Account}
     * with specified ID equals a specified expected value.  Typically to be run 
     * inside of a Tx via {@link TransactionalPokerGameIntegrationTest#executeInTx(Callable...)}.
@@ -261,7 +399,7 @@
       public Void call() throws Exception
       {
          final Account account = db.find(Account.class, accountId);
-         Assert.assertEquals("Balance was not as expected", expectedBalance, account.getBalance());
+         Assert.assertTrue("Balance was not as expected", expectedBalance.compareTo(account.getBalance()) == 0);
          return null;
       }
 
@@ -302,6 +440,7 @@
       }
       catch (final TaskExecutionException tee)
       {
+         // Unwrap the real cause
          throw tee.getCause();
       }
    }

Modified: projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerBean.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerBean.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerBean.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -39,10 +39,13 @@
 import org.jboss.ejb3.annotation.LocalBinding;
 import org.jboss.ejb3.examples.chxx.transactions.entity.Account;
 import org.jboss.ejb3.examples.chxx.transactions.entity.User;
+import org.jboss.ejb3.examples.chxx.transactions.impl.PokerServiceConstants;
 
 /**
  * Singleton EJB to initialize and prepropulate
- * the database state before running tests.
+ * the database state before running tests.  Also permits
+ * refreshing the DB with default state via 
+ * {@link DbInitializerLocalBusiness#refreshWithDefaultData()}.
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $
@@ -122,22 +125,20 @@
       final User alrubinger = new User();
       alrubinger.setId(USER_ALRUBINGER_ID);
       alrubinger.setName(USER_ALRUBINGER_NAME);
-      alrubinger.setEmail(USER_ALRUBINGER_EMAIL);
       final Account alrubingerAccount = new Account();
       alrubingerAccount.deposit(INITIAL_ACCOUNT_BALANCE_ALR);
       alrubingerAccount.setOwner(alrubinger);
-      alrubingerAccount.setId(ACCOUNT_ALRUBINGERL_ID);
+      alrubingerAccount.setId(ACCOUNT_ALRUBINGER_ID);
       alrubinger.setAccount(alrubingerAccount);
 
       // Poker Game Service
       final User pokerGameService = new User();
-      pokerGameService.setId(USER_POKERGAME_ID);
-      pokerGameService.setName(USER_POKERGAME_NAME);
-      pokerGameService.setEmail(USER_POKERGAME_EMAIL);
+      pokerGameService.setId(PokerServiceConstants.USER_POKERGAME_ID);
+      pokerGameService.setName(PokerServiceConstants.USER_POKERGAME_NAME);
       final Account pokerGameAccount = new Account();
-      pokerGameAccount.deposit(INITIAL_ACCOUNT_BALANCE_POKERGAME);
+      pokerGameAccount.deposit(PokerServiceConstants.INITIAL_ACCOUNT_BALANCE_POKERGAME);
       pokerGameAccount.setOwner(pokerGameService);
-      pokerGameAccount.setId(ACCOUNT_POKERGAME_ID);
+      pokerGameAccount.setId(PokerServiceConstants.ACCOUNT_POKERGAME_ID);
       pokerGameService.setAccount(pokerGameAccount);
 
       // Persist

Modified: projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerLocalBusiness.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerLocalBusiness.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerLocalBusiness.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -45,26 +45,14 @@
     * Test Data
     */
 
-   public static final long USER_ALRUBINGER_ID = 1L;
+   long USER_ALRUBINGER_ID = 2L;
 
-   public static final String USER_ALRUBINGER_NAME = "Andrew Lee Rubinger";
+   String USER_ALRUBINGER_NAME = "Andrew Lee Rubinger";
 
-   public static final String USER_ALRUBINGER_EMAIL = "alr at fake.com";
+   long ACCOUNT_ALRUBINGER_ID = 2L;
 
-   public static final long ACCOUNT_ALRUBINGERL_ID = 1L;
+   BigDecimal INITIAL_ACCOUNT_BALANCE_ALR = new BigDecimal(500);
 
-   public static final long USER_POKERGAME_ID = 2L;
-
-   public static final String USER_POKERGAME_NAME = "The Poker Game System";
-
-   public static final String USER_POKERGAME_EMAIL = "pokergame at fake.com";
-
-   public static final long ACCOUNT_POKERGAME_ID = 2L;
-
-   public static final BigDecimal INITIAL_ACCOUNT_BALANCE_ALR = new BigDecimal(500);
-
-   public static final BigDecimal INITIAL_ACCOUNT_BALANCE_POKERGAME = new BigDecimal(0);
-
    //-------------------------------------------------------------------------------------||
    // Contracts --------------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

Modified: projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbQueryBean.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbQueryBean.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbQueryBean.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -31,8 +31,12 @@
 import org.jboss.ejb3.annotation.LocalBinding;
 
 /**
+ * Implementation of a test EJB which exposes generic database
+ * query operations directly via the {@link EntityManager}.
+ * Used in validating pre- and postconditions during testing.
+ * All methods will be executed in an existing Transaction, which
+ * is {@link TransactionAttributeType#MANDATORY}. 
  * 
- * 
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $

Modified: projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/TxWrappingBean.java
===================================================================
--- projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/TxWrappingBean.java	2010-05-15 19:35:12 UTC (rev 104827)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/TxWrappingBean.java	2010-05-15 20:46:25 UTC (rev 104828)
@@ -31,7 +31,8 @@
 import org.jboss.ejb3.annotation.LocalBinding;
 
 /**
- * EJB which wraps 
+ * EJB which wraps a specified series of {@link Callable}
+ * tasks within the context of a new Transaction
  *
  * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
  * @version $Revision: $




More information about the jboss-cvs-commits mailing list