1 package net.sf.ehcache.store;
2
3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse;
5 import static org.junit.Assert.assertNotNull;
6 import static org.junit.Assert.assertNull;
7 import static org.junit.Assert.assertTrue;
8 import static org.junit.Assert.fail;
9
10 import javax.transaction.RollbackException;
11 import javax.transaction.Transaction;
12 import javax.transaction.TransactionManager;
13
14 import net.sf.ehcache.Cache;
15 import net.sf.ehcache.CacheManager;
16 import net.sf.ehcache.Element;
17 import net.sf.ehcache.concurrent.CacheLockProvider;
18 import net.sf.ehcache.concurrent.LockType;
19 import net.sf.ehcache.config.CacheConfiguration;
20
21 import org.junit.Before;
22 import org.junit.Test;
23
24 import bitronix.tm.TransactionManagerServices;
25
26 /***
27 * @author Alex Snaps
28 */
29 public class XATransactionalStoreTest {
30
31 private TransactionManager transactionManager;
32 private Cache cach1;
33 private Cache cache;
34
35 @Before
36 public void setup() throws Exception {
37 transactionManager = TransactionManagerServices.getTransactionManager();
38 CacheManager cacheManager = CacheManager.getInstance();
39 cache = cacheManager.getCache("xaCache");
40 if (cache == null) {
41 cache = new Cache(new CacheConfiguration("xaCache", 1000).transactionalMode(CacheConfiguration.TransactionalMode.XA_STRICT));
42 cacheManager.addCache(cache);
43 }
44 cach1 = cacheManager.getCache("otherXaCache");
45 if (cach1 == null) {
46 cach1 = new Cache(new CacheConfiguration("otherXaCache", 1000).transactionalMode(CacheConfiguration.TransactionalMode.XA_STRICT));
47 cacheManager.addCache(cach1);
48 }
49 transactionManager.begin();
50 cache.removeAll();
51 cach1.removeAll();
52 transactionManager.commit();
53 }
54
55 @Test
56 public void testPutIfAbsent() throws Exception {
57 transactionManager.begin();
58 assertEquals("Cache should be empty to start", 0, cache.getSize());
59 assertEquals("Cach1 should be empty to start", 0, cach1.getSize());
60 assertNull(cach1.putIfAbsent(new Element("key", "value1")));
61 assertNull(cache.putIfAbsent(new Element("key", "value1")));
62 Transaction tx1 = transactionManager.suspend();
63 transactionManager.begin();
64 assertNull(cache.putIfAbsent(new Element("key", "value2")));
65 transactionManager.commit();
66 transactionManager.resume(tx1);
67 try {
68 transactionManager.commit();
69 fail("This should have thrown an Exception, as the putIfAbsent should have failed!");
70 } catch (RollbackException e) {
71
72 }
73
74 CacheLockProvider clp = (CacheLockProvider) cache.getInternalContext();
75 assertFalse(clp.getSyncForKey("key").isHeldByCurrentThread(LockType.WRITE));
76
77 transactionManager.begin();
78 Element element = cache.get("key");
79 assertEquals("value2", element.getValue());
80 assertNull(cach1.get("key"));
81 assertEquals(element, cache.putIfAbsent(new Element("key", "value3")));
82 transactionManager.commit();
83
84 transactionManager.begin();
85 element = cache.get("key");
86 assertEquals("value2", element.getValue());
87 transactionManager.commit();
88
89 transactionManager.begin();
90 cache.put(new Element("key2", "randomValue"));
91 cache.putIfAbsent(new Element("key2", "notThere!"));
92 assertEquals("randomValue", cache.get("key2").getValue());
93 transactionManager.commit();
94
95 transactionManager.begin();
96 assertEquals("randomValue", cache.get("key2").getValue());
97 transactionManager.commit();
98
99 transactionManager.begin();
100 cach1.remove("key2");
101 cache.remove("key2");
102 cache.putIfAbsent(new Element("key2", "nowThere!"));
103 assertEquals("nowThere!", cache.get("key2").getValue());
104 transactionManager.commit();
105
106 transactionManager.begin();
107 assertEquals("nowThere!", cache.get("key2").getValue());
108 transactionManager.commit();
109
110 transactionManager.begin();
111 cache.remove("key2");
112 cache.putIfAbsent(new Element("key2", "nowThere!"));
113 assertEquals("nowThere!", cache.get("key2").getValue());
114 Transaction tx2 = transactionManager.suspend();
115
116 transactionManager.begin();
117 assertEquals("nowThere!", cache.get("key2").getValue());
118 cache.put(new Element("key2", "newValue"));
119 transactionManager.commit();
120
121 transactionManager.resume(tx2);
122 cach1.put(new Element("fake", "entry"));
123 try {
124 transactionManager.commit();
125 fail("This should have thrown an Exception!");
126 } catch (RollbackException e) {
127
128 }
129
130 transactionManager.begin();
131 assertEquals("newValue", cache.get("key2").getValue());
132 transactionManager.commit();
133 }
134
135 @Test
136 public void testRemoveElement() throws Exception {
137 transactionManager.begin();
138 assertEquals("Cache should be empty to start", 0, cache.getSize());
139 assertEquals("Cach1 should be empty to start", 0, cach1.getSize());
140 assertFalse(cache.removeElement(new Element("blah", "someValue")));
141 cache.put(new Element("blah", "value"));
142 assertFalse(cache.removeElement(new Element("blah", "someValue")));
143 transactionManager.commit();
144 transactionManager.begin();
145 assertNotNull(cache.get("blah"));
146 assertTrue(cache.removeElement(new Element("blah", "value")));
147 transactionManager.commit();
148 transactionManager.begin();
149 assertNull(cache.get("blah"));
150 transactionManager.commit();
151
152 transactionManager.begin();
153 cache.put(new Element("key", "value"));
154 transactionManager.commit();
155 transactionManager.begin();
156 cach1.put(new Element("random", "things"));
157 cache.removeElement(new Element("key", "value"));
158 Transaction tx1 = transactionManager.suspend();
159 transactionManager.begin();
160 assertTrue(cache.removeElement(new Element("key", "value")));
161 transactionManager.commit();
162 transactionManager.resume(tx1);
163 try {
164 transactionManager.commit();
165 fail("Transaction should have failed, element is deleted already");
166 } catch (RollbackException e) {
167
168 }
169 transactionManager.begin();
170 assertNull(cache.get("key"));
171 transactionManager.commit();
172
173 transactionManager.begin();
174 cache.put(new Element("key", "value"));
175 transactionManager.commit();
176 transactionManager.begin();
177 cach1.put(new Element("random", "things"));
178 cache.removeElement(new Element("key", "value"));
179 tx1 = transactionManager.suspend();
180 transactionManager.begin();
181 cache.put(new Element("key", "newValue"));
182 transactionManager.commit();
183 transactionManager.resume(tx1);
184 try {
185 transactionManager.commit();
186 fail("Transaction should have failed, element has changed in the meantime!");
187 } catch (RollbackException e) {
188
189 }
190 transactionManager.begin();
191 assertNotNull(cache.get("key"));
192 assertEquals("newValue", cache.get("key").getValue());
193 transactionManager.commit();
194 }
195
196 @Test
197 public void testReplace() throws Exception {
198 transactionManager.begin();
199 assertEquals("Cache should be empty to start", 0, cache.getSize());
200 assertEquals("Cach1 should be empty to start", 0, cach1.getSize());
201 assertNull(cache.replace(new Element("blah", "someValue")));
202 cache.put(new Element("blah", "value"));
203 assertNotNull(cache.replace(new Element("blah", "someValue")));
204 transactionManager.commit();
205 transactionManager.begin();
206 assertNotNull(cache.get("blah"));
207 assertEquals("someValue", cache.get("blah").getValue());
208 transactionManager.commit();
209
210 transactionManager.begin();
211 cache.put(new Element("key", "value"));
212 transactionManager.commit();
213 transactionManager.begin();
214 cach1.put(new Element("random", "things"));
215 cache.replace(new Element("key", "newValue"));
216 Transaction tx1 = transactionManager.suspend();
217 transactionManager.begin();
218 cache.remove("key");
219 transactionManager.commit();
220 transactionManager.resume(tx1);
221 try {
222 transactionManager.commit();
223 fail("Transaction should have failed, element is deleted already");
224 } catch (RollbackException e) {
225
226 }
227 transactionManager.begin();
228 assertNull(cache.get("key"));
229 transactionManager.commit();
230
231 transactionManager.begin();
232 cache.put(new Element("key", "value"));
233 transactionManager.commit();
234 transactionManager.begin();
235 cach1.put(new Element("random", "things"));
236 cache.replace(new Element("key", "newValue"));
237 tx1 = transactionManager.suspend();
238 transactionManager.begin();
239 cache.put(new Element("key", "allNewValue"));
240 transactionManager.commit();
241 transactionManager.resume(tx1);
242 try {
243 transactionManager.commit();
244 fail("Transaction should have failed, element is deleted already");
245 } catch (RollbackException e) {
246
247 }
248 transactionManager.begin();
249 assertNotNull(cache.get("key"));
250 assertNotNull("allNewValue", cache.get("key").getValue());
251 transactionManager.commit();
252
253 transactionManager.begin();
254 cache.put(new Element("key", "value"));
255 transactionManager.commit();
256 transactionManager.begin();
257 cach1.put(new Element("random", "things"));
258 cache.replace(new Element("key", "newValue"));
259 tx1 = transactionManager.suspend();
260 transactionManager.begin();
261 cache.put(new Element("key", "allNewValue"));
262 transactionManager.commit();
263 transactionManager.resume(tx1);
264 try {
265 transactionManager.commit();
266 fail("Transaction should have failed, element value has changed");
267 } catch (RollbackException e) {
268
269 }
270 transactionManager.begin();
271 assertNotNull(cache.get("key"));
272 assertNotNull("allNewValue", cache.get("key").getValue());
273 transactionManager.commit();
274
275 transactionManager.begin();
276 cache.put(new Element("key", "value"));
277 transactionManager.commit();
278 transactionManager.begin();
279 cach1.put(new Element("random", "things"));
280 cache.replace(new Element("key", "value"));
281 tx1 = transactionManager.suspend();
282 transactionManager.begin();
283 cache.put(new Element("key", "newValue"));
284 transactionManager.commit();
285 transactionManager.resume(tx1);
286 try {
287 transactionManager.commit();
288 fail("Transaction should have failed, element has changed in the meantime!");
289 } catch (RollbackException e) {
290
291 }
292 transactionManager.begin();
293 assertNotNull(cache.get("key"));
294 assertEquals("newValue", cache.get("key").getValue());
295 transactionManager.commit();
296 }
297
298 @Test
299 public void testReplaceElement() throws Exception {
300 transactionManager.begin();
301 assertEquals("Cache should be empty to start", 0, cache.getSize());
302 assertEquals("Cach1 should be empty to start", 0, cach1.getSize());
303 assertFalse(cache.replace(new Element("blah", "someValue"), new Element("blah", "someOtherValue")));
304 cache.put(new Element("blah", "value"));
305 assertTrue(cache.replace(new Element("blah", "value"), new Element("blah", "someValue")));
306 transactionManager.commit();
307 transactionManager.begin();
308 assertNotNull(cache.get("blah"));
309 assertEquals("someValue", cache.get("blah").getValue());
310 transactionManager.commit();
311
312 transactionManager.begin();
313 assertEquals("someValue", cache.get("blah").getValue());
314 transactionManager.commit();
315
316 transactionManager.begin();
317 cache.put(new Element("key", "value"));
318 transactionManager.commit();
319 transactionManager.begin();
320 cach1.put(new Element("random", "things"));
321 cache.replace(new Element("key", "value"), new Element("key", "newValue"));
322 Transaction tx1 = transactionManager.suspend();
323 transactionManager.begin();
324 cache.remove("key");
325 transactionManager.commit();
326 transactionManager.resume(tx1);
327 try {
328 transactionManager.commit();
329 fail("Transaction should have failed, element is deleted already");
330 } catch (RollbackException e) {
331
332 }
333 transactionManager.begin();
334 assertNull(cache.get("key"));
335 transactionManager.commit();
336
337 transactionManager.begin();
338 cache.put(new Element("key", "value"));
339 transactionManager.commit();
340 transactionManager.begin();
341 cach1.put(new Element("random", "things"));
342 assertFalse(cache.replace(new Element("key", "wrongValue"), new Element("key", "newValue")));
343 assertTrue(cache.replace(new Element("key", "value"), new Element("key", "newValue")));
344 tx1 = transactionManager.suspend();
345 transactionManager.begin();
346 cache.put(new Element("key", "allNewValue"));
347 transactionManager.commit();
348 transactionManager.resume(tx1);
349 try {
350 transactionManager.commit();
351 fail("Transaction should have failed, element's value has changed");
352 } catch (RollbackException e) {
353
354 }
355 transactionManager.begin();
356 assertNotNull(cache.get("key"));
357 assertNotNull("allNewValue", cache.get("key").getValue());
358 transactionManager.commit();
359
360 transactionManager.begin();
361 cache.put(new Element("key", "value"));
362 transactionManager.commit();
363 transactionManager.begin();
364 cach1.put(new Element("random", "things"));
365 cache.replace(new Element("key", "value"), new Element("key", "newValue"));
366 tx1 = transactionManager.suspend();
367 transactionManager.begin();
368 cache.put(new Element("key", "allNewValue"));
369 transactionManager.commit();
370 transactionManager.resume(tx1);
371 try {
372 transactionManager.commit();
373 fail("Transaction should have failed, element is deleted already");
374 } catch (RollbackException e) {
375
376 }
377 transactionManager.begin();
378 assertNotNull(cache.get("key"));
379 assertNotNull("allNewValue", cache.get("key").getValue());
380 transactionManager.commit();
381
382 transactionManager.begin();
383 cache.put(new Element("key", "value"));
384 transactionManager.commit();
385 transactionManager.begin();
386 cach1.put(new Element("random", "things"));
387 cache.replace(new Element("key", "value"), new Element("key", "wrongValue"));
388 tx1 = transactionManager.suspend();
389 transactionManager.begin();
390 cache.put(new Element("key", "newValue"));
391 transactionManager.commit();
392 transactionManager.resume(tx1);
393 try {
394 transactionManager.commit();
395 fail("Transaction should have failed, element has changed in the meantime!");
396 } catch (RollbackException e) {
397
398 }
399 transactionManager.begin();
400 assertNotNull(cache.get("key"));
401 assertEquals("newValue", cache.get("key").getValue());
402 transactionManager.commit();
403 }
404 }