You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@axis.apache.org by ba...@apache.org on 2010/08/16 22:17:46 UTC

svn commit: r986122 - in /axis/axis2/java/core/trunk/modules/jaxws: src/org/apache/axis2/jaxws/ src/org/apache/axis2/jaxws/client/dispatch/ test-resources/wsdl/ test/org/apache/axis2/jaxws/client/dispatch/

Author: barrettj
Date: Mon Aug 16 20:17:45 2010
New Revision: 986122

URL: http://svn.apache.org/viewvc?rev=986122&view=rev
Log:
Add logic to parse the outbound Dispatch<T> message to determine the OperationDescription which will cause the correct Action to be set.  Added a flag to disable the resolution (since it can be slow).  Added logic to only parse the message if the Action was not set on the RequestContext already.  Added associated TDD tests.

Added:
    axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolution.wsdl
    axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionDocLitBare.wsdl
    axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionJAXB.wsdl
    axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionDocLitBareTest.java
    axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionJAXBTest.java
    axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionTest.java
Modified:
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java
    axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/JAXBDispatch.java

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java?rev=986122&r1=986121&r2=986122&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/Constants.java Mon Aug 16 20:17:45 2010
@@ -189,5 +189,33 @@ public interface Constants {
      */
     public static final String JAXWS_JAXB_WRITE_REMOVE_ILLEGAL_CHARS = 
         "jaxws.jaxb.write.remove.illegal.chars";
+    
+    /** 
+     * Context Property:
+     * Name: jaxws.dispatch.outbound.operation.resolution.enable
+     * Value: String "false" or "true"
+     * Default: null, which is interpreted as "true"
+     * Can be set on:
+     * - Axis Configuration, which affects operation resolution across all Dispatch<T> clients
+     * - Request message context, which affects only the Dispatch<T> client using that context.
+     *
+     * Indicates if a Dispatch<T> message should be parsed to determine the operation indicated in the
+     * message, and use that to determine the Action that should be placed in the outgoing message.  The
+     * Action would be placed in the SOAPAction HTTP header and any WS-Addressing Action headers if 
+     * WS-Addressing is enabled.  Prior to the introduction of this property and associated support, 
+     * for Dispatch<T> the client would have to set the Action on the Request Message context in order to 
+     * get a meaningful value set as the Action.
+     * 
+     * Note that parsing the outgoing message in order to determine the operation indicated in the
+     * message can be slow.  Therefore, this property is provided to disable that operation resolution.
+     * The default, however, is to do operation resolution.
+     * 
+     * Operation resolution will also be disabled on a Dispatch<T> client if an Action was set on the 
+     * request message context.  
+     * 
+     * @see javax.xml.ws.BindingProvider.SOAPACTION_USE_PROPERTY
+     * @see javax.xml.ws.BindingProvider.SOAPACTION_URI_PROPERTY
+     */
+    public static final String  DISPATCH_CLIENT_OUTBOUND_RESOLUTION = "jaxws.dispatch.outbound.operation.resolution.enable"; 
 
 }

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java?rev=986122&r1=986121&r2=986122&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/BaseDispatch.java Mon Aug 16 20:17:45 2010
@@ -21,9 +21,12 @@ package org.apache.axis2.jaxws.client.di
 
 import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.client.ServiceClient;
+import org.apache.axis2.description.AxisOperation;
+import org.apache.axis2.description.AxisService;
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.engine.AxisConfiguration;
 import org.apache.axis2.jaxws.BindingProvider;
 import org.apache.axis2.jaxws.ExceptionFactory;
-import org.apache.axis2.jaxws.client.ClientUtils;
 import org.apache.axis2.jaxws.client.async.AsyncResponse;
 import org.apache.axis2.jaxws.core.InvocationContext;
 import org.apache.axis2.jaxws.core.InvocationContextFactory;
@@ -31,6 +34,8 @@ import org.apache.axis2.jaxws.core.Messa
 import org.apache.axis2.jaxws.core.controller.InvocationController;
 import org.apache.axis2.jaxws.core.controller.InvocationControllerFactory;
 import org.apache.axis2.jaxws.description.EndpointDescription;
+import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
+import org.apache.axis2.jaxws.description.OperationDescription;
 import org.apache.axis2.jaxws.i18n.Messages;
 import org.apache.axis2.jaxws.marshaller.impl.alt.MethodMarshallerUtils;
 import org.apache.axis2.jaxws.message.Message;
@@ -42,7 +47,12 @@ import org.apache.axis2.jaxws.spi.migrat
 import org.apache.axis2.transport.http.HTTPConstants;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Node;
 
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPException;
+import javax.xml.soap.SOAPMessage;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.ws.AsyncHandler;
 import javax.xml.ws.ProtocolException;
@@ -170,6 +180,14 @@ public abstract class BaseDispatch<T> ex
             // Perform the WebServiceFeature configuration requested by the user.
             binding.configure(requestMsgCtx, this);
 
+            // Initializing the message context above will put the outbound message onto the messageContext
+            // Determine the operation if possible from the outbound message.  If it can not be determined
+            // it will be set to null.  In this case, an anonymous operation will be used.  Note that determining
+            // the operation will mean deserializing the message.  That means that any WebServiceFeatures must have
+            // been configured first so that any relevant configurations (such as MTOM) have been initialized prior to 
+            // the message being deserialized.  This is particularly true for Dispatch<JAXB Element>.
+            requestMsgCtx.setOperationDescription(getOperationDescriptionForDispatch(requestMsgCtx));
+
             // Send the request using the InvocationController
             ic.invoke(invocationContext);
 
@@ -227,6 +245,173 @@ public abstract class BaseDispatch<T> ex
         }
     }
 
