transaction = storageManager.getTransaction();
String key = senderBean.getMessageContextRefKey();
MessageContext msgCtx = null;
RMMsgContext rmMsgCtx = null;
if(messageToSend != null) {
msgCtx = messageToSend.getMessageContext();
rmMsgCtx = messageToSend;
} else {
msgCtx = storageManager.retrieveMessageContext(key, configurationContext);
if (msgCtx == null) {
// This sender bean has already been processed
return;
}
rmMsgCtx = MsgInitializer.initializeMessage(msgCtx);
}
// sender will not send the message if following property is
// set and not true.
// But it will set if it is not set (null)
// This is used to make sure that the mesage get passed the
// Sandesha2TransportSender.
String qualifiedForSending = (String) msgCtx.getProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING);
if (qualifiedForSending != null && !qualifiedForSending.equals(Sandesha2Constants.VALUE_TRUE)) {
if (log.isDebugEnabled())
log.debug("Exit: SenderWorker::run, !qualified for sending");
return;
}
if (msgCtx == null) {
if (log.isDebugEnabled())
log.debug(SandeshaMessageHelper.getMessage(SandeshaMessageKeys.sendHasUnavailableMsgEntry));
return;
}
// operation is the lowest level Sandesha2 should be attached
ArrayList msgsNotToSend = SandeshaUtil.getPropertyBean(msgCtx.getAxisOperation()).getMsgTypesToDrop();
if (msgsNotToSend != null && msgsNotToSend.contains(new Integer(rmMsgCtx.getMessageType()))) {
if (log.isDebugEnabled())
log.debug("Exit: SenderWorker::run, message type to be dropped " + rmMsgCtx.getMessageType());
return;
}
// If we are sending to the anonymous URI then we _must_ have a transport waiting,
// or the message can't go anywhere. If there is nothing here then we leave the
// message in the sender queue, and a MakeConnection (or a retransmitted request)
// will hopefully pick it up soon.
Boolean makeConnection = (Boolean) msgCtx.getProperty(Sandesha2Constants.MAKE_CONNECTION_RESPONSE);
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;
}
boolean continueSending = updateMessage(rmMsgCtx,senderBean,storageManager);
if (!continueSending) {
if (log.isDebugEnabled())
log.debug("Exit: SenderWorker::run, !continueSending");
return;
}
int messageType = senderBean.getMessageType();
if (isAckPiggybackableMsgType(messageType)) {
// Piggyback ack messages based on the 'To' address of the message
AcknowledgementManager.piggybackAcksIfPresent(rmMsgCtx, storageManager);
}
// sending the message
boolean successfullySent = false;
// Although not actually sent yet, update the send count to indicate an attempt
if (senderBean.isReSend()) {
SenderBean bean2 = senderBeanMgr.retrieve(senderBean.getMessageID());
if (bean2 != null) {
bean2.setSentCount(senderBean.getSentCount());
senderBeanMgr.update(bean2);
}
}
// have to commit the transaction before sending. This may
// get changed when WS-AT is available.
if(transaction != null) {
transaction.commit();
transaction = null;
}
msgCtx.getOptions().setTimeOutInMilliSeconds(1000000);
try {
AxisEngine engine = new AxisEngine (msgCtx.getConfigurationContext());
InvocationResponse response = InvocationResponse.CONTINUE;
SandeshaPolicyBean policy = SandeshaUtil.getPropertyBean(msgCtx.getAxisOperation());
if(policy.isUseMessageSerialization()) {
if(msgCtx.isPaused()) {
if (log.isDebugEnabled())
log.debug("Resuming a send for message : " + msgCtx.getEnvelope().getHeader());
msgCtx.setPaused(false);
msgCtx.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, Boolean.FALSE);
response = engine.resumeSend(msgCtx);
} else {
if (log.isDebugEnabled())
log.debug("Sending a message : " + msgCtx.getEnvelope().getHeader());
msgCtx.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, Boolean.FALSE);
engine.send(msgCtx); // TODO check if this should return an invocation response
}
} else {
// had to fully build the SOAP envelope to support
// retransmissions.
// Otherwise a 'parserAlreadyAccessed' exception could
// get thrown in retransmissions.
// But this has a performance reduction.
msgCtx.getEnvelope().build();
ArrayList retransmittablePhases = (ArrayList) msgCtx.getProperty(Sandesha2Constants.RETRANSMITTABLE_PHASES);
if (retransmittablePhases!=null) {
msgCtx.setExecutionChain(retransmittablePhases);
} else {
ArrayList emptyExecutionChain = new ArrayList ();
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());
response = engine.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;
} catch (Exception e) {
String message = SandeshaMessageHelper.getMessage(
SandeshaMessageKeys.sendMsgError, e.toString());
if (log.isErrorEnabled())
log.error(message, e);
// Store the Exception as a sequence property to enable the client to lookup the last
// exception time and timestamp.
try
{
// Create a new Transaction
transaction = storageManager.getTransaction();
// Get the internal sequence id from the context
String internalSequenceId = (String)rmMsgCtx.getProperty(Sandesha2Constants.MessageContextProperties.INTERNAL_SEQUENCE_ID);
RMSBean bean = SandeshaUtil.getRMSBeanFromInternalSequenceId(storageManager, internalSequenceId);
if (bean != null) {
bean.setLastSendError(e);
bean.setLastSendErrorTimestamp(System.currentTimeMillis());
}
// Update the RMSBean
storageManager.getRMSBeanMgr().update(bean);
// Commit the properties
if(transaction != null) {
transaction.commit();
transaction = null;
}
}
catch (Exception e1)
{
if (log.isErrorEnabled())
log.error(e1);
} finally {
if (transaction != null) {
transaction.rollback();
transaction = null;
}
}
}
// Establish the transaction for post-send processing
transaction = storageManager.getTransaction();
// update or delete only if the object is still present.
SenderBean bean1 = senderBeanMgr
.retrieve(senderBean.getMessageID());
if (bean1 != null) {
if (senderBean.isReSend()) {
bean1.setTimeToSend(senderBean.getTimeToSend());
senderBeanMgr.update(bean1);
} else {
senderBeanMgr.delete(bean1.getMessageID());
// removing the message from the storage.
String messageStoredKey = bean1.getMessageContextRefKey();
storageManager.removeMessageContext(messageStoredKey);
}
}
// Commit the transaction to release the SenderBean
if (transaction!=null)
transaction.commit();
transaction = null;
if (successfullySent && !msgCtx.isServerSide())
checkForSyncResponses(msgCtx);
if ((rmMsgCtx.getMessageType() == Sandesha2Constants.MessageTypes.TERMINATE_SEQ)
&&
(Sandesha2Constants.SPEC_2005_02.NS_URI.equals(rmMsgCtx.getRMNamespaceValue()))) {
try {
transaction = storageManager.getTransaction();
//terminate message sent using the SandeshaClient. Since the terminate message will simply get the
//InFlow of the reference message get called which could be zero sized (OutOnly operations).
// terminate sending side if this is the WSRM 1.0 spec.
// If the WSRM versoion is 1.1 termination will happen in the terminate sequence response message.
TerminateSequence terminateSequence = (TerminateSequence) rmMsgCtx
.getMessagePart(Sandesha2Constants.MessageParts.TERMINATE_SEQ);
String sequenceID = terminateSequence.getIdentifier().getIdentifier();
RMSBean rmsBean = SandeshaUtil.getRMSBeanFromSequenceId(storageManager, sequenceID);
TerminateManager.terminateSendingSide(rmsBean, storageManager);