if (handleStaticResource(request, response)) {
return;
}
// Not giving a specific mutex will synchronize on the continuation
// itself
Continuation cont = ContinuationSupport.getContinuation(request, null);
// If the continuation is not a retry
if (!cont.isPending()) {
// Create the exchange
exchange = createExchange(request);
// Put the exchange in a map so that we can later retrieve it
// We don't put the exchange on the request directly in case the JMS flow is involved
// because the exchange coming back may not be the same object as the one send.
exchanges.put(exchange.getExchangeId(), exchange);
// Put the exchange id on the request to be able to retrieve the exchange later
request.setAttribute(MessageExchange.class.getName(), exchange.getExchangeId());
// Put the continuation in a map under the exchange id key
locks.put(exchange.getExchangeId(), cont);
synchronized (cont) {
// Send the exchange
send(exchange);
if (logger.isDebugEnabled()) {
logger.debug("Suspending continuation for exchange: " + exchange.getExchangeId());
}
// Suspend the continuation for the configured timeout
// If a SelectConnector is used, the call to suspend will throw a RetryRequest exception
// else, the call will block until the continuation is resumed
long to = this.timeout;
if (to == 0) {
to = ((HttpComponent) getServiceUnit().getComponent()).getConfiguration().getConsumerProcessorSuspendTime();
}
boolean result = cont.suspend(to);
// The call has not thrown a RetryRequest, which means we don't use a SelectConnector
// and we must handle the exchange in this very method call.
// If result is false, the continuation has timed out.
// So get the exchange (in case the object has changed) and remove it from the map
exchange = exchanges.remove(exchange.getExchangeId());
// remove the exchange id from the request as we don't need it anymore
request.removeAttribute(MessageExchange.class.getName());
// If a timeout occurred, throw an exception that will be sent back to the HTTP client
// Whenever the exchange comes back, the process(MessageExchange) method will thrown an
// exception and the exchange will be set in an ERROR status
if (!result) {
// Remove the continuation from the map.
// This indicates the continuation has been fully processed
locks.remove(exchange.getExchangeId());
throw new Exception("Exchange timed out");
}
}
// The continuation is a retry.
// This happens when the SelectConnector is used and in two cases:
// * the continuation has been resumed because the exchange has been received
// * the continuation has timed out
} else {
synchronized (cont) {
// Get the exchange id from the request
String id = (String) request.getAttribute(MessageExchange.class.getName());
// Remove the continuation from the map, indicating it has been processed or timed out
locks.remove(id);
exchange = exchanges.remove(id);
request.removeAttribute(MessageExchange.class.getName());
// Check if this is a timeout
if (exchange == null) {
throw new IllegalStateException("Exchange not found");
}
if (!cont.isResumed()) {
throw new Exception("Exchange timed out: " + exchange.getExchangeId());
}
}
}
// At this point, we have received the exchange response,