Search in sources :

Example 1 with LockTimeoutException

use of jakarta.persistence.LockTimeoutException in project hibernate-orm by hibernate.

the class LockTest method testContendedPessimisticWriteLockTimeout.

@Test
@RequiresDialect(OracleDialect.class)
@RequiresDialectFeature(DialectChecks.SupportsLockTimeouts.class)
public void testContendedPessimisticWriteLockTimeout() throws Exception {
    final CountDownLatch latch = new CountDownLatch(1);
    final Lock lock = new Lock();
    FutureTask<Boolean> bgTask = new FutureTask<>(() -> {
        try {
            // true (success) if LockTimeoutException occurred
            AtomicBoolean timedOut = new AtomicBoolean();
            doInJPA(this::entityManagerFactory, _entityManager -> {
                log.info("testContendedPessimisticWriteLockTimeout: (BG) about to read write-locked entity");
                // we should block on the following read
                Lock lock2 = _entityManager.getReference(Lock.class, lock.getId());
                // force entity to be read
                lock2.getName();
                log.info("testContendedPessimisticWriteLockTimeout: (BG) read write-locked entity");
                Map<String, Object> props = new HashMap<String, Object>();
                // timeout is in milliseconds
                props.put(AvailableSettings.JPA_LOCK_TIMEOUT, 1000);
                try {
                    _entityManager.lock(lock2, LockModeType.PESSIMISTIC_WRITE, props);
                } catch (LockTimeoutException e) {
                    // success
                    log.info("testContendedPessimisticWriteLockTimeout: (BG) got expected timeout exception");
                    timedOut.set(true);
                } catch (Throwable e) {
                    log.info("Expected LockTimeoutException but got unexpected exception", e);
                }
            });
            return timedOut.get();
        } finally {
            // signal that we finished
            latch.countDown();
        }
    });
    Thread t = new Thread(bgTask);
    t.setDaemon(true);
    t.setName("Lock timeout Test (bg)");
    try {
        lock.setName("testContendedPessimisticWriteLockTimeout");
        doInJPA(this::entityManagerFactory, em -> {
            em.persist(lock);
        });
        doInJPA(this::entityManagerFactory, em -> {
            Lock _lock = em.getReference(Lock.class, lock.getId());
            em.lock(_lock, LockModeType.PESSIMISTIC_WRITE);
            final Integer id = _lock.getId();
            // force entity to be read
            _lock.getName();
            log.info("testContendedPessimisticWriteLockTimeout: got write lock");
            try {
                t.start();
                // should return quickly on success
                boolean latchSet = latch.await(20, TimeUnit.SECONDS);
                assertTrue("background test thread finished (lock timeout is broken)", latchSet);
                assertTrue("background test thread timed out on lock attempt", bgTask.get());
            } catch (InterruptedException e) {
                Thread.interrupted();
            } catch (ExecutionException e) {
                throw new AssertionError(e);
            }
        });
    } finally {
        awaitThenDelete("testContendedPessimisticWriteLockTimeout", t, lock.getId());
    }
}
Also used : HashMap(java.util.HashMap) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) FutureTask(java.util.concurrent.FutureTask) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ExecutionException(java.util.concurrent.ExecutionException) LockTimeoutException(jakarta.persistence.LockTimeoutException) Test(org.junit.Test) RequiresDialectFeature(org.hibernate.testing.RequiresDialectFeature) RequiresDialect(org.hibernate.testing.RequiresDialect)

Example 2 with LockTimeoutException

use of jakarta.persistence.LockTimeoutException in project hibernate-orm by hibernate.

the class LockTest method testContendedPessimisticWriteLockNoWait.

