001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049:
050: /*
051: * ConcurrencyTest.java
052: *
053: * Created on April 1, 2002, 5:47 PM
054: */
055:
056: package org.jaffa.persistence.blackboxtests;
057:
058: import java.util.*;
059: import junit.framework.TestCase;
060: import org.jaffa.persistence.*;
061: import org.jaffa.persistence.exceptions.*;
062: import org.jaffa.persistence.domainobjects.*;
063:
064: /**
065: *
066: * @author GautamJ
067: * @version
068: */
069: public class ConcurrencyTest extends TestCase {
070: int m_succesfulUowCreationCounter;
071:
072: /** Creates new QueryTest */
073: public ConcurrencyTest(String name) {
074: super (name);
075: }
076:
077: /** This test will create 50 UOW objects concurrently. The test fails, if any exception is raised.
078: */
079: public void testConcurrentUowCreation() {
080: m_succesfulUowCreationCounter = 0;
081: int threadLimit = 50;
082: ThreadGroup tg = new ThreadGroup(""
083: + (new java.util.Date()).getTime());
084: try {
085: for (int i = 0; i < threadLimit; i++) {
086: Thread t = new Thread(tg, new UowCreationThread());
087: t.start();
088: }
089: } finally {
090: try {
091: //while (tg.activeCount() > 0) { *** this doesn't work ***
092: while (tg.activeCount() > 1)
093: Thread.sleep(100);
094: } catch (InterruptedException e) {
095: e.printStackTrace();
096: fail("Error in thread execution");
097: }
098: if (m_succesfulUowCreationCounter != threadLimit)
099: fail(m_succesfulUowCreationCounter
100: + " UOW object(s) were created out of the expected "
101: + threadLimit);
102: }
103: }
104:
105: private synchronized void incrementSuccesfulUowCreationCounter() {
106: ++m_succesfulUowCreationCounter;
107: }
108:
109: private class UowCreationThread implements Runnable {
110: /** This will create a UOW object and then perform a rollback on it.
111: * It will update the SuccesfulUowCreationCounter on the calling class, if everything goes smoothly.
112: */
113: public void run() {
114: try {
115: UOW uow = new UOW();
116: uow.rollback();
117: incrementSuccesfulUowCreationCounter();
118: } catch (Exception e) {
119: e.printStackTrace();
120: }
121: }
122: }
123:
124: /** This is a test for Optimistic locking.
125: * It will retrieve the condition 'Z-TESTSYCD-01' in Optimistic locking-mode and modify a field. The condition will remain unlocked.
126: * It'll then retrieve the same condition in another UOW, but in Paranoid locking mode. The other UOW should obtain a lock on the condition object.
127: * It'll then try to retrieve the same condition in another UOW, but in Pessimistic locking mode. It should be possible to modify it.
128: * Finally retrieve the same object in another UOW in Optimistic locking mode and try to update it. It should be possible to modify it.
129: * Note: In the case of Optimistic locking, a lock is acquired on the object only when the UOW is commited.
130: */
131: public void testOptimisticLocking() {
132: UOW uow1 = null;
133: UOW uow2 = null;
134: try {
135: // Retrieve the condition in 'Optimistic' locking-mode and modify a field
136: // The object should remain un-locked
137: uow1 = new UOW();
138: Criteria c = new Criteria();
139: c.setTable(ConditionMeta.getName());
140: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
141: // The following is optional, since the Optimistic locking is the default
142: c.setLocking(Criteria.LOCKING_OPTIMISTIC);
143: Iterator i = uow1.query(c).iterator();
144: assertTrue("Condition not retrieved", i.hasNext());
145: Condition condition1 = (Condition) i.next();
146: assertTrue("Only one Condition should have been retrieved",
147: !i.hasNext());
148: assertTrue(
149: "Condition should not have been locked because we doing Optimistic locking",
150: !condition1.isLocked());
151: condition1
152: .setDescription(condition1.getDescription() + 'Z');
153: assertTrue(
154: "Condition should not have been locked because we doing Optimistic locking",
155: !condition1.isLocked());
156:
157: // Now try to retrieve the same condition in another UOW
158: // It should be possible to get it in 'Paranoid' locking-mode, since the object was not locked in the 1st UOW
159: uow2 = new UOW();
160: c = new Criteria();
161: c.setTable(ConditionMeta.getName());
162: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
163: c.setLocking(Criteria.LOCKING_PARANOID);
164: i = uow2.query(c).iterator();
165: assertTrue("Condition not retrieved", i.hasNext());
166: Condition condition2 = (Condition) i.next();
167: assertTrue("Only one Condition should have been retrieved",
168: !i.hasNext());
169: assertTrue(
170: "Condition should have been locked because we are doing Paranoid locking",
171: condition2.isLocked());
172: uow2.rollback();
173:
174: // Now retrieve the same object in Pessimistic locking-mode. It should be possible to modify the field and acquire a lock
175: uow2 = new UOW();
176: c = new Criteria();
177: c.setTable(ConditionMeta.getName());
178: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
179: c.setLocking(Criteria.LOCKING_PESSIMISTIC);
180: i = uow2.query(c).iterator();
181: assertTrue("Condition not retrieved", i.hasNext());
182: condition2 = (Condition) i.next();
183: assertTrue("Only one Condition should have been retrieved",
184: !i.hasNext());
185: assertTrue(
186: "Condition should not have been initially locked because we doing Pessimistic locking",
187: !condition2.isLocked());
188: condition2
189: .setDescription(condition2.getDescription() + "Z");
190: assertTrue(
191: "Condition should have been locked because we are doing Pessimistic locking",
192: condition2.isLocked());
193: uow2.rollback();
194:
195: // Now retrieve the same object in Optimitsic locking-mode. It should be possible to update the object
196: uow2 = new UOW();
197: c = new Criteria();
198: c.setTable(ConditionMeta.getName());
199: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
200: i = uow2.query(c).iterator();
201: assertTrue("Condition not retrieved", i.hasNext());
202: condition2 = (Condition) i.next();
203: assertTrue("Only one Condition should have been retrieved",
204: !i.hasNext());
205: assertTrue(
206: "Condition should not have been initially locked because we doing Optimistic locking",
207: !condition2.isLocked());
208: condition2
209: .setDescription(condition2.getDescription() + "Z");
210: uow2.update(condition2);
211: uow2.commit();
212:
213: } catch (Exception e) {
214: e.printStackTrace();
215: fail(e.getMessage());
216: } finally {
217: try {
218: if (uow1 != null)
219: uow1.rollback();
220: } catch (Exception e) {
221: e.printStackTrace();
222: }
223: try {
224: if (uow2 != null)
225: uow2.rollback();
226: } catch (Exception e) {
227: e.printStackTrace();
228: }
229: }
230: }
231:
232: /** This is a test for Pessimistic locking.
233: * It will retrieve the condition 'Z-TESTSYCD-01' in Pessimistic locking-mode and modify a field. The condition will get locked.
234: * It'll then try to retrieve the same condition in another UOW, but in Paranoid locking mode. The retrieve should fail, since the object has been locked by the 1st UOW
235: * It'll then try to retrieve the same condition in another UOW, but in Pessimistic locking mode. The retrieve will work, but it'll not be possible to modify it, since the object has been locked by the 1st UOW
236: * Finally retrieve the same object in another UOW in Optimistic locking mode and try to update it. The update will fail.
237: * Note: In the case of Pessimistic locking, a lock is acquired on the object when any field is updated.
238: */
239: public void testPessimisticLocking() {
240: UOW uow1 = null;
241: UOW uow2 = null;
242: try {
243: // Retrieve the condition in 'Pessimistic' locking-mode and modify a field
244: // The object should get locked
245: uow1 = new UOW();
246: Criteria c = new Criteria();
247: c.setTable(ConditionMeta.getName());
248: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
249: c.setLocking(Criteria.LOCKING_PESSIMISTIC);
250: Iterator i = uow1.query(c).iterator();
251: assertTrue("Condition not retrieved", i.hasNext());
252: Condition condition1 = (Condition) i.next();
253: assertTrue("Only one Condition should have been retrieved",
254: !i.hasNext());
255: assertTrue(
256: "Condition should not have been initially locked because we doing Pessimistic locking",
257: !condition1.isLocked());
258: condition1
259: .setDescription(condition1.getDescription() + 'Z');
260: assertTrue(
261: "Condition should have been locked because we doing Pessimistic locking",
262: condition1.isLocked());
263:
264: // Now try to retrieve the same condition in another UOW
265: // It should not be possible to get it in 'Paranoid' locking-mode, since the object was not locked in the 1st UOW
266: uow2 = new UOW();
267: c = new Criteria();
268: c.setTable(ConditionMeta.getName());
269: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
270: c.setLocking(Criteria.LOCKING_PARANOID);
271: try {
272: uow2.query(c).iterator();
273: fail("We expected a QueryFailedException to be raised while trying to obtain a lock on an already locked object");
274: } catch (QueryFailedException e) {
275: // An exception is expected to be raised
276: }
277:
278: // Now retrieve the same object in Pessimistic locking-mode and try to modify a field
279: // An exception should be raised while trying to modify the field
280: c = new Criteria();
281: c.setTable(ConditionMeta.getName());
282: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
283: c.setLocking(Criteria.LOCKING_PESSIMISTIC);
284: i = uow2.query(c).iterator();
285: assertTrue("Condition not retrieved", i.hasNext());
286: Condition condition2 = (Condition) i.next();
287: assertTrue("Only one Condition should have been retrieved",
288: !i.hasNext());
289: assertTrue(
290: "Condition should not have been initially locked because we doing Pessimistic locking",
291: !condition2.isLocked());
292: try {
293: condition2.setDescription(condition2.getDescription()
294: + "Z");
295: fail("We expected an AlreadyLockedObjectException to be raised while trying to modify an already locked object");
296: } catch (AlreadyLockedObjectException e) {
297: // An exception is expected to be raised
298: }
299:
300: // Now retrieve the same object in Optimitsic locking-mode and try to modify a field
301: // An exception should be raised when updating the object
302: c = new Criteria();
303: c.setTable(ConditionMeta.getName());
304: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
305: i = uow2.query(c).iterator();
306: assertTrue("Condition not retrieved", i.hasNext());
307: condition2 = (Condition) i.next();
308: assertTrue("Only one Condition should have been retrieved",
309: !i.hasNext());
310: assertTrue(
311: "Condition should not have been initially locked because we doing Optimistic locking",
312: !condition2.isLocked());
313: condition2
314: .setDescription(condition2.getDescription() + "Z");
315: try {
316: // Update the record by firing the commit
317: uow2.update(condition2);
318: uow2.commit();
319: fail("We expected an AlreadyLockedObjectException to be raised while trying to update an already locked object");
320: } catch (CommitFailedException e) {
321: // An exception is expected to be raised
322: if (e.getCause() == null
323: || !(e.getCause() instanceof AlreadyLockedObjectException)) {
324: e.printStackTrace();
325: this
326: .fail("We expected an AlreadyLockedObjectException to be raised while trying to update an already locked object");
327: }
328: }
329:
330: } catch (Exception e) {
331: e.printStackTrace();
332: fail(e.getMessage());
333: } finally {
334: try {
335: if (uow1 != null)
336: uow1.rollback();
337: } catch (Exception e) {
338: e.printStackTrace();
339: }
340: try {
341: if (uow2 != null)
342: uow2.rollback();
343: } catch (Exception e) {
344: e.printStackTrace();
345: }
346: }
347: }
348:
349: /** This is a test for Paranoid locking.
350: * It will retrieve the condition 'Z-TESTSYCD-01' in Paranoid locking-mode. The condition will get locked.
351: * It'll then try to retrieve the same condition in another UOW, in Paranoid locking mode. The retrieve should fail, since the object has been locked by the 1st UOW
352: * It'll then try to retrieve the same condition in another UOW, but in Pessimistic locking mode. The retrieve will work, but it'll not be possible to modify it, since the object has been locked by the 1st UOW
353: * Finally retrieve the same object in another UOW in Optimistic locking mode and try to update it. The update will fail.
354: * Note: In the case of Paranoid locking, a lock is acquired on the object when retrieving it.
355: */
356: public void testParanoidLocking() {
357: UOW uow1 = null;
358: UOW uow2 = null;
359: try {
360: // Retrieve the condition in 'Paranoid' locking-mode
361: // The object should get locked
362: uow1 = new UOW();
363: Criteria c = new Criteria();
364: c.setTable(ConditionMeta.getName());
365: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
366: c.setLocking(Criteria.LOCKING_PARANOID);
367: Iterator i = uow1.query(c).iterator();
368: assertTrue("Condition not retrieved", i.hasNext());
369: Condition condition1 = (Condition) i.next();
370: assertTrue("Only one Condition should have been retrieved",
371: !i.hasNext());
372: assertTrue(
373: "Condition should have been locked because we are doing Paranoid locking",
374: condition1.isLocked());
375:
376: // Now try to retrieve the same condition in another UOW
377: // It should not be possible to get it in 'Paranoid' locking-mode, since the object was not locked in the 1st UOW
378: uow2 = new UOW();
379: c = new Criteria();
380: c.setTable(ConditionMeta.getName());
381: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
382: c.setLocking(Criteria.LOCKING_PARANOID);
383: try {
384: uow2.query(c).iterator();
385: fail("We expected a QueryFailedException to be raised while trying to obtain a lock on an already locked object");
386: } catch (QueryFailedException e) {
387: // An exception is expected to be raised
388: }
389:
390: // Now retrieve the same object in Pessimistic locking-mode and try to modify a field
391: // An exception should be raised while trying to modify the field
392: c = new Criteria();
393: c.setTable(ConditionMeta.getName());
394: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
395: c.setLocking(Criteria.LOCKING_PESSIMISTIC);
396: i = uow2.query(c).iterator();
397: assertTrue("Condition not retrieved", i.hasNext());
398: Condition condition2 = (Condition) i.next();
399: assertTrue("Only one Condition should have been retrieved",
400: !i.hasNext());
401: assertTrue(
402: "Condition should not have been initially locked because we doing Pessimistic locking",
403: !condition2.isLocked());
404: try {
405: condition2.setDescription(condition2.getDescription()
406: + "Z");
407: fail("We expected an AlreadyLockedObjectException to be raised while trying to modify an already locked object");
408: } catch (AlreadyLockedObjectException e) {
409: // An exception is expected to be raised
410: }
411:
412: // Now retrieve the same object in Optimitsic locking-mode and try to modify a field
413: // An exception should be raised when updating the object
414: c = new Criteria();
415: c.setTable(ConditionMeta.getName());
416: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
417: i = uow2.query(c).iterator();
418: assertTrue("Condition not retrieved", i.hasNext());
419: condition2 = (Condition) i.next();
420: assertTrue("Only one Condition should have been retrieved",
421: !i.hasNext());
422: assertTrue(
423: "Condition should not have been initially locked because we doing Optimistic locking",
424: !condition2.isLocked());
425: condition2
426: .setDescription(condition2.getDescription() + "Z");
427: try {
428: // Update the record by firing the commit
429: uow2.update(condition2);
430: uow2.commit();
431: fail("We expected an AlreadyLockedObjectException to be raised while trying to update an already locked object");
432: } catch (CommitFailedException e) {
433: // An exception is expected to be raised
434: if (e.getCause() == null
435: || !(e.getCause() instanceof AlreadyLockedObjectException)) {
436: e.printStackTrace();
437: this
438: .fail("We expected an AlreadyLockedObjectException to be raised while trying to update an already locked object");
439: }
440: }
441:
442: } catch (Exception e) {
443: e.printStackTrace();
444: fail(e.getMessage());
445: } finally {
446: try {
447: if (uow1 != null)
448: uow1.rollback();
449: } catch (Exception e) {
450: e.printStackTrace();
451: }
452: try {
453: if (uow2 != null)
454: uow2.rollback();
455: } catch (Exception e) {
456: e.printStackTrace();
457: }
458: }
459: }
460:
461: /** This is a test for ReadOnly locking.
462: * It will retrieve the condition 'Z-TESTSYCD-01' in ReadOnly mode.
463: * An exception should be raised while trying to update any of its fields.
464: */
465: public void testReadOnlyLocking() {
466: UOW uow = null;
467: try {
468: // Retrieve the condition in 'ReadOnly' locking-mode
469: uow = new UOW();
470: Criteria c = new Criteria();
471: c.setTable(ConditionMeta.getName());
472: c.addCriteria(ConditionMeta.CONDITION, "Z-TESTSYCD-01");
473: c.setLocking(Criteria.LOCKING_READ_ONLY);
474: Iterator i = uow.query(c).iterator();
475: assertTrue("Condition not retrieved", i.hasNext());
476: Condition condition = (Condition) i.next();
477: assertTrue("Only one Condition should have been retrieved",
478: !i.hasNext());
479: assertTrue(
480: "Condition should not have been locked because we doing ReadOnly locking",
481: !condition.isLocked());
482:
483: // A ReadOnlyObjectException is expected to be thrown when modifying the condition
484: try {
485: condition
486: .setDescription(condition.getDescription() + 'Z');
487: fail("We expected an ReadOnlyObjectException to be raised while trying to update ReadOnly object");
488: } catch (ReadOnlyObjectException e) {
489: // An exception is expected to be raised
490: }
491:
492: } catch (Exception e) {
493: e.printStackTrace();
494: fail(e.getMessage());
495: } finally {
496: try {
497: if (uow != null)
498: uow.rollback();
499: } catch (Exception e) {
500: e.printStackTrace();
501: }
502: }
503: }
504: }
|