+    /**
+     * Given a JAXWS Message Context which contains an outbound service-requester Message for a Dispatch client, 
+     * determine the OperationDescription for the operation contained in that Dispatch message.
+     * 
+     * Note that operation resolution can be disabled by a property setting.
+     * @see org.apache.axis2.jaxws.Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION
+     * 
+     * @param requestMessageCtx JAXWS Message Context containing the outbound Dispatch message
+     * @return the OperationDescription corresponding to the operation contained in the Dispatch message, or null 
+     * if it can not be determined or if dispatch operation resolution is disabled via a property.
+     */
+    private OperationDescription getOperationDescriptionForDispatch(MessageContext requestMessageCtx) {
+        OperationDescription operationDesc = null;
+        if (dispatchOperationResolutionEnabled()) {
+            EndpointInterfaceDescription endpointInterfaceDesc = getEndpointDescription().getEndpointInterfaceDescription();
+            // The SEI interface could be null (for example if there was no SEI and all the ports were dynamically added).
+            // If there is an SEI, then try to determine the operation for the outbound dispatch message.
+            if (endpointInterfaceDesc != null) {
+                QName bodyElementQName = getBodyElementQNameFromDispatchMessage(requestMessageCtx);
+                operationDesc = determineOperationDescFromBodyElementQName(endpointInterfaceDesc, bodyElementQName);
+            }
+        }
+        return operationDesc;
+    }
+    
+    /**
+     * Returns the OperationDescription corresponding to the bodyElementQName passed in.  What that body element corresponds to
+     * depends on the type of the message:
+     * - For Doc/Lit/Wrapped, the body element is the operation name
+     * - For Doc/Lit/Bare, the body element is the element name contained in the wsdl:message wsdl:part
+     * - For RPC, the body element is effectively the operation name.
+     * 
+     * @param endpointInterfaceDesc The interface (i.e. SEI) on which to search for the operation
+     * @param bodyElementQName the QName of the first body element for which to find the operation
+     * 
+     * @return The OperationDescription corresponding to the body element QName or null if one can not be found.
+     */
+    private OperationDescription determineOperationDescFromBodyElementQName(EndpointInterfaceDescription endpointInterfaceDesc,
+                                                                            QName bodyElementQName) {
+        OperationDescription operationDesc = null;
+        
+        // This logic mimics the code in SOAPMessageBodyBasedOperationDispatcher.findOperation.  We will look for
+        // the AxisOperation corresponding to the body element name.  Note that we are searching for the AxisOperation instead
+        // of searching through the OperationDescriptions so that we can use the getOperationByMessageElementQName
+        // for the Doc/Lit/Bare case.  Once we have the AxisOperation, we'll use that to find the Operation Description.
+        AxisService axisService = endpointInterfaceDesc.getEndpointDescription().getAxisService();
+        AxisOperation axisOperation = null;
+
+        // Doc/Lit/Wrapped and RPC, the operation name is the first body element qname
+        axisOperation = axisService.getOperation(new QName(bodyElementQName.getLocalPart()));
+        
+        if (axisOperation == null) {
+            // Doc/Lit/Bare, the first body element qname is the element name contained in the wsdl:message part
+            axisOperation = axisService.getOperationByMessageElementQName(bodyElementQName);
+        }
+        
+        if (axisOperation == null) {
+            // Not sure why we wouldn't have found the operation above using just the localPart rather than the full QName used here,
+            // but this is what SOAPMessageBodyBasedOperationDispatcher.findOperation does.
+            axisOperation = axisService.getOperation(bodyElementQName);
+        }
+
+        // If we found an axis operation, then find the operation description that corresponds to it
+        if (axisOperation != null) {
+            OperationDescription allOpDescs[] = endpointInterfaceDesc.getDispatchableOperations();
+            for (OperationDescription checkOpDesc : allOpDescs ) {
+                AxisOperation checkAxisOperation = checkOpDesc.getAxisOperation();
+                if (checkAxisOperation == axisOperation) {
+                    operationDesc = checkOpDesc;
+                    break;
+                }
+            }
+        }
+        return operationDesc;
+    }
+
+    /**
+     * Answer if operation resolution on outbound messages for dispatch clients should be done.  The default value 
+     * is TRUE, enabling operation resolution.  Resolution can be disabled via a property on the AxisConfiguration
+     * or on the RequestContext.  
+     * 
+     * Operation resolution is also disabled if a non-null value is specified on the request context for the Action
+     * 
+     * @see org.apache.axis2.jaxws.Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION
+     * @see javax.xml.ws.BindingProvider.SOAPACTION_USE_PROPERTY
+     * @see javax.xml.ws.BindingProvider.SOAPACTION_URI_PROPERTY
+     * 
+     * @return true if operation resolution should be performed on outbound 
+     */
+    private boolean dispatchOperationResolutionEnabled() {
+        boolean resolutionEnabled = true;
+        
+        // See if any properties disabled operation resolution 
+        // Check for System property setting
+        String flagValue = getProperty(org.apache.axis2.jaxws.Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION);
+
+        // If no System property was set, see if one was set on this request context.
+        if (flagValue == null) {
+            flagValue =  (String) getRequestContext().get(org.apache.axis2.jaxws.Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION);
+        }
+        
+        // If any property was set, check the value.
+        if (flagValue != null) {
+            if ("false".equalsIgnoreCase(flagValue)) {
+                resolutionEnabled = false;
+            } else if ("true".equalsIgnoreCase(flagValue)) {
+                resolutionEnabled = true;
+            }
+        }
+
+        // If a property didn't disable resolution, then see if a URI value was specified.
+        // If so, we'll use that later and there's no need to do operation resolution.         
+        if (resolutionEnabled) {
+            Boolean useSoapAction = (Boolean) getRequestContext().get(SOAPACTION_USE_PROPERTY);
+            if (useSoapAction != null && useSoapAction.booleanValue()) {
+                String soapAction = (String) getRequestContext().get(SOAPACTION_URI_PROPERTY);
+                if (soapAction != null) {
+                    resolutionEnabled = false;
+                }
+            }
+        }
+        return resolutionEnabled;
+    }
+
+    /**
+     * Retrieve the specified property from the AxisConfiguration.
+     * 
+     * @param key The property to retrieve from the AxisConfiguration
+     * @return the value associated with the property or null if the property did not exist on the configuration.
+     */
+    private String getProperty(String key) {
+        String propertyValue = null;
+        AxisConfiguration axisConfig = serviceDelegate.getServiceDescription().getAxisConfigContext().getAxisConfiguration();
+        Parameter parameter = axisConfig.getParameter(key);
+        if (parameter != null) {
+            propertyValue = (String) parameter.getValue();
+        }
+        return propertyValue;
+    }
+
+
+    /**
+     * Given a JAXWS Message Context which contains an outbound service-requester Message for a Dispatch client,
+     * determine the QName of the first body element contained in that message.
+     * 
+     * @param requestMessageCtx requestMessageCtx JAXWS Message Context containing the outbound Dispatch message
+     * @return the QName of the first body element contained in the outbound Dispatch message, or null if it 
+     * can not be determined.
+     */
+    QName getBodyElementQNameFromDispatchMessage(MessageContext requestMessageCtx) {
+        QName bodyElementQName = null;
+        Message dispatchMessage = requestMessageCtx.getMessage();
+        SOAPMessage soapMessage = dispatchMessage.getAsSOAPMessage();
+        try {
+            SOAPBody soapBody = soapMessage.getSOAPBody();
+            Node firstElement = soapBody.getFirstChild();
+            String ns = firstElement.getNamespaceURI();
+            String lp= firstElement.getLocalName();
+            bodyElementQName = new QName(ns, lp);
+        } catch (SOAPException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unabled to get the first body element from the outbound dispatch message", e);
+            }
+        }
+        return bodyElementQName;
+    }
+
     protected void initMessageContext(Object obj, MessageContext requestMsgCtx) {
         Message requestMsg = createRequestMessage(obj);
         setupMessageProperties(requestMsg);
@@ -287,7 +472,7 @@ public abstract class BaseDispatch<T> ex
             invocationContext.setHandlers(binding.getHandlerChain());
 
             initMessageContext(obj, requestMsgCtx);
-            
+
             /*
              * if SESSION_MAINTAIN_PROPERTY is true, and the client app has explicitly set a HEADER_COOKIE on the request context, assume the client
              * app is expecting the HEADER_COOKIE to be the session id.  If we were establishing a new session, no cookie would be sent, and the 
@@ -321,6 +506,14 @@ public abstract class BaseDispatch<T> ex
             // Perform the WebServiceFeature configuration requested by the user.
             binding.configure(requestMsgCtx, this);
 
+            // Initializing the message context above will put the outbound message onto the messageContext
+            // Determine the operation if possible from the outbound message.  If it can not be determined
+            // it will be set to null.  In this case, an anonymous operation will be used.  Note that determining
+            // the operation will mean deserializing the message.  That means that any WebServiceFeatures must have
+            // been configured first so that any relevant configurations (such as MTOM) have been initialized prior to 
+            // the message being deserialized.  This is particularly true for Dispatch<JAXB Element>.
+            requestMsgCtx.setOperationDescription(getOperationDescriptionForDispatch(requestMsgCtx));
+
             // Send the request using the InvocationController
             ic.invokeOneWay(invocationContext);
 
@@ -431,6 +624,14 @@ public abstract class BaseDispatch<T> ex
             // Perform the WebServiceFeature configuration requested by the user.
             binding.configure(requestMsgCtx, this);
 
+            // Initializing the message context above will put the outbound message onto the messageContext
+            // Determine the operation if possible from the outbound message.  If it can not be determined
+            // it will be set to null.  In this case, an anonymous operation will be used.  Note that determining
+            // the operation will mean deserializing the message.  That means that any WebServiceFeatures must have
+            // been configured first so that any relevant configurations (such as MTOM) have been initialized prior to 
+            // the message being deserialized.  This is particularly true for Dispatch<JAXB Element>.
+            requestMsgCtx.setOperationDescription(getOperationDescriptionForDispatch(requestMsgCtx));
+
             // Setup the Executor that will be used to drive async responses back to 
             // the client.
             // FIXME: We shouldn't be getting this from the ServiceDelegate, rather each 
@@ -518,7 +719,7 @@ public abstract class BaseDispatch<T> ex
             invocationContext.setHandlers(binding.getHandlerChain());
 
             initMessageContext(obj, requestMsgCtx);
-            
+
             /*
              * if SESSION_MAINTAIN_PROPERTY is true, and the client app has explicitly set a HEADER_COOKIE on the request context, assume the client
              * app is expecting the HEADER_COOKIE to be the session id.  If we were establishing a new session, no cookie would be sent, and the 
@@ -552,6 +753,15 @@ public abstract class BaseDispatch<T> ex
             // Perform the WebServiceFeature configuration requested by the user.
             binding.configure(requestMsgCtx, this);
 
+            // Initializing the message context above will put the outbound message onto the messageContext
+            // Determine the operation if possible from the outbound message.  If it can not be determined
+            // it will be set to null.  In this case, an anonymous operation will be used.  Note that determining
+            // the operation will mean deserializing the message.  That means that any WebServiceFeatures must have
+            // been configured first so that any relevant configurations (such as MTOM) have been initialized prior to 
+            // the message being deserialized.  This is particularly true for Dispatch<JAXB Element>.
+            requestMsgCtx.setOperationDescription(getOperationDescriptionForDispatch(requestMsgCtx));
+            
+
             // Setup the Executor that will be used to drive async responses back to 
             // the client.
             // FIXME: We shouldn't be getting this from the ServiceDelegate, rather each 

Modified: axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/JAXBDispatch.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/JAXBDispatch.java?rev=986122&r1=986121&r2=986122&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/JAXBDispatch.java (original)
+++ axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/client/dispatch/JAXBDispatch.java Mon Aug 16 20:17:45 2010
@@ -22,6 +22,7 @@ package org.apache.axis2.jaxws.client.di
 import org.apache.axis2.addressing.EndpointReference;
 import org.apache.axis2.jaxws.ExceptionFactory;
 import org.apache.axis2.jaxws.client.async.AsyncResponse;
+import org.apache.axis2.jaxws.core.MessageContext;
 import org.apache.axis2.jaxws.description.EndpointDescription;
 import org.apache.axis2.jaxws.message.Block;
 import org.apache.axis2.jaxws.message.Message;
@@ -46,6 +47,7 @@ import javax.xml.ws.WebServiceFeature;
 public class JAXBDispatch<T> extends BaseDispatch<T> {
     private static final Log log = LogFactory.getLog(JAXBDispatch.class);
     private JAXBContext jaxbContext;
+    private QName elementQName;
 
     public JAXBDispatch(ServiceDelegate svcDelegate,
                         EndpointDescription epDesc,
@@ -110,8 +112,8 @@ public class JAXBDispatch<T> extends Bas
             Protocol proto = Protocol.getProtocolForBinding(endpointDesc.getClientBindingID());
 
             // Create a block from the value
-            QName qName = XMLRootElementUtil.getXmlRootElementQNameFromObject(value);
-            Block block = factory.createFrom(value, context, qName);
+            elementQName = XMLRootElementUtil.getXmlRootElementQNameFromObject(value);
+            Block block = factory.createFrom(value, context, elementQName);
             MessageFactory mf = (MessageFactory)FactoryRegistry.getFactory(MessageFactory.class);
 
             if (mode.equals(Mode.PAYLOAD)) {
@@ -132,7 +134,19 @@ public class JAXBDispatch<T> extends Bas
 
         return message;
     }
-
+    
+    // For a JAXB element we don't need to parse the message to get the element QName (which is
+    // slow); we saved the element QName from the JAXBElement earlier.  If for some reason it was not
+    // saved, we'll try parsing the message to get it.
+    QName getBodyElementQNameFromDispatchMessage(MessageContext requestMessageCtx) {
+        QName returnElementQName = null;
+        if (elementQName != null) {
+            returnElementQName = elementQName;
+        } else {
+            returnElementQName = super.getBodyElementQNameFromDispatchMessage(requestMessageCtx);
+        }
+        return returnElementQName;
+    }
     public Object getValueFromMessage(Message message) {
         return getValue(message, mode, jaxbContext);
     }

Added: axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolution.wsdl
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolution.wsdl?rev=986122&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolution.wsdl (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolution.wsdl Mon Aug 16 20:17:45 2010
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                  xmlns:tns="http://org/apache/axis2/jaxws/samples/echo/"
+                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="EchoService"
+                  targetNamespace="http://org/apache/axis2/jaxws/samples/echo/">
+    <wsdl:types>
+        <xsd:schema
+                targetNamespace="http://org/apache/axis2/jaxws/samples/echo/"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+
+            <xsd:element name="echoStringResponse">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="echoResponse"
+                                     type="xsd:string"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+
+            <xsd:element name="echoStringInput">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="echoInput" type="xsd:string"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+
+        </xsd:schema>
+    </wsdl:types>
+    <wsdl:message name="echoOperationRequest">
+        <wsdl:part element="tns:echoStringInput" name="parameter"/>
+    </wsdl:message>
+    <wsdl:message name="echoOperationResponse">
+        <wsdl:part element="tns:echoStringResponse" name="parameter"/>
+    </wsdl:message>
+    <wsdl:portType name="EchoServicePortType">
+
+        <wsdl:operation name="echoOperation">
+            <wsdl:input message="tns:echoOperationRequest"/>
+            <wsdl:output message="tns:echoOperationResponse"/>
+        </wsdl:operation>
+        <wsdl:operation name="echoOperation2">
+            <wsdl:input message="tns:echoOperationRequest"/>
+            <wsdl:output message="tns:echoOperationResponse"/>
+        </wsdl:operation>
+    </wsdl:portType>
+    <wsdl:binding name="EchoSOAP" type="tns:EchoServicePortType">
+        <soap:binding style="document"
+                      transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="echoOperation">
+            <soap:operation soapAction="echoOperation" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+        <wsdl:operation name="echoOperation2">
+            <soap:operation soapAction="echoOperation2" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:service name="EchoService">
+        <wsdl:port binding="tns:EchoSOAP" name="EchoServicePort">
+            <soap:address
+                    location="http://localhost:8080/jaxws-samples/services/EchoService"/>
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>

Added: axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionDocLitBare.wsdl
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionDocLitBare.wsdl?rev=986122&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionDocLitBare.wsdl (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionDocLitBare.wsdl Mon Aug 16 20:17:45 2010
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                  xmlns:tns="http://org/apache/axis2/jaxws/samples/echo/"
+                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="EchoService"
+                  targetNamespace="http://org/apache/axis2/jaxws/samples/echo/">
+    <wsdl:types>
+        <xsd:schema
+                targetNamespace="http://org/apache/axis2/jaxws/samples/echo/"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+            <xsd:element name="echoStringInput" type="xsd:string"/>
+            <xsd:element name="echoStringResponse" type="xsd:string"/>
+
+        </xsd:schema>
+    </wsdl:types>
+    
+    <wsdl:message name="echoOperationRequest">
+        <wsdl:part element="tns:echoStringInput" name="arg0"/>
+    </wsdl:message>
+    <wsdl:message name="echoOperationResponse">
+        <wsdl:part element="tns:echoStringResponse" name="return"/>
+    </wsdl:message>
+
+    <wsdl:portType name="EchoServicePortType">
+        <wsdl:operation name="echoOperation">
+            <wsdl:input message="tns:echoOperationRequest"/>
+            <wsdl:output message="tns:echoOperationResponse"/>
+        </wsdl:operation>
+    </wsdl:portType>
+    <wsdl:binding name="EchoSOAP" type="tns:EchoServicePortType">
+        <soap:binding style="document"
+                      transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="echoOperation">
+            <soap:operation soapAction="echoOperation" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:service name="EchoService">
+        <wsdl:port binding="tns:EchoSOAP" name="EchoServicePort">
+            <soap:address
+                    location="http://localhost:8080/jaxws-samples/services/EchoService"/>
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>

Added: axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionJAXB.wsdl
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionJAXB.wsdl?rev=986122&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionJAXB.wsdl (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test-resources/wsdl/DispatchOperationResolutionJAXB.wsdl Mon Aug 16 20:17:45 2010
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+  -->
+<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+                  xmlns:tns="http://test/"
+                  xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="EchoService"
+                  targetNamespace="http://test/">
+    <wsdl:types>
+        <xsd:schema
+                targetNamespace="http://test/"
+                xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
+
+            <xsd:element name="echoStringResponse">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="echoResponse"
+                                     type="xsd:string"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+
+            <xsd:element name="echoStringInput">
+                <xsd:complexType>
+                    <xsd:sequence>
+                        <xsd:element name="echoInput" type="xsd:string"/>
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+
+        </xsd:schema>
+    </wsdl:types>
+    <wsdl:message name="echoStringRequest">
+        <wsdl:part element="tns:echoStringInput" name="parameter"/>
+    </wsdl:message>
+    <wsdl:message name="echoStringResponse">
+        <wsdl:part element="tns:echoStringResponse" name="parameter"/>
+    </wsdl:message>
+    <wsdl:portType name="EchoServicePortType">
+
+        <wsdl:operation name="echoString">
+            <wsdl:input message="tns:echoStringRequest"/>
+            <wsdl:output message="tns:echoStringResponse"/>
+        </wsdl:operation>
+        <wsdl:operation name="echoString2">
+            <wsdl:input message="tns:echoStringRequest"/>
+            <wsdl:output message="tns:echoStringResponse"/>
+        </wsdl:operation>
+    </wsdl:portType>
+    <wsdl:binding name="EchoSOAP" type="tns:EchoServicePortType">
+        <soap:binding style="document"
+                      transport="http://schemas.xmlsoap.org/soap/http"/>
+        <wsdl:operation name="echoString">
+            <soap:operation soapAction="echoString" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+        <wsdl:operation name="echoString2">
+            <soap:operation soapAction="echoString2" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:service name="EchoService">
+        <wsdl:port binding="tns:EchoSOAP" name="EchoServicePort">
+            <soap:address
+                    location="http://localhost:8080/jaxws-samples/services/EchoService"/>
+        </wsdl:port>
+    </wsdl:service>
+</wsdl:definitions>

Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionDocLitBareTest.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionDocLitBareTest.java?rev=986122&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionDocLitBareTest.java (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionDocLitBareTest.java Mon Aug 16 20:17:45 2010
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *      
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axis2.jaxws.client.dispatch;
+
+import org.apache.axis2.jaxws.client.InterceptableClientTestCase;
+import org.apache.axis2.jaxws.client.TestClientInvocationController;
+import org.apache.axis2.jaxws.core.InvocationContext;
+import org.apache.axis2.jaxws.core.MessageContext;
+import org.apache.axis2.jaxws.description.EndpointDescription;
+import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
+import org.apache.axis2.jaxws.description.OperationDescription;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.Service;
+
+import java.net.URL;
+
+/**
+ * Validate that operation resolution occurs correctly for a Doc/Lit/Bare message.
+ */
+public class DispatchOperationResolutionDocLitBareTest extends InterceptableClientTestCase {
+    URL wsdlDocumentLocation = getClass().getResource("/wsdl/DispatchOperationResolutionDocLitBare.wsdl");
+    QName serviceQName = new QName("http://org/apache/axis2/jaxws/samples/echo/", "EchoService");
+    QName portQName = new QName("http://org/apache/axis2/jaxws/samples/echo/", "EchoServicePort");
+
+    private static final String echoBodyContent_PAYLOAD =
+        "<ns1:echoStringInput xmlns:ns1=\"http://org/apache/axis2/jaxws/samples/echo/\">" + 
+        "The Bare Necessities" + 
+        "</ns1:echoStringInput>";
+
+    public void testOperationResolution() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+        
+    }
+    
+    //*********************************************************************************************
+    // Utility methods
+    //*********************************************************************************************
+
+    private OperationDescription expectedOperationDescription(MessageContext requestMC) {
+        return expectedOperationDescription(requestMC, "echoOperation");
+    }
+    private OperationDescription expectedOperationDescription(MessageContext requestMC, String operationName) {
+        EndpointDescription endpointDescription = requestMC.getEndpointDescription();
+        EndpointInterfaceDescription endpointInterfaceDescription = endpointDescription.getEndpointInterfaceDescription();
+        QName operationQName = new QName("http://org/apache/axis2/jaxws/samples/echo", operationName);
+        OperationDescription expectedOperationDescription = endpointInterfaceDescription.getOperation(operationQName)[0];
+        return expectedOperationDescription;
+    }
+
+}

Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionJAXBTest.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionJAXBTest.java?rev=986122&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionJAXBTest.java (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionJAXBTest.java Mon Aug 16 20:17:45 2010
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *      
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axis2.jaxws.client.dispatch;
+
+import org.apache.axis2.jaxws.client.InterceptableClientTestCase;
+import org.apache.axis2.jaxws.client.TestClientInvocationController;
+import org.apache.axis2.jaxws.core.InvocationContext;
+import org.apache.axis2.jaxws.core.MessageContext;
+import org.apache.axis2.jaxws.description.EndpointDescription;
+import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
+import org.apache.axis2.jaxws.description.OperationDescription;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.namespace.QName;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.Service;
+
+import java.net.URL;
+
+import test.EchoString;
+import test.ObjectFactory;
+
+/**
+ * Validate that Dispatch operation resolution occurs correctly for JAXB elements.
+ * 
+ * Note that this test uses the JAXB-generated artifacts from test-resources/xsd/echo.xsd and that the WSDL
+ * used in this test, test-resources/wsdl/DispatchOperationResolutionJAXB.wsdl, was crafted to match the
+ * generated JAXB artifacts.  That is why the WSDL and operations are different between this test and the other
+ * DispatchOperationResolution*.java tests
+ */
+public class DispatchOperationResolutionJAXBTest extends InterceptableClientTestCase {
+    URL wsdlDocumentLocation = getClass().getResource("/wsdl/DispatchOperationResolutionJAXB.wsdl");
+    QName serviceQName = new QName("http://test/", "EchoService");
+    QName portQName = new QName("http://test/", "EchoServicePort");
+
+    public void testJAXBResolution() {
+        try {
+            ObjectFactory factory = new ObjectFactory();
+            EchoString request = factory.createEchoString();         
+            request.setInput("Operation resolution JAXB test");
+            JAXBContext jbc = JAXBContext.newInstance(EchoString.class);
+    
+            Service service = Service.create(wsdlDocumentLocation, serviceQName);
+            Dispatch<Object> dispatch = service.createDispatch(portQName, jbc, Service.Mode.PAYLOAD);
+    
+            // The InterceptableClientTestCase invoke will return the "request" as the response.
+            EchoString response = (EchoString) dispatch.invoke(request);
+        } catch (Exception e) {
+            fail("Caught exception: " + e);
+        }
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC, "echoString");
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+    
+    private OperationDescription expectedOperationDescription(MessageContext requestMC, String operationName) {
+        EndpointDescription endpointDescription = requestMC.getEndpointDescription();
+        EndpointInterfaceDescription endpointInterfaceDescription = endpointDescription.getEndpointInterfaceDescription();
+        QName operationQName = new QName("http://test/", operationName);
+        OperationDescription expectedOperationDescription = endpointInterfaceDescription.getOperation(operationQName)[0];
+        return expectedOperationDescription;
+    }
+
+}

Added: axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionTest.java
URL: http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionTest.java?rev=986122&view=auto
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionTest.java (added)
+++ axis/axis2/java/core/trunk/modules/jaxws/test/org/apache/axis2/jaxws/client/dispatch/DispatchOperationResolutionTest.java Mon Aug 16 20:17:45 2010
@@ -0,0 +1,484 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *      
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.axis2.jaxws.client.dispatch;
+
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.description.Parameter;
+import org.apache.axis2.engine.AxisConfiguration;
+import org.apache.axis2.jaxws.Constants;
+import org.apache.axis2.jaxws.client.InterceptableClientTestCase;
+import org.apache.axis2.jaxws.client.TestClientInvocationController;
+import org.apache.axis2.jaxws.core.InvocationContext;
+import org.apache.axis2.jaxws.core.MessageContext;
+import org.apache.axis2.jaxws.description.DescriptionTestUtils2;
+import org.apache.axis2.jaxws.description.EndpointDescription;
+import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
+import org.apache.axis2.jaxws.description.OperationDescription;
+import org.apache.axis2.jaxws.description.ServiceDescription;
+import org.apache.axis2.jaxws.spi.BindingProvider;
+import org.apache.axis2.jaxws.spi.ServiceDelegate;
+
+import javax.xml.namespace.QName;
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Dispatch;
+import javax.xml.ws.Response;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.MTOMFeature;
+import javax.xml.ws.soap.SOAPBinding;
+
+import java.net.URL;
+import java.util.concurrent.Future;
+
+/**
+ * Validate the operation resolution of a Dispatch client.  For a Dispatch client, operation resolution is done
+ * by parsing the outbound message in order to determine the operation so that the Action can be set correctly.
+ * Prior to this functionality being added, Dispatch clients always used a generic Anonymous outbound operation, resulting
+ * in an Action that was not correct for the operation being invoked.  That meant that the client had to set the Action on 
+ * the outound Request Context to get the correct Action set.
+ * 
+ * With the new functionality, an outbound Dispatch message will be parsed to determine the operation and thus the correct
+ * Action UNLESS
+ * - A property has been set indicating that Resolution should not be done
+ * - A non-null Action has been set on the Request Context
+ * 
+ * Note that these tests are all Doc/Lit/Wrapped based.  There are additional tests to validate other styles such
+ * as Doc/Lit/Bare.  Those tests simply test the operation resolution using that style; they do not validate
+ * the flag settings and other aspects since that doesn't change based on the style in use.
+ * @see DispatchOperationResolutionDocLitBareTest
+ * @see DispatchOperationResolutionJAXBTest
+ */
+public class DispatchOperationResolutionTest extends InterceptableClientTestCase {
+    URL wsdlDocumentLocation = getClass().getResource("/wsdl/DispatchOperationResolution.wsdl");
+    QName serviceQName = new QName("http://org/apache/axis2/jaxws/samples/echo/", "EchoService");
+    QName portQName = new QName("http://org/apache/axis2/jaxws/samples/echo/", "EchoServicePort");
+
+    private static final String echoBodyContent_PAYLOAD =
+        "<ns1:echoOperation xmlns:ns1=\"http://org/apache/axis2/jaxws/samples/echo\">" + 
+        "<ns1:echoStringInput xmlns=\"http://org/apache/axis2/jaxws/samples/echo\">HELLO THERE!!!</ns1:echoStringInput>" + 
+        "</ns1:echoOperation>";
+    
+    private static final String echoBodyContent_NoResolution_PAYLOAD =
+        "<ns1:echoNoOperation xmlns:ns1=\"http://org/apache/axis2/jaxws/samples/echo\">" + 
+        "<ns1:echoStringInput xmlns=\"http://org/apache/axis2/jaxws/samples/echo\">HELLO THERE!!!</ns1:echoStringInput>" + 
+        "</ns1:echoNoOperation>";
+
+    private static final String echoBodyContent_MESSAGE = 
+        "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"><soapenv:Body>"
+        + echoBodyContent_PAYLOAD
+        + "</soapenv:Body></soapenv:Envelope>";
+
+    private static final String echoBodyContent2_PAYLOAD =
+        "<ns1:echoOperation2 xmlns:ns1=\"http://org/apache/axis2/jaxws/samples/echo\">" + 
+        "<ns1:echoStringInput xmlns=\"http://org/apache/axis2/jaxws/samples/echo\">HELLO THERE!!!</ns1:echoStringInput>" + 
+        "</ns1:echoOperation2>";
+    
+    /**
+     * Validate that operation resolution does not happen for dynamic ports
+     */
+    public void testDynamicPort_NoResolution() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        QName dynamicPortQN = new QName("http://org/apache/axis2/jaxws/samples/echo/", "DynamicPort");
+        service.addPort(dynamicPortQN, SOAPBinding.SOAP11HTTP_BINDING, "http://localhost");
+        Dispatch<String> dispatch = service.createDispatch(dynamicPortQN, String.class, Service.Mode.PAYLOAD);
+
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null for dynamic ports", opDesc);
+    }
+    
+    /**
+     * Validate Dispatch<String>, Synchronous request/response, Mode.PAYLOAD determines the operation correctly.
+     */
+    public void testOperationResolution_Sync_String_PAYLOAD() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+
+    /**
+     * Validate Dispatch<String>, Synchronous request/response, Mode.PAYLOAD determines the second operation correctly.
+     * 
+     * Most other tests validate the "echoOperation" operation; this test simply validates that the second WSDL operation
+     * "echoOperation2" is also resolved correctly.
+     */
+    public void testOperation2Resolution_Sync_String_PAYLOAD() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent2_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC, "echoOperation2");
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+
+    /**
+     * Validate Dispatch<String>, Synchronous request/response,Mode.MESSAGE determines the operation correctly.
+     */
+    public void testOperationResolution_Sync_String_MESSAGE() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.MESSAGE);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_MESSAGE);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+    
+    /**
+     * Validate that if the operation in the outbound dispatch message can not be resolved to a WSDL operation, the 
+     * operation is null.
+     * 
+     * Note that this seems like it should be an error.  However, it was not an error in previous releases since we did no
+     * operation resolution on the outbound dispatch message.  For backwards compatability, it is still not considered an error.
+     */
+    public void testNoOperationResolution() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_NoResolution_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null because operation in message could not be resolved to WSDL operations", opDesc);
+    }
+    
+    /**
+     * Validate Dispatch<String>, Oneway request, Mode.PAYLOAD determines the operation correctly.
+     */
+    public void testOperationResolution_Oneway_String_PAYLOAD() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        dispatch.invokeOneWay(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+
+    /**
+     * Validate Dispatch<String>, Async request/response, Mode.PAYLOAD determines the operation correctly.
+     */
+    public void testOperationResolution_Async_String_PAYLOAD() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        Response<String> response = dispatch.invokeAsync(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+
+    /**
+     * Validate Dispatch<String>, Async-Callback request/response, Mode.PAYLOAD determines the operation correctly.
+     */
+    public void testOperationResolution_AsyncCallback_String_PAYLOAD() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        AsyncHandler asyncHandler = new TestAsyncHandler();
+        Future<?> future = dispatch.invokeAsync(echoBodyContent_PAYLOAD, asyncHandler);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+    }
+    
+    /**
+     * Validate that operation resolution is not performed if the AxisConfiguration property is set to indicate it should not be.
+     */
+    public void testOperationResolutionDisabled_AxisConfiguration_false() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        
+        setAxisConfigParameter(service, Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION, "false");
+        
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null", opDesc);
+    }
+
+    /**
+     * Validate that operation resolution is not performed if the AxisConfiguration property is set to indicate it should not be.
+     * Note the value used in the property value is mixed case.
+     */
+    public void testOperationResolutionDisabled_AxisConfiguration_False() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        setAxisConfigParameter(service, Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION, "False");
+
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null", opDesc);
+    }
+    
+    /**
+     * Validate that setting the property on System has no effect on disabling operation resolution.  The property should only be set on 
+     * the AxisConfiguration (to affect all Dispatch clients) or on the Request Context (to affect that Dispatch client).
+     */
+    public void testOperationResolutionDisabled_SystemProperty_NoEffect() {
+        try {
+            System.setProperty(Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION, "false");
+            Service service = Service.create(wsdlDocumentLocation, serviceQName);
+
+            Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+            assertNotNull(dispatch);
+            
+            String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+            TestClientInvocationController testController = getInvocationController();
+            InvocationContext ic = testController.getInvocationContext();
+            MessageContext requestMC = ic.getRequestMessageContext();
+            
+            OperationDescription opDesc = requestMC.getOperationDescription();
+            assertNotNull("OpDesc from request MC should not be null", opDesc);
+            // Make sure we get the correct Operation Description
+            OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+            assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+
+        } finally {
+            System.clearProperty(Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION);
+        }
+    }
+    
+    /**
+     * Validate that doing operation resolution does not impact using a WebServiceFeature such as MTOM on the
+     * createDispatch.
+     */
+    public void testOperationResolutionAndMTOMFeature() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        MTOMFeature feature = new MTOMFeature(true);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.MESSAGE, feature);
+        assertNotNull(dispatch);
+        
+        String result = dispatch.invoke(echoBodyContent_MESSAGE);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should not be null", opDesc);
+        // Make sure we get the correct Operation Description
+        OperationDescription expectedOperationDescription = expectedOperationDescription(requestMC);
+        assertSame("Wrong operation description returned", expectedOperationDescription, opDesc);
+        assertTrue("MTOM should be enabled via the MTOMFeature.", requestMC.getMessage().isMTOMEnabled());
+    }
+
+    /**
+     * Validate that if a Action URI is set, the operation resolution does not occur.
+     */
+    public void testOperationResolutionDisabled_RequestContext_Action_Set() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY,"http://should.not.resolve.operation");
+
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null", opDesc);
+    }
+
+    /**
+     * Validate that even if the AxisConfiguration property is explicitly set to "true" to enable operation resolution,
+     * if a Action URI is also set, then resolution does not occur.
+     */
+    public void testOperationResolutionDisabled_AxisConfiguration_True_Request_Context_Action_Set() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        setAxisConfigParameter(service, Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION, "true");
+
+        
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY,"http://should.not.resolve.operation");
+
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null", opDesc);
+    }
+    
+    /**
+     * Validate that if the property to use a SOAP action is set, but the value for the SOAP action is null
+     * then operation resolution occurs.  That is necessary so the correct value for the soap action can be set.
+     */
+    public void testOperationResolutionDisabled_RequestContext_Action_null() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, null);
+
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNotNull("OpDesc from request MC should be null", opDesc);
+    }
+    /**
+     * Validate that if the property to use a SOAP action is set, and the value for the SOAP action is the 
+     * empty string, then operation resolution does NOT occur.  The empty string value is acceptable as a action value.
+     */
+    public void testOperationResolutionDisabled_RequestContext_Action_EmptyString() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
+        dispatch.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, "");
+
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null", opDesc);
+    }
+
+    /**
+     * Validate that operation resolution can be disabled by setting a property on the request context.
+     */
+    public void testOperationResolutionDisabled_RequestContext_Property() {
+        Service service = Service.create(wsdlDocumentLocation, serviceQName);
+        Dispatch<String> dispatch = service.createDispatch(portQName, String.class, Service.Mode.PAYLOAD);
+        assertNotNull(dispatch);
+        
+        dispatch.getRequestContext().put(Constants.DISPATCH_CLIENT_OUTBOUND_RESOLUTION, "false");
+
+        String result = dispatch.invoke(echoBodyContent_PAYLOAD);
+        TestClientInvocationController testController = getInvocationController();
+        InvocationContext ic = testController.getInvocationContext();
+        MessageContext requestMC = ic.getRequestMessageContext();
+        
+        OperationDescription opDesc = requestMC.getOperationDescription();
+        assertNull("OpDesc from request MC should be null", opDesc);
+    }
+    
+    //*********************************************************************************************
+    // Utility methods
+    //*********************************************************************************************
+
+    private OperationDescription expectedOperationDescription(MessageContext requestMC) {
+        return expectedOperationDescription(requestMC, "echoOperation");
+    }
+    private OperationDescription expectedOperationDescription(MessageContext requestMC, String operationName) {
+        EndpointDescription endpointDescription = requestMC.getEndpointDescription();
+        EndpointInterfaceDescription endpointInterfaceDescription = endpointDescription.getEndpointInterfaceDescription();
+        QName operationQName = new QName("http://org/apache/axis2/jaxws/samples/echo", operationName);
+        OperationDescription expectedOperationDescription = endpointInterfaceDescription.getOperation(operationQName)[0];
+        return expectedOperationDescription;
+    }
+    
+    private void setAxisConfigParameter(Service service, String key, String value) {
+        ServiceDelegate delegate = DescriptionTestUtils2.getServiceDelegate(service);
+        ServiceDescription svcDesc = delegate.getServiceDescription();
+        AxisConfiguration axisConfig = svcDesc.getAxisConfigContext().getAxisConfiguration();
+        Parameter parameter = new Parameter(key, value);
+        try {
+            axisConfig.addParameter(parameter);
+        } catch (AxisFault e) {
+            fail("Unable to set Parameter on AxisConfig due to exception " + e);
+        }
+    }
+
+    class TestAsyncHandler implements AsyncHandler {
+        public void handleResponse(Response response) {
+            // The Test Invocation Controller will not call the async handler, so this method
+            // does not need to do anything.
+        }
+        
+    }
+}