Search in sources :

Example 1 with InvalidBidException

use of org.jpwh.model.concurrency.version.InvalidBidException in project microservices by pwillhan.

the class Versioning method forceIncrement.

// TODO This throws the wrong exception!
// @Test(expectedExceptions = OptimisticLockException.class)
@Test(expectedExceptions = org.hibernate.StaleObjectStateException.class)
public void forceIncrement() throws Throwable {
    final TestData testData = storeItemAndBids();
    Long ITEM_ID = testData.getFirstId();
    UserTransaction tx = TM.getUserTransaction();
    try {
        tx.begin();
        EntityManager em = JPA.createEntityManager();
        /* 
               The <code>find()</code> method accepts a <code>LockModeType</code>. The
               <code>OPTIMISTIC_FORCE_INCREMENT</code> mode tells Hibernate that the version
               of the retrieved <code>Item</code> should be incremented after loading,
               even if it's never modified in the unit of work.
             */
        Item item = em.find(Item.class, ITEM_ID, LockModeType.OPTIMISTIC_FORCE_INCREMENT);
        Bid highestBid = queryHighestBid(em, item);
        // Now a concurrent transaction will place a bid for this item, and
        // succeed because the first commit wins!
        Executors.newSingleThreadExecutor().submit(new Callable<Object>() {

            @Override
            public Object call() throws Exception {
                UserTransaction tx = TM.getUserTransaction();
                try {
                    tx.begin();
                    EntityManager em = JPA.createEntityManager();
                    Item item = em.find(Item.class, testData.getFirstId(), LockModeType.OPTIMISTIC_FORCE_INCREMENT);
                    Bid highestBid = queryHighestBid(em, item);
                    try {
                        Bid newBid = new Bid(new BigDecimal("44.44"), item, highestBid);
                        em.persist(newBid);
                    } catch (InvalidBidException ex) {
                    // Ignore
                    }
                    tx.commit();
                    em.close();
                } catch (Exception ex) {
                    // This shouldn't happen, this commit should win!
                    TM.rollback();
                    throw new RuntimeException("Concurrent operation failure: " + ex, ex);
                }
                return null;
            }
        }).get();
        try {
            /* 
                   The code persists a new <code>Bid</code> instance; this does not affect
                   any values of the <code>Item</code> instance. A new row will be inserted
                   into the <code>BID</code> table. Hibernate would not detect concurrently
                   made bids at all without a forced version increment of the
                   <code>Item</code>. We also use a checked exception to validate the
                   new bid amount; it must be greater than the currently highest bid.
                */
            Bid newBid = new Bid(new BigDecimal("44.44"), item, highestBid);
            em.persist(newBid);
        } catch (InvalidBidException ex) {
        // Bid too low, show a validation error screen...
        }
        /* 
               When flushing the persistence context, Hibernate will execute an
               <code>INSERT</code> for the new <code>Bid</code> and force an
               <code>UPDATE</code> of the <code>Item</code> with a version check.
               If someone modified the <code>Item</code> concurrently, or placed a
               <code>Bid</code> concurrently with this procedure, Hibernate throws
               an exception.
             */
        tx.commit();
        em.close();
    } catch (Exception ex) {
        throw unwrapCauseOfType(ex, org.hibernate.StaleObjectStateException.class);
    } finally {
        TM.rollback();
    }
}
Also used : UserTransaction(javax.transaction.UserTransaction) TestData(org.jpwh.shared.util.TestData) Callable(java.util.concurrent.Callable) BigDecimal(java.math.BigDecimal) OptimisticLockException(javax.persistence.OptimisticLockException) NoResultException(javax.persistence.NoResultException) InvalidBidException(org.jpwh.model.concurrency.version.InvalidBidException) InvalidBidException(org.jpwh.model.concurrency.version.InvalidBidException) Item(org.jpwh.model.concurrency.version.Item) EntityManager(javax.persistence.EntityManager) Bid(org.jpwh.model.concurrency.version.Bid) JPATest(org.jpwh.env.JPATest) Test(org.testng.annotations.Test)

Aggregations

BigDecimal (java.math.BigDecimal)1 Callable (java.util.concurrent.Callable)1 EntityManager (javax.persistence.EntityManager)1 NoResultException (javax.persistence.NoResultException)1 OptimisticLockException (javax.persistence.OptimisticLockException)1 UserTransaction (javax.transaction.UserTransaction)1 JPATest (org.jpwh.env.JPATest)1 Bid (org.jpwh.model.concurrency.version.Bid)1 InvalidBidException (org.jpwh.model.concurrency.version.InvalidBidException)1 Item (org.jpwh.model.concurrency.version.Item)1 TestData (org.jpwh.shared.util.TestData)1 Test (org.testng.annotations.Test)1