@Test
@RequiresDialect({ OracleDialect.class, PostgreSQLDialect.class })
@RequiresDialectFeature(DialectChecks.SupportsLockTimeouts.class)
public void testContendedPessimisticWriteLockNoWait() throws Exception {
    final CountDownLatch latch = new CountDownLatch(1);
    final Lock lock = new Lock();
    FutureTask<Boolean> bgTask = new FutureTask<>(() -> {
        try {
            // true (success) if LockTimeoutException occurred
            AtomicBoolean timedOut = new AtomicBoolean();
            doInJPA(this::entityManagerFactory, _entityManager -> {
                log.info("testContendedPessimisticWriteLockNoWait: (BG) about to read write-locked entity");
                // we should block on the following read
                Lock lock2 = _entityManager.getReference(Lock.class, lock.getId());
                // force entity to be read
                lock2.getName();
                log.info("testContendedPessimisticWriteLockNoWait: (BG) read write-locked entity");
                Map<String, Object> props = new HashMap<String, Object>();
                // timeout of zero means no wait (for lock)
                props.put(AvailableSettings.JPA_LOCK_TIMEOUT, 0);
                try {
                    _entityManager.lock(lock2, LockModeType.PESSIMISTIC_WRITE, props);
                } catch (LockTimeoutException e) {
                    // success
                    log.info("testContendedPessimisticWriteLockNoWait: (BG) got expected timeout exception");
                    timedOut.set(true);
                } catch (Throwable e) {
                    log.info("Expected LockTimeoutException but got unexpected exception", e);
                }
            });
            return timedOut.get();
        } finally {
            // signal that we finished
            latch.countDown();
        }
    });
    Thread t = new Thread(bgTask);
    t.setDaemon(true);
    t.setName("Lock timeout Test (bg)");
    try {
        lock.setName("testContendedPessimisticWriteLockNoWait");
        doInJPA(this::entityManagerFactory, em -> {
            em.persist(lock);
        });
        doInJPA(this::entityManagerFactory, em -> {
            Lock _lock = em.getReference(Lock.class, lock.getId());
            em.lock(_lock, LockModeType.PESSIMISTIC_WRITE);
            final Integer id = _lock.getId();
            // force entity to be read
            _lock.getName();
            log.info("testContendedPessimisticWriteLockNoWait: got write lock");
            try {
                t.start();
                // should return quickly on success
                boolean latchSet = latch.await(20, TimeUnit.SECONDS);
                assertTrue("background test thread finished (lock timeout is broken)", latchSet);
                assertTrue("background test thread timed out on lock attempt", bgTask.get());
            } catch (InterruptedException e) {
                Thread.interrupted();
            } catch (ExecutionException e) {
                throw new AssertionError(e);
            }
        });
    } finally {
        awaitThenDelete("testContendedPessimisticWriteLockNoWait", t, lock.getId());
    }
}
Also used : HashMap(java.util.HashMap) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) FutureTask(java.util.concurrent.FutureTask) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ExecutionException(java.util.concurrent.ExecutionException) LockTimeoutException(jakarta.persistence.LockTimeoutException) Test(org.junit.Test) RequiresDialectFeature(org.hibernate.testing.RequiresDialectFeature) RequiresDialect(org.hibernate.testing.RequiresDialect)

Example 3 with LockTimeoutException

use of jakarta.persistence.LockTimeoutException in project hibernate-orm by hibernate.

the class LockExceptionTests method testLockTimeoutFind.

@Test
@TestForIssue(jiraKey = "HHH-8786")
public void testLockTimeoutFind() {
    final Item item = new Item("find");
    inTransaction(session -> session.persist(item));
    try {
        inTransaction(session -> {
            session.find(Item.class, item.getId(), LockModeType.PESSIMISTIC_WRITE);
            TransactionUtil2.inTransaction(sessionFactory(), secondSession -> {
                try {
                    secondSession.find(Item.class, item.getId(), LockModeType.PESSIMISTIC_WRITE, Collections.singletonMap(AvailableSettings.JAKARTA_LOCK_TIMEOUT, LockOptions.NO_WAIT));
                    fail("Expecting a failure");
                } catch (LockTimeoutException | PessimisticLockException expected) {
                // expected outcome
                }
            });
        });
    } finally {
        inTransaction(session -> session.createQuery("delete Item").executeUpdate());
    }
}
Also used : Item(org.hibernate.orm.test.jpa.model.Item) LockTimeoutException(jakarta.persistence.LockTimeoutException) PessimisticLockException(jakarta.persistence.PessimisticLockException) AbstractJPATest(org.hibernate.orm.test.jpa.model.AbstractJPATest) Test(org.junit.jupiter.api.Test) TestForIssue(org.hibernate.testing.TestForIssue)

Example 4 with LockTimeoutException

use of jakarta.persistence.LockTimeoutException in project eclipselink by eclipse-ee4j.

the class QueryImpl method getSingleResult.

/**
 * Execute a SELECT query that returns a single untyped result.
 *
 * @return the result
 * @throws NoResultException if there is no result
 * @throws NonUniqueResultException if more than one result
 * @throws IllegalStateException if called for a Java Persistence query
 *         language UPDATE or DELETE statement
 * @throws QueryTimeoutException if the query execution exceeds the query
 *         timeout value set and only the statement is rolled back
 * @throws TransactionRequiredException if a lock mode other than NONE has
 *         been been set and there is no transaction or the persistence
 *         context has not been joined to the transaction
 * @throws PessimisticLockException if pessimistic locking fails and the
 *         transaction is rolled back
 * @throws LockTimeoutException if pessimistic locking fails and only the
 *         statement is rolled back
 * @throws PersistenceException if the query execution exceeds the query
 *         timeout value set and the transaction is rolled back
 */
