Home | History | Annotate | Download | only in jpa
      1 /*
      2  * Copyright (C) 2010 Google, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.inject.persist.jpa;
     18 
     19 import com.google.inject.Guice;
     20 import com.google.inject.Inject;
     21 import com.google.inject.Injector;
     22 import com.google.inject.name.Named;
     23 import com.google.inject.persist.PersistService;
     24 import com.google.inject.persist.Transactional;
     25 import com.google.inject.persist.UnitOfWork;
     26 import com.google.inject.persist.finder.Finder;
     27 import java.io.IOException;
     28 import java.util.Date;
     29 import javax.persistence.EntityManager;
     30 import javax.persistence.EntityManagerFactory;
     31 import javax.persistence.NoResultException;
     32 import junit.framework.TestCase;
     33 
     34 /** @author Dhanji R. Prasanna (dhanji (at) gmail.com) */
     35 
     36 public class ManagedLocalTransactionsAcrossRequestTest extends TestCase {
     37   private Injector injector;
     38   private static final String UNIQUE_TEXT = "some unique text" + new Date();
     39   private static final String UNIQUE_TEXT_MERGE = "meRG_Esome unique text" + new Date();
     40   private static final String UNIQUE_TEXT_MERGE_FORDF =
     41       "aSdoaksdoaksdmeRG_Esome unique text" + new Date();
     42   private static final String TRANSIENT_UNIQUE_TEXT = "some other unique text" + new Date();
     43 
     44   @Override
     45   public void setUp() {
     46     injector = Guice.createInjector(new JpaPersistModule("testUnit"));
     47 
     48     //startup persistence
     49     injector.getInstance(PersistService.class).start();
     50   }
     51 
     52   @Override
     53   public final void tearDown() {
     54     injector.getInstance(EntityManagerFactory.class).close();
     55   }
     56 
     57   public void testSimpleTransaction() {
     58     injector.getInstance(TransactionalObject.class).runOperationInTxn();
     59 
     60     EntityManager em = injector.getInstance(EntityManager.class);
     61     assertFalse(em.getTransaction().isActive());
     62 
     63     //test that the data has been stored
     64     Object result =
     65         em.createQuery("from JpaTestEntity where text = :text")
     66             .setParameter("text", UNIQUE_TEXT)
     67             .getSingleResult();
     68     injector.getInstance(UnitOfWork.class).end();
     69 
     70     assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
     71 
     72     assertEquals(
     73         "queried entity did not match--did automatic txn fail?",
     74         UNIQUE_TEXT,
     75         ((JpaTestEntity) result).getText());
     76     injector.getInstance(UnitOfWork.class).end();
     77   }
     78 
     79   public void testSimpleTransactionWithMerge() {
     80     EntityManager emOrig = injector.getInstance(EntityManager.class);
     81     JpaTestEntity entity =
     82         injector.getInstance(TransactionalObject.class).runOperationInTxnWithMerge();
     83 
     84     assertNotNull("Entity was not given an id (was not persisted correctly?)", entity.getId());
     85 
     86     EntityManager em = injector.getInstance(EntityManager.class);
     87     assertFalse(em.getTransaction().isActive());
     88 
     89     //test that the data has been stored
     90     assertTrue("Em was closed after txn!", em.isOpen());
     91     assertEquals("Em was not kept open across txns", emOrig, em);
     92     assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity));
     93 
     94     Object result =
     95         em.createQuery("from JpaTestEntity where text = :text")
     96             .setParameter("text", UNIQUE_TEXT_MERGE)
     97             .getSingleResult();
     98     injector.getInstance(UnitOfWork.class).end();
     99 
    100     assertTrue(result instanceof JpaTestEntity);
    101 
    102     assertEquals(
    103         "queried entity did not match--did automatic txn fail?",
    104         UNIQUE_TEXT_MERGE,
    105         ((JpaTestEntity) result).getText());
    106     injector.getInstance(UnitOfWork.class).end();
    107   }
    108 
    109   public void disabled_testSimpleTransactionWithMergeAndDF() {
    110     EntityManager emOrig = injector.getInstance(EntityManager.class);
    111     JpaTestEntity entity =
    112         injector.getInstance(TransactionalObject.class).runOperationInTxnWithMergeForDf();
    113 
    114     EntityManager em = injector.getInstance(EntityManager.class);
    115     assertFalse("txn was not closed by transactional service", em.getTransaction().isActive());
    116 
    117     //test that the data has been stored
    118     assertTrue("Em was closed after txn!", em.isOpen());
    119     assertEquals("Em was not kept open across txns", emOrig, em);
    120     assertTrue("Merge did not store state or did not return persistent copy", em.contains(entity));
    121 
    122     Object result = injector.getInstance(TransactionalObject.class).find(UNIQUE_TEXT_MERGE_FORDF);
    123     injector.getInstance(UnitOfWork.class).end();
    124 
    125     assertNotNull(result);
    126     assertTrue(result instanceof JpaTestEntity);
    127 
    128     assertEquals(
    129         "queried entity did not match--did automatic txn fail?",
    130         UNIQUE_TEXT_MERGE_FORDF,
    131         ((JpaTestEntity) result).getText());
    132     injector.getInstance(UnitOfWork.class).end();
    133   }
    134 
    135   public void testSimpleTransactionRollbackOnChecked() {
    136     try {
    137       injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingChecked();
    138     } catch (IOException e) {
    139       //ignore
    140       injector.getInstance(UnitOfWork.class).end();
    141     }
    142 
    143     EntityManager em = injector.getInstance(EntityManager.class);
    144 
    145     assertFalse(
    146         "Previous EM was not closed by transactional service (rollback didnt happen?)",
    147         em.getTransaction().isActive());
    148 
    149     //test that the data has been stored
    150     try {
    151       Object result =
    152           em.createQuery("from JpaTestEntity where text = :text")
    153               .setParameter("text", TRANSIENT_UNIQUE_TEXT)
    154               .getSingleResult();
    155       injector.getInstance(UnitOfWork.class).end();
    156       fail();
    157     } catch (NoResultException e) {
    158     }
    159 
    160     injector.getInstance(UnitOfWork.class).end();
    161   }
    162 
    163   public void testSimpleTransactionRollbackOnUnchecked() {
    164     try {
    165       injector.getInstance(TransactionalObject.class).runOperationInTxnThrowingUnchecked();
    166     } catch (RuntimeException re) {
    167       //ignore
    168       injector.getInstance(UnitOfWork.class).end();
    169     }
    170 
    171     EntityManager em = injector.getInstance(EntityManager.class);
    172     assertFalse(
    173         "Session was not closed by transactional service (rollback didnt happen?)",
    174         em.getTransaction().isActive());
    175 
    176     try {
    177       Object result =
    178           em.createQuery("from JpaTestEntity where text = :text")
    179               .setParameter("text", TRANSIENT_UNIQUE_TEXT)
    180               .getSingleResult();
    181       injector.getInstance(UnitOfWork.class).end();
    182       fail();
    183     } catch (NoResultException e) {
    184     }
    185 
    186     injector.getInstance(UnitOfWork.class).end();
    187   }
    188 
    189   public static class TransactionalObject {
    190     private final EntityManager em;
    191 
    192     @Inject
    193     public TransactionalObject(EntityManager em) {
    194       this.em = em;
    195     }
    196 
    197     @Transactional
    198     public void runOperationInTxn() {
    199       JpaTestEntity entity = new JpaTestEntity();
    200       entity.setText(UNIQUE_TEXT);
    201       em.persist(entity);
    202     }
    203 
    204     @Transactional
    205     public JpaTestEntity runOperationInTxnWithMerge() {
    206       JpaTestEntity entity = new JpaTestEntity();
    207       entity.setText(UNIQUE_TEXT_MERGE);
    208       return em.merge(entity);
    209     }
    210 
    211     @Transactional
    212     public JpaTestEntity runOperationInTxnWithMergeForDf() {
    213       JpaTestEntity entity = new JpaTestEntity();
    214       entity.setText(UNIQUE_TEXT_MERGE_FORDF);
    215       return em.merge(entity);
    216     }
    217 
    218     @Transactional(rollbackOn = IOException.class)
    219     public void runOperationInTxnThrowingChecked() throws IOException {
    220       JpaTestEntity entity = new JpaTestEntity();
    221       entity.setText(TRANSIENT_UNIQUE_TEXT);
    222       em.persist(entity);
    223 
    224       throw new IOException();
    225     }
    226 
    227     @Transactional
    228     public void runOperationInTxnThrowingUnchecked() {
    229       JpaTestEntity entity = new JpaTestEntity();
    230       entity.setText(TRANSIENT_UNIQUE_TEXT);
    231       em.persist(entity);
    232 
    233       throw new IllegalStateException();
    234     }
    235 
    236     @Finder(query = "from JpaTestEntity where text = :text")
    237     public JpaTestEntity find(@Named("text") String text) {
    238       return null;
    239     }
    240   }
    241 }
    242