Search in sources :

Example 11 with Context

use of jakarta.enterprise.context.spi.Context in project helidon by oracle.

the class TestJpaTransactionScopedSynchronizedEntityManager method testJpaTransactionScopedSynchronizedEntityManager.

/*
     * Test methods.
     */
@Test
void testJpaTransactionScopedSynchronizedEntityManager() throws HeuristicMixedException, HeuristicRollbackException, NotSupportedException, RollbackException, SQLException, SystemException {
    // Get a BeanManager for later use.
    final BeanManager beanManager = this.cdiContainer.getBeanManager();
    assertNotNull(beanManager);
    // Get a CDI contextual reference to this test instance.  It
    // is important to use "self" in this test instead of "this".
    final TestJpaTransactionScopedSynchronizedEntityManager self = this.cdiContainer.select(TestJpaTransactionScopedSynchronizedEntityManager.class).get();
    assertNotNull(self);
    // Get the EntityManager that is synchronized with and scoped
    // to a JTA transaction.
    final EntityManager em = self.getJpaTransactionScopedSynchronizedEntityManager();
    assertNotNull(em);
    assertTrue(em.isOpen());
    // Get a DataSource for JPA-independent testing and assertions.
    final DataSource dataSource = self.getDataSource();
    assertNotNull(dataSource);
    // We haven't started any kind of transaction yet and we
    // aren't testing anything using
    // the @jakarta.transaction.Transactional annotation so there is
    // no transaction in effect so the EntityManager cannot be
    // joined to one.
    assertFalse(em.isJoinedToTransaction());
    // Create a JPA entity and try to insert it.  This should fail
    // because according to JPA a TransactionRequiredException
    // will be thrown.
    Author author1 = new Author("Abraham Lincoln");
    try {
        em.persist(author1);
        fail("A TransactionRequiredException should have been thrown");
    } catch (final TransactionRequiredException expected) {
    }
    assertFalse(em.contains(author1));
    assertNull(author1.getId());
    // Get the TransactionManager that normally is behind the
    // scenes and use it to start a Transaction.
    final TransactionManager tm = self.getTransactionManager();
    assertNotNull(tm);
    // TODO: set to 20 minutes for debugging purposes only
    tm.setTransactionTimeout(60 * 20);
    // New transaction.
    tm.begin();
    // Grab the TransactionScoped context while the transaction is
    // active.  We want to make sure it's active at various
    // points.
    final Context transactionScopedContext = beanManager.getContext(TransactionScoped.class);
    assertNotNull(transactionScopedContext);
    assertTrue(transactionScopedContext.isActive());
    // Now magically our EntityManager should be joined to it.
    assertTrue(em.isJoinedToTransaction());
    // Roll the transaction back and note that our EntityManager
    // is no longer joined to it.
    tm.rollback();
    assertFalse(em.isJoinedToTransaction());
    assertFalse(transactionScopedContext.isActive());
    assertFalse(em.contains(author1));
    assertNull(author1.getId());
    // Start another transaction.
    tm.begin();
    assertTrue(transactionScopedContext.isActive());
    // Persist our Author.
    assertNull(author1.getId());
    em.persist(author1);
    assertTrue(em.contains(author1));
    // A persist() doesn't flush(), so no ID should have been
    // generated yet.
    // assertNull(author1.getId());
    // Commit the transaction and flush changes to the database.
    tm.commit();
    // After the transaction commits, a flush should happen, and
    // the Author is managed, so we should see his ID.
    assertEquals(Integer.valueOf(1), author1.getId());
    // Make sure the database contains the changes.
    try (final Connection connection = dataSource.getConnection();
        final Statement statement = connection.createStatement();
        final ResultSet resultSet = statement.executeQuery("SELECT ID, NAME FROM AUTHOR WHERE ID = 1")) {
        assertNotNull(resultSet);
        assertTrue(resultSet.next());
        assertEquals(1, resultSet.getInt(1));
        assertEquals("Abraham Lincoln", resultSet.getString(2));
        assertFalse(resultSet.next());
    }
    // The Author, however, is detached, because the transaction
    // is over, and because our PersistenceContextType is
    // TRANSACTION, not EXTENDED, the underlying persistence
    // context dies with the transaction.
    assertFalse(em.contains(author1));
    // The transaction is over, so our EntityManager is not joined
    // to one anymore.
    assertFalse(em.isJoinedToTransaction());
    assertFalse(transactionScopedContext.isActive());
    // Start a new transaction.
    tm.begin();
    assertTrue(transactionScopedContext.isActive());
    // Remove the Author we successfully committed before.  We
    // have to merge because author1 became detached a few lines
    // above.
    author1 = em.merge(author1);
    assertNotNull(author1);
    assertTrue(em.contains(author1));
    em.remove(author1);
    assertFalse(em.contains(author1));
    // Commit and flush the removal.
    tm.commit();
    assertFalse(em.isJoinedToTransaction());
    assertFalse(transactionScopedContext.isActive());
    // Note that its ID is still 1.
    assertEquals(Integer.valueOf(1), author1.getId());
    // After all this activity we should have no rows in any
    // tables.
    assertTableRowCount(dataSource, "AUTHOR", 0);
    // Start a new transaction, merge our detached author1, and
    // commit.  This will bump the author's ID and put a row in
    // the database.
    tm.begin();
    assertTrue(em.isJoinedToTransaction());
    assertTrue(transactionScopedContext.isActive());
    author1 = em.merge(author1);
    tm.commit();
    assertFalse(em.isJoinedToTransaction());
    assertFalse(em.contains(author1));
    assertFalse(transactionScopedContext.isActive());
    // Now that the commit and accompanying flush have
    // happened, our author's ID has changed.
    assertEquals(Integer.valueOf(2), author1.getId());
    // Make sure the database contains the changes.
    try (final Connection connection = dataSource.getConnection();
        final Statement statement = connection.createStatement();
        final ResultSet resultSet = statement.executeQuery("SELECT ID, NAME FROM AUTHOR")) {
        assertNotNull(resultSet);
        assertTrue(resultSet.next());
        assertEquals(2, resultSet.getInt(1));
        assertEquals("Abraham Lincoln", resultSet.getString(2));
        assertFalse(resultSet.next());
    }
    // Discard author1 in this unit test so we'll get a
    // NullPointerException if we try to use him again.  (After
    // all it's confusing now that author1 has 2 for an ID!)
    author1 = null;
    // Let's find the new author that got merged in.  We'll use a
    // transaction just for kicks.
    tm.begin();
    assertTrue(em.isJoinedToTransaction());
    assertTrue(transactionScopedContext.isActive());
    Author author2 = em.find(Author.class, Integer.valueOf(2));
    assertNotNull(author2);
    assertTrue(em.contains(author2));
    assertEquals(Integer.valueOf(2), author2.getId());
    assertEquals("Abraham Lincoln", author2.getName());
    // No need, really, but it's what a @Transactional method
    // would do.
    tm.commit();
    assertFalse(em.isJoinedToTransaction());
    assertFalse(em.contains(author2));
    assertFalse(transactionScopedContext.isActive());
    // New transaction.  Let's change the name.
    tm.begin();
    assertTrue(em.isJoinedToTransaction());
    assertTrue(transactionScopedContext.isActive());
    author2 = em.find(Author.class, Integer.valueOf(2));
    assertNotNull(author2);
    // Remember that finding an entity causes it to become
    // managed.
    assertTrue(em.contains(author2));
    assertEquals(Integer.valueOf(2), author2.getId());
    assertEquals("Abraham Lincoln", author2.getName());
    author2.setName("Abe Lincoln");
    assertEquals(Integer.valueOf(2), author2.getId());
    assertEquals("Abe Lincoln", author2.getName());
    tm.commit();
    assertFalse(em.isJoinedToTransaction());
    assertFalse(em.contains(author2));
    assertFalse(transactionScopedContext.isActive());
    // Make sure the database contains the changes.
    try (final Connection connection = dataSource.getConnection();
        final Statement statement = connection.createStatement();
        final ResultSet resultSet = statement.executeQuery("SELECT ID, NAME FROM AUTHOR")) {
        assertNotNull(resultSet);
        assertTrue(resultSet.next());
        assertEquals(2, resultSet.getInt(1));
        assertEquals("Abe Lincoln", resultSet.getString(2));
        assertFalse(resultSet.next());
    }
    // Let's go find him again.
    tm.begin();
    assertTrue(em.isJoinedToTransaction());
    assertTrue(transactionScopedContext.isActive());
    author2 = em.find(Author.class, Integer.valueOf(2));
    assertNotNull(author2);
    assertTrue(em.contains(author2));
    assertEquals(Integer.valueOf(2), author2.getId());
    assertEquals("Abe Lincoln", author2.getName());
    // No need, really, but it's what a @Transactional method
    // would do.
    tm.commit();
    assertFalse(em.isJoinedToTransaction());
    assertFalse(em.contains(author2));
    assertFalse(transactionScopedContext.isActive());
}
Also used : PersistenceContext(jakarta.persistence.PersistenceContext) Context(jakarta.enterprise.context.spi.Context) EntityManager(jakarta.persistence.EntityManager) TransactionRequiredException(jakarta.persistence.TransactionRequiredException) TransactionManager(jakarta.transaction.TransactionManager) Statement(java.sql.Statement) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) BeanManager(jakarta.enterprise.inject.spi.BeanManager) DataSource(javax.sql.DataSource) Test(org.junit.jupiter.api.Test)

