Hi Deepal, As Nick pointed out in his response to Sanjiva, this didn't change the API -- people using the ServiceClient will not notice a thing and anyone using the OperationClient will now get the correct behavior when using RM and sync 2-way messaging. The modification simply moved implementation logic from the ServiceClient down to the OperationClient.
I can point out 100s of instances of this pattern of modification without any discussion on the mailing list what so ever. -Bill On Thu, 2007-01-25 at 14:16 +0530, Deepal Jayasinghe wrote: > Hi ; > > My mistake I didnt see the JIRA , but I am still in -1 state until we > come to a conclusion. > > Specially when we change API and their implementation we need to discuss > that in the mailing list and then implement . > > Thnaks > Deepal > > Deepal Jayasinghe wrote: > > >Hi Bill; > > > >I am -1 on this since no one discuss about this change before in the > >mailing list and I didnt find any JIRA related to this. So I think we > >need to revert this changes until we come to an conclusion. > > > >Thanks > >Deepal > > > >[EMAIL PROTECTED] wrote: > > > > > > > >>Author: nagy > >>Date: Wed Jan 24 10:38:56 2007 > >>New Revision: 499521 > >> > >>URL: http://svn.apache.org/viewvc?view=rev&rev=499521 > >>Log: > >>AXIS2-2020 > >>Contributor: Matt Lovett > >>Fix to allow clients/other layers that use the OperationClient directly (as > >>opposed to going through the ServiceClient) to function correctly with sync > >>2-way messaging and RM enabled. > >> > >>Modified: > >> > >> webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/client/ServiceClient.java > >> > >> webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java > >> > >>Modified: > >>webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/client/ServiceClient.java > >>URL: > >>http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/client/ServiceClient.java?view=diff&rev=499521&r1=499520&r2=499521 > >>============================================================================== > >>--- > >>webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/client/ServiceClient.java > >> (original) > >>+++ > >>webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/client/ServiceClient.java > >> Wed Jan 24 10:38:56 2007 > >>@@ -20,17 +20,13 @@ > >>import org.apache.axiom.om.OMElement; > >>import org.apache.axiom.soap.*; > >>import org.apache.axis2.AxisFault; > >>-import org.apache.axis2.Constants; > >>import org.apache.axis2.addressing.EndpointReference; > >>-import org.apache.axis2.client.async.AsyncResult; > >>import org.apache.axis2.client.async.Callback; > >>import org.apache.axis2.context.*; > >>import org.apache.axis2.description.*; > >>import org.apache.axis2.engine.AxisConfiguration; > >>import org.apache.axis2.engine.ListenerManager; > >>-import org.apache.axis2.engine.MessageReceiver; > >>import org.apache.axis2.i18n.Messages; > >>-import org.apache.axis2.util.CallbackReceiver; > >>import org.apache.axis2.wsdl.WSDLConstants; > >> > >>import javax.wsdl.Definition; > >>@@ -396,65 +392,11 @@ > >> * @see #createClient(QName) > >> */ > >> public void sendRobust(QName operation, OMElement elem) throws > >> AxisFault { > >>- if (options.isUseSeparateListener()) { > >>- > >>- // This mean doing a Fault may come through a different > >>channel . > >>- // If the > >>- // transport is two way transport (e.g. http) Only one channel > >>is > >>- // used (e.g. in http cases > >>- // 202 OK is sent to say no response available). Axis2 get > >>blocked > >>- // return when the response is available. > >>- SyncCallBack callback = new SyncCallBack(); > >>- > >>- // this method call two channel non blocking method to do the > >>work > >>- // and wait on the callback > >>- sendReceiveNonBlocking(operation, elem, callback); > >>- > >>- long timeout = options.getTimeOutInMilliSeconds(); > >>- long waitTime = timeout; > >>- long startTime = System.currentTimeMillis(); > >>- > >>- synchronized (callback) { > >>- while (! callback.isComplete() && waitTime >= 0) { > >>- try { > >>- callback.wait(timeout); > >>- } catch (InterruptedException e) { > >>- // We were interrupted for some reason, keep > >>waiting > >>- // or throw new AxisFault( "Callback was > >>interrupted by someone?" ); > >>- } > >>- // The wait finished, compute remaining time > >>- // - wait can end prematurely, see Object.wait( int > >>timeout ) > >>- waitTime = timeout - (System.currentTimeMillis() - > >>startTime); > >>- } > >>- > >>- } > >>- SOAPEnvelope envelope = callback.envelope; > >>- // process the result of the invocation > >>- if (envelope != null) { > >>- // building soap envelope > >>- envelope.build(); > >>- // closing transport > >>- if (envelope.getBody().hasFault()) { > >>- SOAPFault soapFault = envelope.getBody().getFault(); > >>- throw new AxisFault(soapFault.getCode(), > >>soapFault.getReason(), > >>- soapFault.getNode(), soapFault.getRole(), > >>soapFault.getDetail()); > >>- } > >>- } else { > >>- if (callback.error instanceof AxisFault) { > >>- throw (AxisFault) callback.error; > >>- } else if (callback.error != null) { > >>- throw new AxisFault(callback.error); > >>- } else if (! callback.isComplete()) { > >>- //no exception has occurred > >>- } > >>- } > >>- } else { > >>- MessageContext mc = new MessageContext(); > >>- fillSOAPEnvelope(mc, elem); > >>- OperationClient mepClient = createClient(operation); > >>- mepClient.addMessageContext(mc); > >>- mepClient.execute(true); > >>- } > >>+ MessageContext mc = new MessageContext(); > >>+ fillSOAPEnvelope(mc, elem); > >>+ OperationClient mepClient = createClient(operation); > >>+ mepClient.addMessageContext(mc); > >>+ mepClient.execute(true); > >> } > >> > >> /** > >>@@ -524,76 +466,14 @@ > >> */ > >> public OMElement sendReceive(QName operationQName, OMElement xmlPayload) > >> throws AxisFault { > >>- /** > >>- * If a module has set the USE_ASYNC_OPERATIONS option then we > >>override the behaviour > >>- * for sync calls. However we leave real async calls alone. > >>- */ > >>- boolean useAsync = false; > >>- if (!options.isUseSeparateListener()) { > >>- Boolean useAsyncOption = (Boolean) > >>configContext.getProperty(Constants.Configuration.USE_ASYNC_OPERATIONS); > >>- if (useAsyncOption != null) useAsync = > >>useAsyncOption.booleanValue(); > >>- } > >>- > >>- if (useAsync || options.isUseSeparateListener()) { > >>- > >>- // Here we are trying to do a request-response invocation > >>using two different channels for the request > >>- // and the response. > >>- // For example, if the IN and OUT transports are HTTP, then > >>two different HTTP channels will be used. The first > >>- // channel will be used to send the request, which the server > >>respond sending HTTP 200, if accepted and uses > >>- // a completely different channel to send the response. This > >>flag, informs the Axis2 client engine to > >>- // keep listeners ready to receive the response. > >>- > >>- // even if the client is blocking we use a Callback, > >>internally, to relate the response back to the client. > >>- SyncCallBack callback = new SyncCallBack(); > >>- > >>- // this method call two channel non blocking method to do the > >>work > >>- // and wait on the callback > >>- sendReceiveNonBlocking(operationQName, xmlPayload, callback); > >>- > >>- long timeout = options.getTimeOutInMilliSeconds(); > >>- long waitTime = timeout; > >>- long startTime = System.currentTimeMillis(); > >>- > >>- synchronized (callback) { > >>- while (! callback.isComplete() && waitTime >= 0) { > >>- try { > >>- callback.wait(timeout); > >>- } catch (InterruptedException e) { > >>- // We were interrupted for some reason, keep > >>waiting > >>- // or throw new AxisFault( "Callback was > >>interrupted by someone?" ); > >>- } > >>- // The wait finished, compute remaining time > >>- // - wait can end prematurely, see Object.wait( int > >>timeout ) > >>- waitTime = timeout - (System.currentTimeMillis() - > >>startTime); > >>- } > >>- > >>- } > >>- // process the result of the invocation > >>- if (callback.envelope != null) { > >>- // transport was already returned by the call back receiver > >>- //Building of the Envelope should happen at the > >>setComplete() > >>- // or onComplete() methods of the Callback class > >>- return callback.envelope.getBody().getFirstElement(); > >>- } else { > >>- if (callback.error instanceof AxisFault) { > >>- throw (AxisFault) callback.error; > >>- } else if (callback.error != null) { > >>- throw new AxisFault(callback.error); > >>- } else if (! callback.isComplete()) { > >>- throw new > >>AxisFault(Messages.getMessage("responseTimeOut")); > >>- } else > >>- throw new > >>AxisFault(Messages.getMessage("callBackCompletedWithError")); > >>- } > >>- } else { > >>- MessageContext messageContext = new MessageContext(); > >>- fillSOAPEnvelope(messageContext, xmlPayload); > >>- OperationClient operationClient = createClient(operationQName); > >>- operationClient.addMessageContext(messageContext); > >>- operationClient.execute(true); > >>- MessageContext response = operationClient > >>- > >>.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE); > >>- return response.getEnvelope().getBody().getFirstElement(); > >>- } > >>+ MessageContext messageContext = new MessageContext(); > >>+ fillSOAPEnvelope(messageContext, xmlPayload); > >>+ OperationClient operationClient = createClient(operationQName); > >>+ operationClient.addMessageContext(messageContext); > >>+ operationClient.execute(true); > >>+ MessageContext response = operationClient > >>+ .getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE); > >>+ return response.getEnvelope().getBody().getFirstElement(); > >> } > >> > >> /** > >>@@ -635,24 +515,6 @@ > >> // progamming model is non blocking > >> mepClient.setCallback(callback); > >> mepClient.addMessageContext(mc); > >>- > >>- /** > >>- * If a module has set the USE_ASYNC_OPERATIONS option then we > >>override the behaviour > >>- * for sync calls. However we leave real async calls alone. > >>- */ > >>- boolean useAsync = false; > >>- if (!options.isUseSeparateListener()) { > >>- Boolean useAsyncOption = (Boolean) > >>configContext.getProperty(Constants.Configuration.USE_ASYNC_OPERATIONS); > >>- if (useAsyncOption != null) useAsync = > >>useAsyncOption.booleanValue(); > >>- } > >>- > >>- if (useAsync || options.isUseSeparateListener()) { > >>- MessageReceiver messageReceiver = > >>axisService.getOperation(operation).getMessageReceiver(); > >>- if (messageReceiver == null || !(messageReceiver instanceof > >>CallbackReceiver)) { > >>- CallbackReceiver callbackReceiver = new CallbackReceiver(); > >>- > >>axisService.getOperation(operation).setMessageReceiver(callbackReceiver); > >>- } > >>- } > >> mepClient.execute(false); > >> } > >> > >>@@ -785,42 +647,6 @@ > >> serviceContext.setCachingOperationContext(cachingOpContext); > >> } > >> > >>- > >>- /** > >>- * This class acts as a callback that allows users to wait on the > >>result. > >>- */ > >>- private class SyncCallBack extends Callback { > >>- private SOAPEnvelope envelope; > >>- > >>- private MessageContext msgctx; > >>- > >>- private Exception error; > >>- > >>- public void onComplete(AsyncResult result) { > >>- this.envelope = result.getResponseEnvelope(); > >>- // Transport input stream gets closed after calling setComplete > >>- // method. Have to build the whole envelope including the > >>- // attachments at this stage. Data might get lost if the input > >>- // stream gets closed before building the whole envelope. > >>- this.envelope.buildWithAttachments(); > >>- this.msgctx = result.getResponseMessageContext(); > >>- } > >>- > >>- public void setComplete(boolean complete) { > >>- super.setComplete(complete); > >>- synchronized (this) { > >>- notify(); > >>- } > >>- } > >>- > >>- public void onError(Exception e) { > >>- error = e; > >>- } > >>- > >>- public MessageContext getMsgctx() { > >>- return msgctx; > >>- } > >>- } > >> > >> /** > >> * Get the service context. > >> > >>Modified: > >>webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java > >>URL: > >>http://svn.apache.org/viewvc/webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java?view=diff&rev=499521&r1=499520&r2=499521 > >>============================================================================== > >>--- > >>webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java > >> (original) > >>+++ > >>webservices/axis2/trunk/java/modules/kernel/src/org/apache/axis2/description/OutInAxisOperation.java > >> Wed Jan 24 10:38:56 2007 > >>@@ -35,6 +35,8 @@ > >>import org.apache.axis2.util.CallbackReceiver; > >>import org.apache.axiom.om.util.UUIDGenerator; > >>import org.apache.axis2.wsdl.WSDLConstants; > >>+import org.apache.commons.logging.Log; > >>+import org.apache.commons.logging.LogFactory; > >> > >>import javax.xml.namespace.QName; > >>import java.util.HashMap; > >>@@ -95,6 +97,8 @@ > >> */ > >>class OutInAxisOperationClient extends OperationClient { > >> > >>+ private static Log log = > >>LogFactory.getLog(OutInAxisOperationClient.class); > >>+ > >> OutInAxisOperationClient(OutInAxisOperation axisOp, ServiceContext sc, > >> Options options) { > >> super(axisOp, sc, options); > >>@@ -149,6 +153,7 @@ > >> * @throws AxisFault if something goes wrong during the execution of > >> the MEP. > >> */ > >> public void execute(boolean block) throws AxisFault { > >>+ if(log.isDebugEnabled()) log.debug("Entry: > >>OutInAxisOperationClient::execute, " + block); > >> if (completed) { > >> throw new AxisFault(Messages.getMessage("mepiscomplted")); > >> } > >>@@ -181,9 +186,29 @@ > >> } > >> > >> if (useAsync || options.isUseSeparateListener()) { > >>- CallbackReceiver callbackReceiver = (CallbackReceiver) axisOp > >>- .getMessageReceiver(); > >>- callbackReceiver.addCallback(mc.getMessageID(), callback); > >>+ if(log.isDebugEnabled()) > >>+ log.debug("useAsync=" + useAsync + ", > >>seperateListener=" + options.isUseSeparateListener()); > >>+ /** > >>+ * We are following the async path. If the user hasn't set a > >>callback object then we must > >>+ * block until the whole MEP is complete, as they have no other > >>way to get their reply message. > >>+ */ > >>+ CallbackReceiver callbackReceiver = null; > >>+ if(axisOp.getMessageReceiver() != null && > >>axisOp.getMessageReceiver() instanceof CallbackReceiver) { > >>+ callbackReceiver = (CallbackReceiver) > >>axisOp.getMessageReceiver(); > >>+ } else { > >>+ if(log.isDebugEnabled()) log.debug("Creating new > >>callback receiver"); > >>+ callbackReceiver = new CallbackReceiver(); > >>+ axisOp.setMessageReceiver(callbackReceiver); > >>+ } > >>+ > >>+ SyncCallBack internalCallback = null; > >>+ if(callback != null) { > >>+ callbackReceiver.addCallback(mc.getMessageID(), callback); > >>+ } else { > >>+ if(log.isDebugEnabled()) log.debug("Creating internal > >>callback"); > >>+ internalCallback = new SyncCallBack(); > >>+ callbackReceiver.addCallback(mc.getMessageID(), > >>internalCallback); > >>+ } > >> > >> /** > >> * If USE_CUSTOM_LISTENER is set to 'true' the replyTo value > >> will not be replaced and Axis2 will not > >>@@ -205,14 +230,45 @@ > >> > >> mc.getReplyTo().setAddress(replyToFromTransport.getAddress()); > >> } > >> } > >>- > >>- > >> > >> //if we don't do this , this guy will wait till it gets HTTP > >> 202 in the HTTP case > >> mc.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, > >> Boolean.TRUE); > >> AxisEngine engine = new AxisEngine(cc); > >> > >> mc.getConfigurationContext().registerOperationContext(mc.getMessageID(), > >> oc); > >> engine.send(mc); > >>+ > >>+ if(internalCallback != null) { > >>+ long timeout = options.getTimeOutInMilliSeconds(); > >>+ long waitTime = timeout; > >>+ long startTime = System.currentTimeMillis(); > >>+ > >>+ synchronized (internalCallback) { > >>+ while (! internalCallback.isComplete() && waitTime >= > >>0) { > >>+ try { > >>+ internalCallback.wait(timeout); > >>+ } catch (InterruptedException e) { > >>+ // We were interrupted for some reason, keep > >>waiting > >>+ // or throw new AxisFault( "Callback was > >>interrupted by someone?" ); > >>+ } > >>+ // The wait finished, compute remaining time > >>+ // - wait can end prematurely, see Object.wait( int > >>timeout ) > >>+ waitTime = timeout - (System.currentTimeMillis() - > >>startTime); > >>+ } > >>+ } > >>+ // process the result of the invocation > >>+ if (internalCallback.envelope != null) { > >>+ // The call ended normally, so there is > >>nothing to do > >>+ } else { > >>+ if (internalCallback.error instanceof > >>AxisFault) { > >>+ throw (AxisFault) > >>internalCallback.error; > >>+ } else if (internalCallback.error != > >>null) { > >>+ throw new > >>AxisFault(internalCallback.error); > >>+ } else if (! > >>internalCallback.isComplete()) { > >>+ throw new > >>AxisFault(Messages.getMessage("responseTimeOut")); > >>+ } else > >>+ throw new > >>AxisFault(Messages.getMessage("callBackCompletedWithError")); > >>+ } > >>+ } > >> } else { > >> if (block) { > >> // Send the SOAP Message and receive a response > >>@@ -344,4 +400,41 @@ > >> } > >> } > >> } > >>+ > >>+ /** > >>+ * This class acts as a callback that allows users to wait on the > >>result. > >>+ */ > >>+ private class SyncCallBack extends Callback { > >>+ > >>+ private SOAPEnvelope envelope; > >>+ > >>+ private Exception error; > >>+ > >>+ public void onComplete(AsyncResult result) { > >>+ if(log.isDebugEnabled()) log.debug("Entry: > >>OutInAxisOperationClient$SyncCallBack::onComplete"); > >>+ // Transport input stream gets closed after calling setComplete > >>+ // method. Have to build the whole envelope including the > >>+ // attachments at this stage. Data might get lost if the input > >>+ // stream gets closed before building the whole envelope. > >>+ this.envelope = result.getResponseEnvelope(); > >>+ this.envelope.buildWithAttachments(); > >>+ if(log.isDebugEnabled()) log.debug("Exit: > >>OutInAxisOperationClient$SyncCallBack::onComplete"); > >>+ } > >>+ > >>+ public void setComplete(boolean complete) { > >>+ if(log.isDebugEnabled()) log.debug("Entry: > >>OutInAxisOperationClient$SyncCallBack::setComplete, " + complete); > >>+ super.setComplete(complete); > >>+ synchronized (this) { > >>+ notify(); > >>+ } > >>+ if(log.isDebugEnabled()) log.debug("Exit: > >>OutInAxisOperationClient$SyncCallBack::setComplete, " + complete); > >>+ } > >>+ > >>+ public void onError(Exception e) { > >>+ if(log.isDebugEnabled()) log.debug("Entry: > >>OutInAxisOperationClient$SyncCallBack::onError, " + e); > >>+ error = e; > >>+ if(log.isDebugEnabled()) log.debug("Exit: > >>OutInAxisOperationClient$SyncCallBack::onError"); > >>+ } > >>+ } > >>+ > >>} > >> > >> > >> > >>--------------------------------------------------------------------- > >>To unsubscribe, e-mail: [EMAIL PROTECTED] > >>For additional commands, e-mail: [EMAIL PROTECTED] > >> > >> > >> > >> > >> > >> > >> > > > > > > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
