EndpointReference toEPR = msgCtx.getTo();
MessageContext inMsg = null;
OperationContext op = msgCtx.getOperationContext();
RequestResponseTransport t = (RequestResponseTransport) msgCtx.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
if (t==null) {
if (op != null)
inMsg = op.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
if (inMsg != null)
t = (RequestResponseTransport) inMsg.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
}
// If we are anonymous, and this is not a makeConnection, then we must have a transport waiting
if((toEPR==null || toEPR.hasAnonymousAddress()) &&
(makeConnection == null || !makeConnection.booleanValue()) &&
(t == null || !t.getStatus().equals(RequestResponseTransportStatus.WAITING))) {
// Mark this sender bean so that we know that the transport is unavailable, if the
// bean is still stored.
SenderBean bean = senderBeanMgr.retrieve(senderBean.getMessageID());
if(bean != null && bean.isTransportAvailable()) {
bean.setTransportAvailable(false);
senderBeanMgr.update(bean);
}
// Commit the update
if(transaction != null && transaction.isActive()) transaction.commit();
transaction = null;
if (log.isDebugEnabled())
log.debug("Exit: SenderWorker::run, no response transport for anonymous message");
return;
}
int messageType = senderBean.getMessageType();
if (isAckPiggybackableMsgType(messageType)) {
// Commit the update
if(transaction != null && transaction.isActive()) transaction.commit();
transaction = storageManager.getTransaction();
// Piggyback ack messages based on the 'To' address of the message
AcknowledgementManager.piggybackAcksIfPresent(rmMsgCtx, storageManager);
}
if (transaction != null && transaction.isActive())
transaction.commit();
transaction = storageManager.getTransaction();
/*Removing the sending of AckRequested msgs as has performance impact.
It could be rewritten to send AckRequested headers infrequantly and
hence be less of a performance impact. Functionally it
may be required to interop with other implementations but until
the problem occurs it's best not to do it at all and keep performance
as optimal as possible
//If this is an application msg we need to add an ackRequest to the header
if(messageType == Sandesha2Constants.MessageTypes.APPLICATION){
//Add an ackRequest
RMSBean rmsBean = SandeshaUtil.getRMSBeanFromSequenceId(storageManager, senderBean.getSequenceID());
RMMsgCreator.addAckRequest(rmMsgCtx, senderBean.getSequenceID(), rmsBean);
if (transaction != null && transaction.isActive())
transaction.commit();
transaction = storageManager.getTransaction();
} */
//if this is a sync RM exchange protocol we always have to add an ack
boolean ackPresent = false;
Iterator it = rmMsgCtx.getSequenceAcknowledgements();
if (it.hasNext())
ackPresent = true;
if (!ackPresent && toEPR.hasAnonymousAddress()
&& rmMsgCtx.getMessageContext().isServerSide()
&&
(messageType==Sandesha2Constants.MessageTypes.APPLICATION ||
messageType==Sandesha2Constants.MessageTypes.UNKNOWN ||
messageType==Sandesha2Constants.MessageTypes.LAST_MESSAGE)) {
String inboundSequenceId = senderBean.getInboundSequenceId();
if (inboundSequenceId==null)
throw new SandeshaException ("InboundSequenceID is not set for the sequence:" + senderBean.getSequenceID());
RMDBean incomingSequenceBean = SandeshaUtil.getRMDBeanFromSequenceId(storageManager, inboundSequenceId);
if (incomingSequenceBean!=null)
RMMsgCreator.addAckMessage(rmMsgCtx, inboundSequenceId, incomingSequenceBean, false, true);
}
if (transaction != null && transaction.isActive())
transaction.commit();
transaction = storageManager.getTransaction();
senderBean = updateMessage(rmMsgCtx,senderBean,storageManager);
if (senderBean == null) {
if (log.isDebugEnabled())
log.debug("Exit: SenderWorker::run, !continueSending");
if(transaction != null && transaction.isActive()) {
transaction.rollback();
transaction = null;
}
return;
}
// Although not actually sent yet, update the send count to indicate an attempt
if (senderBean.isReSend()) {
senderBeanMgr.update(senderBean);
}
// sending the message
boolean successfullySent = false;
// No need to redecorate application messages ... only for rm protocol messages
if(Sandesha2Constants.MessageTypes.APPLICATION!=senderBean.getMessageType()){
//try to redecorate the EPR if necessary
if (log.isDebugEnabled())
log.debug("Redecorate EPR : " + msgCtx.getEnvelope().getHeader());
EndpointReference replyToEPR = msgCtx.getReplyTo();
if(replyToEPR!=null){
replyToEPR = SandeshaUtil.getEPRDecorator(msgCtx.getConfigurationContext()).decorateEndpointReference(replyToEPR);
msgCtx.setReplyTo(replyToEPR);
}
}
// have to commit the transaction before sending. This may
// get changed when WS-AT is available.
if(transaction != null) {
transaction.commit();
transaction = null;
}
boolean processResponseForFaults = false;
try {
InvocationResponse response = InvocationResponse.CONTINUE;
if(storageManager.requiresMessageSerialization()) {
if(msgCtx.isPaused()) {
if (log.isDebugEnabled())
log.debug("Resuming a send for message : " + msgCtx.getEnvelope().getHeader());
msgCtx.setPaused(false);
msgCtx.setProperty(MessageContext.CLIENT_API_NON_BLOCKING, Boolean.FALSE);
response = AxisEngine.resumeSend(msgCtx);
} else {
if (log.isDebugEnabled())
log.debug("Sending a message : " + msgCtx.getEnvelope().getHeader());
msgCtx.setProperty(MessageContext.CLIENT_API_NON_BLOCKING, Boolean.FALSE);
AxisEngine.send(msgCtx); // TODO check if this should return an invocation response
}
} else {
ArrayList<Handler> retransmittablePhases = (ArrayList<Handler>) msgCtx.getProperty(Sandesha2Constants.RETRANSMITTABLE_PHASES);
if (retransmittablePhases!=null) {
msgCtx.setExecutionChain(retransmittablePhases);
} else {
ArrayList<Handler> emptyExecutionChain = new ArrayList<Handler>();
msgCtx.setExecutionChain(emptyExecutionChain);
}
msgCtx.setCurrentHandlerIndex(0);
msgCtx.setCurrentPhaseIndex(0);
msgCtx.setPaused(false);
if (log.isDebugEnabled())
log.debug("Resuming a send for message : " + msgCtx.getEnvelope().getHeader());
msgCtx.setProperty(MessageContext.CLIENT_API_NON_BLOCKING, Boolean.FALSE);
response = AxisEngine.resumeSend(msgCtx);
}
if(log.isDebugEnabled()) log.debug("Engine resume returned " + response);
if(response != InvocationResponse.SUSPEND) {
if(t != null) {
if(log.isDebugEnabled()) log.debug("Signalling transport in " + t);
t.signalResponseReady();
}
}
successfullySent = true;