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;
24
25import junit.framework.TestCase;
26
27import java.io.FileNotFoundException;
28import java.io.IOException;
29import java.util.Date;
30import java.util.List;
31
32import javax.persistence.EntityManager;
33
34/**
35 * This test asserts class level @Transactional annotation behavior.
36 *
37 * Class-level @Transactional is a shortcut if all non-private methods in the class are meant to be
38 * transactional.
39 *
40 * @author Dhanji R. Prasanna (dhanji@gmail.com)
41 */
42
43public class ClassLevelManagedLocalTransactionsTest extends TestCase {
44  private Injector injector;
45  private static final String UNIQUE_TEXT = "JPAsome unique text88888" + new Date();
46  private static final String UNIQUE_TEXT_2 = "JPAsome asda unique teasdalsdplasdxt" + new Date();
47  private static final String TRANSIENT_UNIQUE_TEXT = "JPAsome other unique texaksoksojadasdt"
48      + new Date();
49
50  public void setUp() {
51    injector = Guice.createInjector(new JpaPersistModule("testUnit"));
52
53    //startup persistence
54    injector.getInstance(PersistService.class).start();
55  }
56
57  public void tearDown() {
58    injector.getInstance(PersistService.class).stop();
59    injector = null;
60  }
61
62  public void testSimpleTransaction() {
63    injector.getInstance(TransactionalObject.class).runOperationInTxn();
64
65    EntityManager session = injector.getInstance(EntityManager.class);
66    assertFalse("EntityManager was not closed by transactional service",
67        session.getTransaction().isActive());
68
69    //test that the data has been stored
70    session.getTransaction().begin();
71    Object result = session.createQuery("from JpaTestEntity where text = :text")
72        .setParameter("text", UNIQUE_TEXT).getSingleResult();
73
74    session.getTransaction().commit();
75
76    assertTrue("odd result returned fatal", result instanceof JpaTestEntity);
77
78    assertEquals("queried entity did not match--did automatic txn fail?",
79        UNIQUE_TEXT, (((JpaTestEntity) result).getText()));
80  }
81
82  public void testSimpleTransactionRollbackOnChecked() {
83    try {
84      injector.getInstance(TransactionalObject2.class).runOperationInTxnThrowingChecked();
85    } catch (IOException e) {
86      //ignore
87    }
88
89    EntityManager session = injector.getInstance(EntityManager.class);
90    assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)",
91        session.getTransaction().isActive());
92
93    //test that the data has been stored
94    session.getTransaction().begin();
95    List<?> result = session.createQuery("from JpaTestEntity where text = :text")
96        .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList();
97
98    session.getTransaction().commit();
99
100    assertTrue("a result was returned! rollback sure didnt happen!!!", result.isEmpty());
101  }
102
103  public void testSimpleTransactionRollbackOnCheckedExcepting() {
104    Exception ex = null;
105    try {
106      injector.getInstance(TransactionalObject3.class).runOperationInTxnThrowingCheckedExcepting();
107      fail("Exception was not thrown by test txn-al method!");
108    } catch (IOException e) {
109      //ignored
110    }
111
112    EntityManager session = injector.getInstance(EntityManager.class);
113    assertFalse("Txn was not closed by transactional service (commit didnt happen?)",
114        session.getTransaction().isActive());
115
116    //test that the data has been stored
117    session.getTransaction().begin();
118    Object result = session.createQuery("from JpaTestEntity where text = :text")
119        .setParameter("text", UNIQUE_TEXT_2).getSingleResult();
120
121    session.getTransaction().commit();
122
123    assertNotNull("a result was not returned! rollback happened anyway (ignore failed)!!!",
124        result);
125  }
126
127  public void testSimpleTransactionRollbackOnUnchecked() {
128    try {
129      injector.getInstance(TransactionalObject4.class).runOperationInTxnThrowingUnchecked();
130    } catch (RuntimeException re) {
131      //ignore
132    }
133
134    EntityManager session = injector.getInstance(EntityManager.class);
135    assertFalse("EntityManager was not closed by transactional service (rollback didnt happen?)",
136        session.getTransaction().isActive());
137
138    //test that the data has been stored
139    session.getTransaction().begin();
140    List<?> result = session.createQuery("from JpaTestEntity where text = :text")
141        .setParameter("text", TRANSIENT_UNIQUE_TEXT).getResultList();
142
143    session.getTransaction().commit();
144
145    assertTrue("a result was returned! rollback sure didnt happen!!!",
146        result.isEmpty());
147  }
148
149  @Transactional
150  public static class TransactionalObject {
151    @Inject EntityManager session;
152
153    public void runOperationInTxn() {
154      assertTrue(session.getTransaction().isActive());
155      JpaTestEntity entity = new JpaTestEntity();
156      entity.setText(UNIQUE_TEXT);
157      session.persist(entity);
158    }
159
160  }
161
162  @Transactional
163  public static class TransactionalObject4 {
164    @Inject EntityManager session;
165
166    @Transactional
167    public void runOperationInTxnThrowingUnchecked() {
168      assertTrue(session.getTransaction().isActive());
169      JpaTestEntity entity = new JpaTestEntity();
170      entity.setText(TRANSIENT_UNIQUE_TEXT);
171      session.persist(entity);
172
173      throw new IllegalStateException();
174    }
175  }
176
177  @Transactional(rollbackOn = IOException.class, ignore = FileNotFoundException.class)
178  public static class TransactionalObject3 {
179    @Inject EntityManager session;
180
181    public void runOperationInTxnThrowingCheckedExcepting() throws IOException {
182      assertTrue(session.getTransaction().isActive());
183      JpaTestEntity entity = new JpaTestEntity();
184      entity.setText(UNIQUE_TEXT_2);
185      session.persist(entity);
186
187      throw new FileNotFoundException();
188    }
189  }
190
191  @Transactional(rollbackOn = IOException.class)
192  public static class TransactionalObject2 {
193    @Inject EntityManager session;
194
195    public void runOperationInTxnThrowingChecked() throws IOException {
196      assertTrue(session.getTransaction().isActive());
197      JpaTestEntity entity = new JpaTestEntity();
198      entity.setText(TRANSIENT_UNIQUE_TEXT);
199      session.persist(entity);
200
201      throw new IOException();
202    }
203  }
204}
205