engine.onProducerInitialized();
// Wait for messages from application threads. The uima ee client engine
// will call doStop() which sets the global flag 'done' to true.
PendingMessage pm = null;
ClientRequest cacheEntry = null;
while (!done) {
// Remove the oldest message from the shared 'queue'
// // Wait for a new message
try {
pm = messageQueue.take();
} catch (InterruptedException e) {
}
if (done) {
break; // done in this loop
}
// Check if the request should be rejected. If the connection to the broker is invalid and the request
// is not GetMeta Ping, reject the request after the connection is made. The reject() method created
// an exception and notified client of the fact that the request could not continue. The ping is a
// special case that we dont reject even though the broker connection has been lost. It is allow to
// fall through and will be sent as soon as the connection is recovered.
boolean rejectRequest = reject(pm);
if ( !engine.running) {
break;
}
// blocks until the connection is re-established with a broker
engine.recoverSharedConnectionIfClosed();
// get the producer initialized from a valid connection
producer = getMessageProducer();
// Check if the request should be rejected. It would be the case if the connection was invalid and
// subsequently recovered. If it was invalid, we went through error handling and the request is stale.
if ( !rejectRequest && engine.running) {
if ( engine.serviceDelegate.isAwaitingPingReply() &&
pm.getMessageType() == AsynchAEMessage.GetMeta ){
if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.INFO)) {
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.INFO, getClass().getName(),
"run", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
"UIMAJMS_client_dispatching_getmeta_ping__INFO", new Object[] { });
}
}
try {
// Request JMS Message from the concrete implementation
Message message = null;
// Determine if this a CAS Process Request
boolean casProcessRequest = isProcessRequest(pm);
// Only Process request can be serialized as binary
if (casProcessRequest && engine.getSerializationStrategy().equals("binary")) {
message = createBytesMessage();
} else {
message = createTextMessage();
}
initializeMessage(pm, message);
if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
UIMAFramework.getLogger(CLASS_NAME).logrb(
Level.FINE,
CLASS_NAME.getName(),
"run",
JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
"UIMAJMS_sending_msg_to_endpoint__FINE",
new Object[] {
UimaMessageValidator.decodeIntToString(AsynchAEMessage.Command, message
.getIntProperty(AsynchAEMessage.Command)),
UimaMessageValidator.decodeIntToString(AsynchAEMessage.MessageType, message
.getIntProperty(AsynchAEMessage.MessageType)), destination });
}
if (casProcessRequest) {
cacheEntry = (ClientRequest) engine.getCache().get(
pm.get(AsynchAEMessage.CasReference));
if (cacheEntry != null) {
CAS cas = cacheEntry.getCAS();
// Use Process Timeout value for the time-to-live property in the
// outgoing JMS message. When this time is exceeded
// while the message sits in a queue, the JMS Server will remove it from
// the queue. What happens with the expired message depends on the
// configuration. Most JMS Providers create a special dead-letter queue
// where all expired messages are placed. NOTE: In ActiveMQ expired msgs in the DLQ
// are not auto evicted yet and accumulate taking up memory.
long timeoutValue = cacheEntry.getProcessTimeout();
if (timeoutValue > 0 && addTimeToLive ) {
// Set high time to live value
message.setJMSExpiration(10 * timeoutValue);
}
if (pm.getMessageType() == AsynchAEMessage.Process) {
cacheEntry.setCASDepartureTime(System.nanoTime());
}
cacheEntry.setCASDepartureTime(System.nanoTime());
UimaASProcessStatus status = new UimaASProcessStatusImpl(new ProcessTrace_impl(),cacheEntry.getCAS(),
cacheEntry.getCasReferenceId());
// Notify engine before sending a message
if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
UIMAFramework.getLogger(CLASS_NAME).logrb(
Level.FINE,
CLASS_NAME.getName(),
"run",
JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
"UIMAJMS_calling_onBeforeMessageSend__FINE",
new Object[] {
pm.get(AsynchAEMessage.CasReference),
String.valueOf(cas.hashCode())
});
}
engine.onBeforeMessageSend(status);
} else {
if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.WARNING)) {
UIMAFramework.getLogger(CLASS_NAME).logrb(
Level.WARNING,
CLASS_NAME.getName(),
"run",
JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
"UIMAJMS_failed_cache_lookup__WARNING",
new Object[] {
pm.get(AsynchAEMessage.CasReference),
UimaMessageValidator.decodeIntToString(AsynchAEMessage.Command, message
.getIntProperty(AsynchAEMessage.Command)),
UimaMessageValidator.decodeIntToString(AsynchAEMessage.MessageType, message
.getIntProperty(AsynchAEMessage.MessageType)), destination });
}
}
}
// start timers
if( casProcessRequest ) {
CAS cas = cacheEntry.getCAS();
// Add the cas to a list of CASes pending reply. Also start the timer if necessary
engine.serviceDelegate.addCasToOutstandingList(cacheEntry.getCasReferenceId(), cas.hashCode());
if (UIMAFramework.getLogger(CLASS_NAME).isLoggable(Level.FINE)) {
UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(),
"sendCAS", JmsConstants.JMS_LOG_RESOURCE_BUNDLE,
"UIMAJMS_cas_added_to_pending_FINE", new Object[] { cacheEntry.getCasReferenceId(), String.valueOf(cas.hashCode()), engine.serviceDelegate.toString()});
}
} else if ( pm.getMessageType() == AsynchAEMessage.GetMeta &&
engine.serviceDelegate.getGetMetaTimeout() > 0 ) {
// timer for PING has been started in sendCAS()
if ( !engine.serviceDelegate.isAwaitingPingReply()) {
engine.serviceDelegate.startGetMetaRequestTimer();
}