Aggregations

Context (jakarta.enterprise.context.spi.Context)11 CreationalContext (jakarta.enterprise.context.spi.CreationalContext)4 EntityManager (jakarta.persistence.EntityManager)3 Annotation (java.lang.annotation.Annotation)3 ContextNotActiveException (jakarta.enterprise.context.ContextNotActiveException)2 Dependent (jakarta.enterprise.context.Dependent)2 AlterableContext (jakarta.enterprise.context.spi.AlterableContext)2 Bean (jakarta.enterprise.inject.spi.Bean)2 BeanManager (jakarta.enterprise.inject.spi.BeanManager)2 ProxyObject (org.jboss.weld.bean.proxy.ProxyObject)2 WeldCreationalContext (org.jboss.weld.contexts.WeldCreationalContext)2 ReferenceCountedContext (io.helidon.integrations.cdi.referencecountedcontext.ReferenceCountedContext)1 ApplicationScoped (jakarta.enterprise.context.ApplicationScoped)1 RequestScoped (jakarta.enterprise.context.RequestScoped)1 RequestContextController (jakarta.enterprise.context.control.RequestContextController)1 CreationException (jakarta.enterprise.inject.CreationException)1 AnnotatedType (jakarta.enterprise.inject.spi.AnnotatedType)1 InjectionPoint (jakarta.enterprise.inject.spi.InjectionPoint)1 InterceptionType (jakarta.enterprise.inject.spi.InterceptionType)1 ProcessInjectionPoint (jakarta.enterprise.inject.spi.ProcessInjectionPoint)1