// If the MEP doesn't need the backchannel, and nor do we, we should signal it so that it
// can close off as soon as possible.
if (backchannelFree) {
TransportUtils.setResponseWritten(msgCtx, false);
RequestResponseTransport t = null;
t = (RequestResponseTransport) rmMsgCtx.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
if(t != null && RequestResponseTransportStatus.WAITING.equals(t.getStatus())) {
t.acknowledgeMessage(msgCtx);
}
}
}
// If this message matches the WSRM 1.0 pattern for an empty last message (e.g.
// the sender wanted to signal the last message, but didn't have an application
// message to send) then we direct it to the RMMessageReceiver.
//This is not done when LastMsg is a response - it is sent throuth the normal response flow.
if((Sandesha2Constants.SPEC_2005_02.Actions.ACTION_LAST_MESSAGE.equals(msgCtx.getWSAAction()) ||
Sandesha2Constants.SPEC_2005_02.Actions.SOAP_ACTION_LAST_MESSAGE.equals(msgCtx.getSoapAction())))
{
if (rmMsgCtx.getRelatesTo()==null) {
if (log.isDebugEnabled())
log.debug("SequenceProcessor::processReliableMessage, got WSRM 1.0 lastmessage");
msgCtx.getAxisOperation().setMessageReceiver(new RMMessageReceiver ());
}
}
// If the storage manager is implementing inOrder, or using transactional delivery
// then we should hand the message over to the invoker thread. If not, we can invoke
// it directly ourselves.
InvokerWorker worker = null;
if (SandeshaUtil.isInOrder(msgCtx)) {
String key = SandeshaUtil.getUUID(); // key to store the message.
InvokerBean invokerBean = new InvokerBean(key, msgNo, sequenceId);
ContextManager contextMgr = SandeshaUtil.getContextManager(configCtx);
if(contextMgr != null) invokerBean.setContext(contextMgr.storeContext());
boolean wasAdded = storageManager.getInvokerBeanMgr().insert(invokerBean);
// This will avoid performing application processing more than once.
rmMsgCtx.setProperty(Sandesha2Constants.APPLICATION_PROCESSING_DONE, "true");
// Whatever the MEP, we stop processing here and the invoker will do the real work. As we
// are taking responsibility for the message we need to return SUSPEND
result = InvocationResponse.SUSPEND;
if (wasAdded) {
storageManager.storeMessageContext(key, msgCtx);
// We can invoke the message immediately, if this is the next message to invoke,
// and we don't have a user transaction in play.
if(bean.getNextMsgNoToProcess() == msgNo && !storageManager.hasUserTransaction(msgCtx)) {
String workId = sequenceId;
ConfigurationContext context = msgCtx.getConfigurationContext();
worker = new InvokerWorker(context, invokerBean);
worker.setWorkId(workId);
// Actually take the lock
worker.getLock().addWork(workId, worker);
}
} else {
// Abort this message immediately as this message has already been added
sendAck = false;
result = InvocationResponse.ABORT;
RequestResponseTransport t = null;
t = (RequestResponseTransport) rmMsgCtx.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
// Tell the transport that there will be no response message
if(t != null && RequestResponseTransportStatus.WAITING.equals(t.getStatus())) {
TransportUtils.setResponseWritten(msgCtx, false);
t.acknowledgeMessage(msgCtx);
}
}
// if the relates to is not null then this is at the client side
// so it is receiving a response. We have to abort the thread in the Async case as
// we don't want too many threads open e.g. many async responses coming in at once all waiting
// for an earlier response which hasn't arrived. In the Sync case we need to suspend as aborting
// causes Axis to mark this msg as delivered and then when the invoker thread tries to deliver
// the msg Axis returns with a NullPointerException.
if (msgCtx.getRelatesTo() != null && msgCtx.getTo() != null && !msgCtx.getTo().hasAnonymousAddress()) {
result = InvocationResponse.ABORT;
if (log.isDebugEnabled())
log.debug("SequenceProcessor::processReliableMessage, Aborting the thread as this " +
"is an async response requiring inorder delivery. An invoker thread will process the delivery");
}
}
if (transaction != null && transaction.isActive())
transaction.commit();
if(worker != null) {
try {
worker.run();
} catch(Exception e) {
log.error("Caught exception running InvokerWorker", e);
}
}
if (sendAck) {
try {
transaction = storageManager.getTransaction();
RMMsgContext ackRMMsgContext = AcknowledgementManager.generateAckMessage(rmMsgCtx, bean, sequenceId, storageManager,true);
AcknowledgementManager.sendAckNow(ackRMMsgContext);
TransportUtils.setResponseWritten(msgCtx, true);
RequestResponseTransport t =
(RequestResponseTransport) rmMsgCtx.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
// Tell the transport that we have finished with the message as the response should have been
// written
if(t != null && RequestResponseTransportStatus.WAITING.equals(t.getStatus())) {
t.signalResponseReady();
}
if (transaction != null && transaction.isActive()) transaction.commit();
transaction = null;