001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.routeheader;
018:
019: import org.junit.Test;
020: import org.kuali.rice.config.Config;
021: import org.kuali.rice.core.Core;
022: import org.kuali.workflow.test.WorkflowTestCase;
023: import org.springframework.transaction.TransactionStatus;
024: import org.springframework.transaction.support.TransactionCallback;
025:
026: import edu.iu.uis.eden.KEWServiceLocator;
027: import edu.iu.uis.eden.clientapp.WorkflowDocument;
028: import edu.iu.uis.eden.clientapp.vo.NetworkIdVO;
029: import edu.iu.uis.eden.exception.LockingException;
030:
031: public class RouteHeaderServiceTest extends WorkflowTestCase {
032:
033: private Object lock = new Object();
034: private RouteHeaderService routeHeaderService;
035:
036: protected void setUpTransaction() throws Exception {
037: super .setUpTransaction();
038: routeHeaderService = KEWServiceLocator.getRouteHeaderService();
039: }
040:
041: @Test
042: public void testGetMessageEntityByDocumentId() throws Exception {
043: WorkflowDocument document = new WorkflowDocument(
044: new NetworkIdVO("ewestfal"), "TestDocumentType2");
045: Long documentId = document.getRouteHeaderId();
046: String messageEntity = routeHeaderService
047: .getMessageEntityByDocumentId(documentId);
048: assertEquals("Message entity should be KEWNEW", "KEWNEW",
049: messageEntity);
050:
051: // now check TestDocumentType
052: document = new WorkflowDocument(new NetworkIdVO("ewestfal"),
053: "TestDocumentType");
054: documentId = document.getRouteHeaderId();
055: messageEntity = routeHeaderService
056: .getMessageEntityByDocumentId(documentId);
057: assertEquals("Message entity should be KEW", "KEW",
058: messageEntity);
059: }
060:
061: @Test
062: public void testLockRouteHeader() throws Exception {
063: if (Core.getRootConfig().getProperty("datasource.ojb.platform")
064: .equals("Mckoi")) {
065: return;
066: }
067:
068: WorkflowDocument document = new WorkflowDocument(
069: new NetworkIdVO("rkirkend"), "TestDocumentType");
070: document.saveRoutingData();
071: final Long documentId = document.getRouteHeaderId();
072: Locker locker = null;
073: synchronized (lock) {
074: locker = new Locker(documentId);
075: locker.start();
076: lock.wait();
077: }
078: // document should be locked by the other thread at this point
079: try {
080: routeHeaderService.lockRouteHeader(documentId, false);
081: fail("The route header should be locked.");
082: } catch (LockingException e) {
083: // should have been thrown!
084: }
085: synchronized (lock) {
086: lock.notify();
087: }
088: locker.join();
089: // document should be unlocked now
090: routeHeaderService.lockRouteHeader(documentId, false);
091: assertTrue("Locker thread should have completed.", locker
092: .isCompleted());
093:
094: // now configure a lock timeout for 2 seconds
095: Core.getCurrentContextConfig().overrideProperty(
096: Config.DOCUMENT_LOCK_TIMEOUT, "2");
097: synchronized (lock) {
098: locker = new Locker(documentId);
099: locker.start();
100: lock.wait();
101: }
102: // document should be locked by the other thread at this point
103: long millisStart = System.currentTimeMillis();
104: try {
105: routeHeaderService.lockRouteHeader(documentId, true);
106: fail("The route header should be locked.");
107: } catch (LockingException e) {
108: // should have been thrown!
109: }
110: long millisEnd = System.currentTimeMillis();
111: long timeLocked = (millisEnd - millisStart);
112: // assert that the time locked was close to 2 seconds += .25 of a second
113: assertTrue(
114: "Time locked should have been around 2 seconds but was "
115: + timeLocked, timeLocked > (2000 - 250)
116: && timeLocked < (2000 + 250));
117:
118: synchronized (lock) {
119: lock.notify();
120: }
121: locker.join();
122:
123: // document should be unlocked again
124: routeHeaderService.lockRouteHeader(document.getRouteHeaderId(),
125: false);
126: assertTrue("Locker thread should have completed.", locker
127: .isCompleted());
128: }
129:
130: private class Locker extends Thread {
131: private Long documentId;
132: private boolean isCompleted = false;
133:
134: public Locker(Long documentId) {
135: this .documentId = documentId;
136: }
137:
138: public void run() {
139: getTransactionTemplate().execute(new TransactionCallback() {
140: public Object doInTransaction(TransactionStatus status) {
141: synchronized (lock) {
142: routeHeaderService.lockRouteHeader(documentId,
143: true);
144: try {
145: lock.notify();
146: lock.wait();
147: } catch (InterruptedException e) {
148: fail("Shouldn't have been interrupted");
149: }
150: }
151: return null;
152: }
153: });
154: isCompleted = true;
155: }
156:
157: public boolean isCompleted() {
158: return isCompleted;
159: }
160: }
161:
162: }
|