[jboss-cvs] JBossAS SVN: r105156 - in projects/ejb-book/trunk/chxx-poker/src: main/java/org/jboss/ejb3/examples/chxx/transactions/impl and 2 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon May 24 14:06:23 EDT 2010
Author: ALRubinger
Date: 2010-05-24 14:06:22 -0400 (Mon, 24 May 2010)
New Revision: 105156
Added:
projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BlackjackGameLocalBusiness.java
projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BlackjackGameBean.java
projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BlackjackServiceConstants.java
projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalBlackjackGameIntegrationTest.java
Removed:
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
projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalPokerGameIntegrationTest.java
Modified:
projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerBean.java
Log:
[EJBBOOK-23] Update from Poker to Blackjack
Copied: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BlackjackGameLocalBusiness.java (from rev 105147, 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/api/BlackjackGameLocalBusiness.java (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/BlackjackGameLocalBusiness.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -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 blackjack. 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 BlackjackGameLocalBusiness
+{
+ //-------------------------------------------------------------------------------------||
+ // 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 Blackjack Service
+ * account to {@link User#getAccount()}, else it will be deducted from the user account
+ * and placed into the Blackjack 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;
+
+}
Deleted: 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/api/PokerGameLocalBusiness.java 2010-05-24 17:50:55 UTC (rev 105155)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/api/PokerGameLocalBusiness.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -1,67 +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 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;
-
-}
Copied: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BlackjackGameBean.java (from rev 105147, 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/BlackjackGameBean.java (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BlackjackGameBean.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -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.BlackjackGameLocalBusiness;
+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 blackjack 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(BlackjackGameLocalBusiness.class)
+ at LocalBinding(jndiBinding = BlackjackGameLocalBusiness.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 BlackjackGameBean implements BlackjackGameLocalBusiness
+{
+
+ //-------------------------------------------------------------------------------------||
+ // 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.BlackjackGameLocalBusiness#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 blackjackServiceAccount = em.find(Account.class, BlackjackServiceConstants.ACCOUNT_BLACKJACKGAME_ID);
+
+ // Transfer the money based upon the outcome
+ if (win)
+ {
+ bank.transfer(blackjackServiceAccount, userAccount, amount);
+ }
+ else
+ {
+ bank.transfer(userAccount, blackjackServiceAccount, amount);
+ }
+
+ // Return the outcome
+ return win;
+ }
+}
Copied: projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BlackjackServiceConstants.java (from rev 105147, 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/BlackjackServiceConstants.java (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/BlackjackServiceConstants.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -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 BlackjackGameBean}
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface BlackjackServiceConstants
+{
+ //-------------------------------------------------------------------------------------||
+ // Constants --------------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ long USER_BLACKJACKGAME_ID = 1L;
+
+ String USER_BLACKJACKGAME_NAME = "The Blackjack Game System";
+
+ long ACCOUNT_BLACKJACKGAME_ID = 1L;
+
+ BigDecimal INITIAL_ACCOUNT_BALANCE_BLACKJACKGAME = new BigDecimal(10000);
+}
Deleted: 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 2010-05-24 17:50:55 UTC (rev 105155)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerGameBean.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -1,141 +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.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;
- }
-}
Deleted: 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 2010-05-24 17:50:55 UTC (rev 105155)
+++ projects/ejb-book/trunk/chxx-poker/src/main/java/org/jboss/ejb3/examples/chxx/transactions/impl/PokerServiceConstants.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -1,46 +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.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);
-}
Copied: projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalBlackjackGameIntegrationTest.java (from rev 105149, 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/TransactionalBlackjackGameIntegrationTest.java (rev 0)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalBlackjackGameIntegrationTest.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -0,0 +1,455 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+import java.util.concurrent.Callable;
+import java.util.logging.Logger;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.persistence.EntityManager;
+
+import junit.framework.Assert;
+
+import org.jboss.arquillian.api.Deployment;
+import org.jboss.arquillian.api.Run;
+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.BlackjackGameLocalBusiness;
+import org.jboss.ejb3.examples.chxx.transactions.ejb.DbInitializerBean;
+import org.jboss.ejb3.examples.chxx.transactions.ejb.ExampleUserData;
+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.BlackjackServiceConstants;
+import org.jboss.ejb3.examples.testsupport.dbinit.DbInitializerLocalBusiness;
+import org.jboss.ejb3.examples.testsupport.dbquery.EntityManagerExposingBean;
+import org.jboss.ejb3.examples.testsupport.dbquery.EntityManagerExposingLocalBusiness;
+import org.jboss.ejb3.examples.testsupport.entity.IdentityBase;
+import org.jboss.ejb3.examples.testsupport.txwrap.ForcedTestException;
+import org.jboss.ejb3.examples.testsupport.txwrap.TaskExecutionException;
+import org.jboss.ejb3.examples.testsupport.txwrap.TxWrappingBean;
+import org.jboss.ejb3.examples.testsupport.txwrap.TxWrappingLocalBusiness;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test cases to ensure that the Blackjack Game
+ * is respecting transactional boundaries at the appropriate
+ * granularity.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+ at RunWith(Arquillian.class)
+ at Run(RunModeType.AS_CLIENT)
+public class TransactionalBlackjackGameIntegrationTest
+{
+
+ //-------------------------------------------------------------------------------------||
+ // Class Members ----------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Logger
+ */
+ private static final Logger log = Logger.getLogger(TransactionalBlackjackGameIntegrationTest.class.getName());
+
+ /**
+ * Naming Context
+ * @deprecated Remove when Arquillian will inject the EJB proxies
+ */
+ @Deprecated
+ private static Context jndiContext;
+
+ /**
+ * The Deployment into the EJB Container
+ */
+ @Deployment
+ public static JavaArchive getDeployment()
+ {
+ final JavaArchive archive = ShrinkWrap.create("test.jar", JavaArchive.class).addPackages(true,
+ BankLocalBusiness.class.getPackage(), User.class.getPackage()).addManifestResource("persistence.xml")
+ .addPackages(false, DbInitializerBean.class.getPackage(), TxWrappingLocalBusiness.class.getPackage(),
+ BankBean.class.getPackage(), DbInitializerLocalBusiness.class.getPackage(),
+ EntityManagerExposingBean.class.getPackage(), IdentityBase.class.getPackage());
+ log.info(archive.toString(true));
+ return archive;
+ }
+
+ //-------------------------------------------------------------------------------------||
+ // Instance Members -------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Test-only DB initializer to sanitize and prepopulate the DB with each test run
+ */
+ // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
+ private DbInitializerLocalBusiness dbInitializer;
+
+ /**
+ * EJB which wraps supplied {@link Callable} instances inside of a new Tx
+ */
+ // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
+ private TxWrappingLocalBusiness txWrapper;
+
+ /**
+ * EJB which provides direct access to an {@link EntityManager}'s method for use in testing.
+ * Must be called inside an existing Tx so that returned entities are not detached.
+ */
+ // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
+ private EntityManagerExposingLocalBusiness emHook;
+
+ /**
+ * Bank EJB Proxy
+ */
+ // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
+ private BankLocalBusiness bank;
+
+ /**
+ * Blackjack Game EJB Proxy
+ */
+ // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
+ private BlackjackGameLocalBusiness blackjackGame;
+
+ //-------------------------------------------------------------------------------------||
+ // Lifecycle --------------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Performs suite-wide initialization
+ */
+ @BeforeClass
+ public static void init() throws Exception
+ {
+ // After the server is up, we don't need to pass any explicit properties
+ jndiContext = new InitialContext();
+ }
+
+ /**
+ * Manually looks up EJBs in JNDI and assigns them
+ * @deprecated Remove when Arquillian will handle the injection for us
+ */
+ @Deprecated
+ @Before
+ public void injectEjbs() throws Exception
+ {
+ // Fake injection by doing manual lookups for the time being
+ dbInitializer = (DbInitializerLocalBusiness) jndiContext.lookup(DbInitializerBean.class.getSimpleName()
+ + "/local");
+ txWrapper = (TxWrappingLocalBusiness) jndiContext.lookup(TxWrappingBean.class.getSimpleName() + "/local");
+ emHook = (EntityManagerExposingLocalBusiness) jndiContext.lookup(EntityManagerExposingBean.class.getSimpleName()
+ + "/local");
+ bank = (BankLocalBusiness) jndiContext.lookup(BankLocalBusiness.JNDI_NAME);
+ blackjackGame = (BlackjackGameLocalBusiness) jndiContext.lookup(BlackjackGameLocalBusiness.JNDI_NAME);
+ }
+
+ /**
+ * Clears and repopulates the database with test data
+ * after each run
+ * @throws Exception
+ */
+ @After
+ public void refreshWithDefaultData() throws Exception
+ {
+ dbInitializer.refreshWithDefaultData();
+ }
+
+ //-------------------------------------------------------------------------------------||
+ // Tests ------------------------------------------------------------------------------||
+ //-------------------------------------------------------------------------------------||
+
+ /**
+ * Ensures that Transfers between accounts obey the ACID properties of Transactions
+ */
+ @Test
+ public void transferRetainsIntegrity() throws Throwable
+ {
+
+ // Init
+ final long alrubingerAccountId = ExampleUserData.ACCOUNT_ALRUBINGER_ID;
+ final long blackjackAccountId = BlackjackServiceConstants.ACCOUNT_BLACKJACKGAME_ID;
+
+ // Ensure there's the expected amounts in both the ALR and Blackjack accounts
+ final BigDecimal expectedinitialALR = ExampleUserData.INITIAL_ACCOUNT_BALANCE_ALR;
+ final BigDecimal expectedinitialBlackjack = BlackjackServiceConstants.INITIAL_ACCOUNT_BALANCE_BLACKJACKGAME;
+ this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR),
+ new CheckBalanceOfAccountTask(blackjackAccountId, expectedinitialBlackjack));
+
+ // Transfer $100 from ALR to Blackjack
+ final BigDecimal oneHundred = new BigDecimal(100);
+ bank.transfer(alrubingerAccountId, blackjackAccountId, oneHundred);
+
+ // Ensure there's $100 less in the ALR account, and $100 more in the blackjack account
+ this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR.subtract(oneHundred)),
+ new CheckBalanceOfAccountTask(blackjackAccountId, expectedinitialBlackjack.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,
+ // and the state should be consistent (as if the xfer request never took place).
+ boolean gotExpectedException = false;
+ final Callable<Void> transferTask = new Callable<Void>()
+ {
+ @Override
+ public Void call() throws Exception
+ {
+ bank.transfer(alrubingerAccountId, blackjackAccountId, oneHundred);
+ return null;
+ }
+ };
+ try
+ {
+ this.executeInTx(transferTask, new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR.subtract(
+ oneHundred).subtract(oneHundred)), new CheckBalanceOfAccountTask(blackjackAccountId, expectedinitialBlackjack
+ .add(oneHundred).add(oneHundred)), ForcedTestExceptionTask.INSTANCE);
+ }
+ // Expected
+ catch (final ForcedTestException fte)
+ {
+ gotExpectedException = true;
+ }
+ Assert.assertTrue("Did not receive expected exception as signaled from the test; was not rolled back",
+ gotExpectedException);
+
+ // 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, expectedinitialALR.subtract(oneHundred)),
+ new CheckBalanceOfAccountTask(blackjackAccountId, expectedinitialBlackjack.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(ExampleUserData.ACCOUNT_ALRUBINGER_ID);
+ log.info("Starting balance before playing blackjack: " + 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(ExampleUserData.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 = ExampleUserData.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 = blackjackGame.bet(ExampleUserData.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 TransactionalBlackjackGameIntegrationTest#executeInTx(Callable...)}.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+ private final class CheckBalanceOfAccountTask implements Callable<Void>
+ {
+
+ private long accountId;
+
+ private BigDecimal expectedBalance;
+
+ CheckBalanceOfAccountTask(final long accountId, final BigDecimal expectedBalance)
+ {
+ assert accountId > 0;
+ assert expectedBalance != null;
+ this.accountId = accountId;
+ this.expectedBalance = expectedBalance;
+ }
+
+ @Override
+ public Void call() throws Exception
+ {
+ final Account account = emHook.getEntityManager().find(Account.class, accountId);
+ Assert.assertTrue("Balance was not as expected", expectedBalance.compareTo(account.getBalance()) == 0);
+ return null;
+ }
+
+ }
+
+ /**
+ * Task which throws a {@link TaskExecutionException} for use in testing
+ * for instance to force a Tx Rollback
+ *
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+ private enum ForcedTestExceptionTask implements Callable<Void> {
+ INSTANCE;
+
+ @Override
+ public Void call() throws Exception
+ {
+ throw new ForcedTestException();
+ }
+
+ }
+
+ /**
+ * Executes the specified tasks inside of a Tx, courtesy of the
+ * {@link TxWrappingLocalBusiness} view.
+ */
+ private void executeInTx(final Callable<?>... tasks) throws Throwable
+ {
+ // Precondition checks
+ assert tasks != null : "Tasks must be specified";
+
+ // Execute in a single new Tx, courtesy of the TxWrapping EJB
+ try
+ {
+ txWrapper.wrapInTx(tasks);
+ }
+ catch (final TaskExecutionException tee)
+ {
+ // Unwrap the real cause
+ throw tee.getCause();
+ }
+ }
+}
Deleted: 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-24 17:50:55 UTC (rev 105155)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/TransactionalPokerGameIntegrationTest.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -1,455 +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;
-
-import java.math.BigDecimal;
-import java.util.concurrent.Callable;
-import java.util.logging.Logger;
-
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.persistence.EntityManager;
-
-import junit.framework.Assert;
-
-import org.jboss.arquillian.api.Deployment;
-import org.jboss.arquillian.api.Run;
-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.ExampleUserData;
-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.ejb3.examples.testsupport.dbinit.DbInitializerLocalBusiness;
-import org.jboss.ejb3.examples.testsupport.dbquery.EntityManagerExposingBean;
-import org.jboss.ejb3.examples.testsupport.dbquery.EntityManagerExposingLocalBusiness;
-import org.jboss.ejb3.examples.testsupport.entity.IdentityBase;
-import org.jboss.ejb3.examples.testsupport.txwrap.ForcedTestException;
-import org.jboss.ejb3.examples.testsupport.txwrap.TaskExecutionException;
-import org.jboss.ejb3.examples.testsupport.txwrap.TxWrappingBean;
-import org.jboss.ejb3.examples.testsupport.txwrap.TxWrappingLocalBusiness;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.spec.JavaArchive;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * 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: $
- */
- at RunWith(Arquillian.class)
- at Run(RunModeType.AS_CLIENT)
-public class TransactionalPokerGameIntegrationTest
-{
-
- //-------------------------------------------------------------------------------------||
- // Class Members ----------------------------------------------------------------------||
- //-------------------------------------------------------------------------------------||
-
- /**
- * Logger
- */
- private static final Logger log = Logger.getLogger(TransactionalPokerGameIntegrationTest.class.getName());
-
- /**
- * Naming Context
- * @deprecated Remove when Arquillian will inject the EJB proxies
- */
- @Deprecated
- private static Context jndiContext;
-
- /**
- * The Deployment into the EJB Container
- */
- @Deployment
- public static JavaArchive getDeployment()
- {
- final JavaArchive archive = ShrinkWrap.create("test.jar", JavaArchive.class).addPackages(true,
- BankLocalBusiness.class.getPackage(), User.class.getPackage()).addManifestResource("persistence.xml")
- .addPackages(false, DbInitializerBean.class.getPackage(), TxWrappingLocalBusiness.class.getPackage(),
- BankBean.class.getPackage(), DbInitializerLocalBusiness.class.getPackage(),
- EntityManagerExposingBean.class.getPackage(), IdentityBase.class.getPackage());
- log.info(archive.toString(true));
- return archive;
- }
-
- //-------------------------------------------------------------------------------------||
- // Instance Members -------------------------------------------------------------------||
- //-------------------------------------------------------------------------------------||
-
- /**
- * Test-only DB initializer to sanitize and prepopulate the DB with each test run
- */
- // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
- private DbInitializerLocalBusiness dbInitializer;
-
- /**
- * EJB which wraps supplied {@link Callable} instances inside of a new Tx
- */
- // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
- private TxWrappingLocalBusiness txWrapper;
-
- /**
- * EJB which provides direct access to an {@link EntityManager}'s method for use in testing.
- * Must be called inside an existing Tx so that returned entities are not detached.
- */
- // TODO: Support Injection of @EJB here when Arquillian for Embedded JBossAS will support it
- private EntityManagerExposingLocalBusiness emHook;
-
- /**
- * Bank EJB Proxy
- */
- // 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 --------------------------------------------------------------------------||
- //-------------------------------------------------------------------------------------||
-
- /**
- * Performs suite-wide initialization
- */
- @BeforeClass
- public static void init() throws Exception
- {
- // After the server is up, we don't need to pass any explicit properties
- jndiContext = new InitialContext();
- }
-
- /**
- * Manually looks up EJBs in JNDI and assigns them
- * @deprecated Remove when Arquillian will handle the injection for us
- */
- @Deprecated
- @Before
- public void injectEjbs() throws Exception
- {
- // Fake injection by doing manual lookups for the time being
- dbInitializer = (DbInitializerLocalBusiness) jndiContext.lookup(DbInitializerBean.class.getSimpleName()
- + "/local");
- txWrapper = (TxWrappingLocalBusiness) jndiContext.lookup(TxWrappingBean.class.getSimpleName() + "/local");
- emHook = (EntityManagerExposingLocalBusiness) jndiContext.lookup(EntityManagerExposingBean.class.getSimpleName()
- + "/local");
- bank = (BankLocalBusiness) jndiContext.lookup(BankLocalBusiness.JNDI_NAME);
- pokerGame = (PokerGameLocalBusiness) jndiContext.lookup(PokerGameLocalBusiness.JNDI_NAME);
- }
-
- /**
- * Clears and repopulates the database with test data
- * after each run
- * @throws Exception
- */
- @After
- public void refreshWithDefaultData() throws Exception
- {
- dbInitializer.refreshWithDefaultData();
- }
-
- //-------------------------------------------------------------------------------------||
- // Tests ------------------------------------------------------------------------------||
- //-------------------------------------------------------------------------------------||
-
- /**
- * Ensures that Transfers between accounts obey the ACID properties of Transactions
- */
- @Test
- public void transferRetainsIntegrity() throws Throwable
- {
-
- // Init
- final long alrubingerAccountId = ExampleUserData.ACCOUNT_ALRUBINGER_ID;
- final long pokerAccountId = PokerServiceConstants.ACCOUNT_POKERGAME_ID;
-
- // Ensure there's the expected amounts in both the ALR and Poker accounts
- final BigDecimal expectedinitialALR = ExampleUserData.INITIAL_ACCOUNT_BALANCE_ALR;
- final BigDecimal expectedinitialPoker = PokerServiceConstants.INITIAL_ACCOUNT_BALANCE_POKERGAME;
- this.executeInTx(new CheckBalanceOfAccountTask(alrubingerAccountId, expectedinitialALR),
- new CheckBalanceOfAccountTask(pokerAccountId, expectedinitialPoker));
-
- // Transfer $100 from ALR to Poker
- final BigDecimal oneHundred = new BigDecimal(100);
- bank.transfer(alrubingerAccountId, pokerAccountId, oneHundred);
-
- // 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,
- // and the state should be consistent (as if the xfer request never took place).
- boolean gotExpectedException = false;
- final Callable<Void> transferTask = new Callable<Void>()
- {
- @Override
- public Void call() throws Exception
- {
- bank.transfer(alrubingerAccountId, pokerAccountId, oneHundred);
- return null;
- }
- };
- try
- {
- 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)
- {
- gotExpectedException = true;
- }
- Assert.assertTrue("Did not receive expected exception as signaled from the test; was not rolled back",
- gotExpectedException);
-
- // 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, 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(ExampleUserData.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(ExampleUserData.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 = ExampleUserData.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(ExampleUserData.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...)}.
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
- private final class CheckBalanceOfAccountTask implements Callable<Void>
- {
-
- private long accountId;
-
- private BigDecimal expectedBalance;
-
- CheckBalanceOfAccountTask(final long accountId, final BigDecimal expectedBalance)
- {
- assert accountId > 0;
- assert expectedBalance != null;
- this.accountId = accountId;
- this.expectedBalance = expectedBalance;
- }
-
- @Override
- public Void call() throws Exception
- {
- final Account account = emHook.getEntityManager().find(Account.class, accountId);
- Assert.assertTrue("Balance was not as expected", expectedBalance.compareTo(account.getBalance()) == 0);
- return null;
- }
-
- }
-
- /**
- * Task which throws a {@link TaskExecutionException} for use in testing
- * for instance to force a Tx Rollback
- *
- *
- * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
- * @version $Revision: $
- */
- private enum ForcedTestExceptionTask implements Callable<Void> {
- INSTANCE;
-
- @Override
- public Void call() throws Exception
- {
- throw new ForcedTestException();
- }
-
- }
-
- /**
- * Executes the specified tasks inside of a Tx, courtesy of the
- * {@link TxWrappingLocalBusiness} view.
- */
- private void executeInTx(final Callable<?>... tasks) throws Throwable
- {
- // Precondition checks
- assert tasks != null : "Tasks must be specified";
-
- // Execute in a single new Tx, courtesy of the TxWrapping EJB
- try
- {
- txWrapper.wrapInTx(tasks);
- }
- 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-24 17:50:55 UTC (rev 105155)
+++ projects/ejb-book/trunk/chxx-poker/src/test/java/org/jboss/ejb3/examples/chxx/transactions/ejb/DbInitializerBean.java 2010-05-24 18:06:22 UTC (rev 105156)
@@ -31,7 +31,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.PokerServiceConstants;
+import org.jboss.ejb3.examples.chxx.transactions.impl.BlackjackServiceConstants;
import org.jboss.ejb3.examples.testsupport.dbinit.DbInitializerBeanBase;
import org.jboss.ejb3.examples.testsupport.dbinit.DbInitializerLocalBusiness;
@@ -106,20 +106,20 @@
alrubinger.setAccount(alrubingerAccount);
// Poker Game Service
- final User pokerGameService = new User();
- pokerGameService.setId(PokerServiceConstants.USER_POKERGAME_ID);
- pokerGameService.setName(PokerServiceConstants.USER_POKERGAME_NAME);
+ final User blackjackGameService = new User();
+ blackjackGameService.setId(BlackjackServiceConstants.USER_BLACKJACKGAME_ID);
+ blackjackGameService.setName(BlackjackServiceConstants.USER_BLACKJACKGAME_NAME);
final Account pokerGameAccount = new Account();
- pokerGameAccount.deposit(PokerServiceConstants.INITIAL_ACCOUNT_BALANCE_POKERGAME);
- pokerGameAccount.setOwner(pokerGameService);
- pokerGameAccount.setId(PokerServiceConstants.ACCOUNT_POKERGAME_ID);
- pokerGameService.setAccount(pokerGameAccount);
+ pokerGameAccount.deposit(BlackjackServiceConstants.INITIAL_ACCOUNT_BALANCE_BLACKJACKGAME);
+ pokerGameAccount.setOwner(blackjackGameService);
+ pokerGameAccount.setId(BlackjackServiceConstants.ACCOUNT_BLACKJACKGAME_ID);
+ blackjackGameService.setAccount(pokerGameAccount);
// Persist
em.persist(alrubinger);
log.info("Created: " + alrubinger);
- em.persist(pokerGameService);
- log.info("Created: " + pokerGameService);
+ em.persist(blackjackGameService);
+ log.info("Created: " + blackjackGameService);
}
}
More information about the jboss-cvs-commits
mailing list