* This is a synchronous method which sends a message to a destination and blocks waiting for a
* reply.
*/
public String sendAndReceiveCAS(CAS aCAS, ProcessTrace pt) throws ResourceProcessException {
if (!running) {
throw new ResourceProcessException(new Exception("Uima EE Client Not In Running State"));
}
if (!serviceDelegate.isSynchronousAPI()) {
// Change the flag to indicate synchronous invocation.
// This info will be needed to handle Ping replies.
// Different code is used for handling PING replies for
// sync and async API.
serviceDelegate.setSynchronousAPI();
}
String casReferenceId = null;
// keep handle to CAS, we'll deserialize into this same CAS later
sendAndReceiveCAS = aCAS;
ThreadMonitor threadMonitor = null;
if (threadMonitorMap.containsKey(Thread.currentThread().getId())) {
threadMonitor = (ThreadMonitor) threadMonitorMap.get(Thread.currentThread().getId());
} else {
threadMonitor = new ThreadMonitor(Thread.currentThread().getId());
threadMonitorMap.put(Thread.currentThread().getId(), threadMonitor);
}
ClientRequest cachedRequest = produceNewClientRequestObject();
cachedRequest.setSynchronousInvocation();
// This is synchronous call, acquire and hold the semaphore before
// dispatching a CAS to a service. The semaphore will be released
// iff:
// a) reply is received (success or failure with exception)
// b) timeout occurs
// c) client is stopped
// Once the semaphore is acquired and the CAS is dispatched
// the thread will block in trying to acquire the semaphore again
// below.
if (threadMonitor != null && threadMonitor.getMonitor() != null) {
try {
threadMonitor.getMonitor().acquire();
} catch (InterruptedException e) {
}
}
try {
// send CAS. This call does not block. Instead we will block the sending thread below.
casReferenceId = sendCAS(aCAS, cachedRequest);
} catch( ResourceProcessException e) {
threadMonitor.getMonitor().release();
throw e;
}
if (threadMonitor != null && threadMonitor.getMonitor() != null) {
while (running) {
try {
// Block sending thread until a reply is received. The thread
// will be signaled either when a reply to the request just
// sent is received OR a Ping reply was received. The latter
// is necessary to allow handling of CASes delayed due to
// a timeout. A previous request timed out and the service
// state was changed to TIMEDOUT. While the service is in this
// state all sending threads add outstanding CASes to the list
// of CASes pending dispatch and each waits until the state
// of the service changes to OK. The state is changed to OK
// when the client receives a reply to a PING request. When
// the Ping reply comes, the client will signal this thread.
// The thread checks the list of CASes pending dispatch trying
// to find an entry that matches ID of the CAS previously
// delayed. If the CAS is found in the delayed list, it will
// be removed from the list and send to the service for
// processing. The 'wasSignaled' flag is only set when the
// CAS reply is received. Ping reply logic does not change
// this flag.
threadMonitor.getMonitor().acquire();
// Send thread was awoken by either process reply or ping reply
// If the service is in the ok state and the CAS is in the
// list of CASes pending dispatch, remove the CAS from the list
// and send it to the service.
if (cachedRequest.isTimeoutException() || cachedRequest.isProcessException()) {
// Handled outside of the while-loop below
break;
}
if (running && serviceDelegate.getState() == Delegate.OK_STATE
&& serviceDelegate.removeCasFromPendingDispatchList(casReferenceId)) {
sendCAS(aCAS, cachedRequest);
} else {
break; // done here, received a reply or the client is not running
}
} catch (InterruptedException e) {
} finally {
threadMonitor.getMonitor().release();
}
}
} // if
if (abort) {
throw new ResourceProcessException(new RuntimeException("Uima AS Client API Stopping"));
}
// check if timeout exception
if (cachedRequest.isTimeoutException()) {
throw new ResourceProcessException(new UimaASProcessCasTimeout());
}
// If a reply contains process exception, throw an exception and let the
// listener decide what happens next
if (cachedRequest.isProcessException()) {
throw new ResourceProcessException(cachedRequest.getException());
}
try {
// Process reply in the send thread
Message message = cachedRequest.getMessage();
if (message != null) {
deserializeAndCompleteProcessingReply(casReferenceId, message, cachedRequest, pt, false);
}
} catch (ResourceProcessException rpe) {
throw rpe;
} catch (Exception e) {
throw new ResourceProcessException(e);
}
return casReferenceId;
}