public Object getSingleResult() {
    boolean rollbackOnException = true;
    // bug51411440: need to throw IllegalStateException if query
    // executed on closed em
    this.entityManager.verifyOpenWithSetRollbackOnly();
    try {
        setAsSQLReadQuery();
        propagateResultProperties();
        // It could be Cursor or other Collection or Map type.
        if (!(getDatabaseQueryInternal().isReadQuery())) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_single_result"));
        }
        Object result = executeReadQuery();
        if (result instanceof List) {
            List results = (List) result;
            if (results.isEmpty()) {
                rollbackOnException = false;
                throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
            } else if (results.size() > 1) {
                rollbackOnException = false;
                throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", null));
            }
            return results.get(0);
        } else {
            if (result == null) {
                rollbackOnException = false;
                throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", null));
            }
            return result;
        }
    } catch (LockTimeoutException exception) {
        throw exception;
    } catch (PersistenceException exception) {
        if (rollbackOnException) {
            setRollbackOnly();
        }
        throw exception;
    } catch (IllegalStateException exception) {
        setRollbackOnly();
        throw exception;
    } catch (RuntimeException exception) {
        setRollbackOnly();
        throw new PersistenceException(exception);
    }
}
Also used : PersistenceException(jakarta.persistence.PersistenceException) ArrayList(java.util.ArrayList) List(java.util.List) LockTimeoutException(jakarta.persistence.LockTimeoutException)

Example 5 with LockTimeoutException

use of jakarta.persistence.LockTimeoutException in project eclipselink by eclipse-ee4j.

the class StoredProcedureQueryImpl method execute.

/**
 * Returns true if the first result corresponds to a result set, and false
 * if it is an update count or if there are no results other than through
 * INOUT and OUT parameters, if any.
 * @return true if first result corresponds to result set
 * @throws QueryTimeoutException if the query execution exceeds the query
 * timeout value set and only the statement is rolled back
 * @throws PersistenceException if the query execution exceeds the query
 * timeout value set and the transaction is rolled back
 */
@Override
public boolean execute() {
    try {
        entityManager.verifyOpen();
        if (!getDatabaseQueryInternal().isResultSetMappingQuery()) {
            throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_spq_query_for_execute"));
        }
        getResultSetMappingQuery().setIsExecuteCall(true);
        executeCall = (DatabaseCall) executeReadQuery();
        executeStatement = executeCall.getStatement();
        // Add this query to the entity manager open queries list.
        // The query will be closed in the following cases:
        // Within a transaction:
        // - on commit
        // - on rollback
        // Outside of a transaction:
        // - em close
        // Other safeguards, we will close the query if/when
        // - we hit the end of the results.
        // - this query is garbage collected (finalize method)
        // 
        // Deferring closing the call avoids having to go through all the
        // results now (and building all the result objects) and things
        // remain on a as needed basis from the statement.
        entityManager.addOpenQuery(this);
        hasMoreResults = executeCall.getExecuteReturnValue();
        // true and build the results from the output cursors.
        if (!hasMoreResults && getCall().hasOutputCursors()) {
            hasMoreResults = true;
            outputCursorIndex = 0;
            isOutputCursorResultSet = true;
        }
        return hasMoreResults;
    } catch (LockTimeoutException exception) {
        throw exception;
    } catch (PersistenceException exception) {
        setRollbackOnly();
        throw exception;
    } catch (IllegalStateException e) {
        setRollbackOnly();
        throw e;
    } catch (RuntimeException exception) {
        setRollbackOnly();
        throw new PersistenceException(exception);
    }
}
Also used : PersistenceException(jakarta.persistence.PersistenceException) LockTimeoutException(jakarta.persistence.LockTimeoutException)

Aggregations

LockTimeoutException (jakarta.persistence.LockTimeoutException)20 PersistenceException (jakarta.persistence.PersistenceException)10 PessimisticLockException (jakarta.persistence.PessimisticLockException)5 List (java.util.List)5 ExecutionException (java.util.concurrent.ExecutionException)5 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)5 RequiresDialectFeature (org.hibernate.testing.RequiresDialectFeature)5 Test (org.junit.Test)5 HashMap (java.util.HashMap)4 CountDownLatch (java.util.concurrent.CountDownLatch)4 FutureTask (java.util.concurrent.FutureTask)4 RequiresDialect (org.hibernate.testing.RequiresDialect)4 QueryTimeoutException (jakarta.persistence.QueryTimeoutException)3 ArrayList (java.util.ArrayList)3 ClassDescriptor (org.eclipse.persistence.descriptors.ClassDescriptor)3 ReadObjectQuery (org.eclipse.persistence.queries.ReadObjectQuery)3 AbstractJPATest (org.hibernate.orm.test.jpa.model.AbstractJPATest)3 Item (org.hibernate.orm.test.jpa.model.Item)3 Test (org.junit.jupiter.api.Test)3 OptimisticLockException (jakarta.persistence.OptimisticLockException)2