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
17package com.google.inject.persist.jpa;
18
19import com.google.inject.Guice;
20import com.google.inject.Inject;
21import com.google.inject.Injector;
22import com.google.inject.persist.PersistService;
23import com.google.inject.persist.Transactional;
24import com.google.inject.persist.UnitOfWork;
25
26import junit.framework.TestCase;
27
28import java.io.IOException;
29import java.util.Date;
30
31import javax.persistence.EntityManager;
32import javax.persistence.EntityManagerFactory;
33import javax.persistence.NoResultException;
34
35/**
36 * @author Dhanji R. Prasanna (dhanji@gmail.com)
37 */
38
39public class JoiningLocalTransactionsTest extends TestCase {
40  private Injector injector;
41  private static final String UNIQUE_TEXT = JoiningLocalTransactionsTest.class + "some unique text"
42      + new Date();
43  private static final String TRANSIENT_UNIQUE_TEXT = JoiningLocalTransactionsTest.class
44      + "some other unique text" + new Date();
45
46  @Override
47  public void setUp() {
48    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
49
50    //startup persistence
51    injector.getInstance(PersistService.class).start();
52  }
53
54  //cleanup entitymanager in case some of the rollback tests left it in an open state
55  @Override
56  public final void tearDown() {
57    injector.getInstance(UnitOfWork.class).end();
58    injector.getInstance(EntityManagerFactory.class).close();
59  }
60
61  public void testSimpleTransaction() {
62    injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class)
63        .runOperationInTxn();
64
65    EntityManager em = injector.getInstance(EntityManager.class);
66    assertFalse("txn was not closed by transactional service",
67        em.getTransaction().isActive());
68
69    //test that the data has been stored
70    Object result = em.createQuery("from JpaTestEntity where text = :text")
71        .setParameter("text", UNIQUE_TEXT).getSingleResult();
72    injector.getInstance(UnitOfWork.class).end();
73
74    assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
75
76    assertEquals("queried entity did not match--did automatic txn fail?", UNIQUE_TEXT,
77        ((JpaTestEntity) result).getText());
78  }
79
80  public void testSimpleTransactionRollbackOnChecked() {
81    try {
82      injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class)
83          .runOperationInTxnThrowingChecked();
84    } catch (IOException e) {
85      //ignore
86      injector.getInstance(UnitOfWork.class).end();
87    }
88
89    EntityManager em = injector.getInstance(EntityManager.class);
90
91    assertFalse("EM was not closed by transactional service (rollback didnt happen?)",
92        em.getTransaction().isActive());
93
94    //test that the data has been stored
95    try {
96      Object result = em.createQuery("from JpaTestEntity where text = :text")
97          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
98      injector.getInstance(UnitOfWork.class).end();
99      fail("a result was returned! rollback sure didnt happen!!!");
100    } catch (NoResultException e) { }
101  }
102
103  public void testSimpleTransactionRollbackOnUnchecked() {
104    try {
105      injector.getInstance(JoiningLocalTransactionsTest.TransactionalObject.class)
106          .runOperationInTxnThrowingUnchecked();
107    } catch (RuntimeException re) {
108      //ignore
109      injector.getInstance(UnitOfWork.class).end();
110    }
111
112    EntityManager em = injector.getInstance(EntityManager.class);
113    assertFalse("Session was not closed by transactional service (rollback didnt happen?)",
114        em.getTransaction().isActive());
115
116    try {
117      Object result = em.createQuery("from JpaTestEntity where text = :text")
118          .setParameter("text", TRANSIENT_UNIQUE_TEXT).getSingleResult();
119      injector.getInstance(UnitOfWork.class).end();
120      fail("a result was returned! rollback sure didnt happen!!!");
121    } catch (NoResultException e) {}
122  }
123
124  public static class TransactionalObject {
125    private final EntityManager em;
126
127    @Inject
128    public TransactionalObject(EntityManager em) {
129      this.em = em;
130    }
131
132    @Transactional
133    public void runOperationInTxn() {
134      runOperationInTxnInternal();
135    }
136
137    @Transactional(rollbackOn = IOException.class)
138    public void runOperationInTxnInternal() {
139      JpaTestEntity entity = new JpaTestEntity();
140      entity.setText(UNIQUE_TEXT);
141      em.persist(entity);
142    }
143
144    @Transactional(rollbackOn = IOException.class)
145    public void runOperationInTxnThrowingChecked() throws IOException {
146      runOperationInTxnThrowingCheckedInternal();
147    }
148
149    @Transactional
150    private void runOperationInTxnThrowingCheckedInternal() throws IOException {
151      JpaTestEntity entity = new JpaTestEntity();
152      entity.setText(TRANSIENT_UNIQUE_TEXT);
153      em.persist(entity);
154
155      throw new IOException();
156    }
157
158    @Transactional
159    public void runOperationInTxnThrowingUnchecked() {
160      runOperationInTxnThrowingUncheckedInternal();
161    }
162
163    @Transactional(rollbackOn = IOException.class)
164    public void runOperationInTxnThrowingUncheckedInternal() {
165      JpaTestEntity entity = new JpaTestEntity();
166      entity.setText(TRANSIENT_UNIQUE_TEXT);
167      em.persist(entity);
168
169      throw new IllegalStateException();
170    }
171  }
172}
173