You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ode.apache.org by mr...@apache.org on 2008/05/22 02:13:25 UTC

svn commit: r658952 - in /ode/branches/APACHE_ODE_1.1: axis2-war/src/test/resources/TestHttpBinding/ axis2/src/main/java/org/apache/ode/axis2/httpbinding/ axis2/src/test/java/org/apache/ode/axis2/httpbinding/ axis2/src/test/resources/ utils/src/main/ja...

Author: mriou
Date: Wed May 21 17:13:24 2008
New Revision: 658952

URL: http://svn.apache.org/viewvc?rev=658952&view=rev
Log:
ODE-283 HTTP Verb at the operation level.

Modified:
    ode/branches/APACHE_ODE_1.1/axis2-war/src/test/resources/TestHttpBinding/Arithmetics.wsdl
    ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java
    ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java
    ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java
    ode/branches/APACHE_ODE_1.1/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpBindingValidatorTest.java
    ode/branches/APACHE_ODE_1.1/axis2/src/test/resources/http-binding-validator.wsdl
    ode/branches/APACHE_ODE_1.1/utils/src/main/java/org/apache/ode/utils/wsdl/WsdlUtils.java

Modified: ode/branches/APACHE_ODE_1.1/axis2-war/src/test/resources/TestHttpBinding/Arithmetics.wsdl
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/axis2-war/src/test/resources/TestHttpBinding/Arithmetics.wsdl?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/axis2-war/src/test/resources/TestHttpBinding/Arithmetics.wsdl (original)
+++ ode/branches/APACHE_ODE_1.1/axis2-war/src/test/resources/TestHttpBinding/Arithmetics.wsdl Wed May 21 17:13:24 2008
@@ -98,9 +98,11 @@
 
 
     <wsdl:binding name="OlaElMundoHttpBinding-GET" type="tns:OlaElMundoPortType">
-        <http:binding verb="GET"/>
+        <!-- /!\ no http:binding element here, see operation binding -->
+        <!-- It's meant to test a wsdl extension defined for RESTful BPEL -->
         <wsdl:operation name="plus">
             <http:operation location="plus/(left):(right)"/>
+            <http:binding verb="GET"/>
             <wsdl:input>
                 <http:urlReplacement/>
             </wsdl:input>
@@ -110,6 +112,7 @@
         </wsdl:operation>
         <wsdl:operation name="minus">
             <http:operation location="minus"/>
+            <http:binding verb="GET"/>
             <wsdl:input>
                 <http:urlEncoded/>
             </wsdl:input>
@@ -120,9 +123,12 @@
     </wsdl:binding>
 
     <wsdl:binding name="OlaElMundoHttpBinding-POST" type="tns:OlaElMundoPortType">
-        <http:binding verb="POST"/>
+        <!-- /!\ here the verb is GET and not POST -->
+        <!-- It's meant to test a verb overridding, see wsdl extensions for RESTful BPEL -->
+        <http:binding verb="GET"/>
         <wsdl:operation name="plus">
             <http:operation location="plus"/>
+            <http:binding verb="POST"/>
             <wsdl:input>
                 <mime:content type="application/x-www-form-urlencoded"/>
             </wsdl:input>
@@ -132,6 +138,7 @@
         </wsdl:operation>
         <wsdl:operation name="minus">
             <http:operation location="minus"/>
+            <http:binding verb="POST"/>
             <wsdl:input>
                 <http:urlEncoded/>
             </wsdl:input>

Modified: ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java (original)
+++ ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpBindingValidator.java Wed May 21 17:13:24 2008
@@ -43,14 +43,11 @@
     private static final org.apache.ode.utils.wsdl.Messages wsdlMsgs = Messages.getMessages(org.apache.ode.utils.wsdl.Messages.class);
 
     protected Binding binding;
-    private String verb;
 
     public HttpBindingValidator(Binding binding) {
         this.binding = binding;
         if (!WsdlUtils.useHTTPBinding(binding))
             throw new IllegalArgumentException(httpMsgs.msgHttpBindingNotUsed(binding));
-        HTTPBinding httpBinding = (HTTPBinding) WsdlUtils.getBindingExtension(binding);
-        verb = httpBinding.getVerb();
     }
 
     public void validate() throws IllegalArgumentException {
@@ -58,7 +55,18 @@
     }
 
     protected void validatePort() {
+        // Validate the given HttpBinding
+        for (int i = 0; i < binding.getBindingOperations().size(); i++) {
+            BindingOperation bindingOperation = (BindingOperation) binding.getBindingOperations().get(i);
+            validateOperation(bindingOperation);
+        }
+    }
 
+    protected void validateOperation(BindingOperation bindingOperation) {
+        String verb = WsdlUtils.resolveVerb(binding, bindingOperation);
+        if(verb==null){
+            throw new IllegalArgumentException(httpMsgs.msgMissingVerb(binding, bindingOperation));
+        }
         if (!"GET".equalsIgnoreCase(verb)
                 && !"DELETE".equalsIgnoreCase(verb)
                 && !"PUT".equalsIgnoreCase(verb)
@@ -66,14 +74,7 @@
             throw new IllegalArgumentException(httpMsgs.msgUnsupportedHttpMethod(binding, verb));
         }
 
-        // Validate the given HttpBinding
-        for (int i = 0; i < binding.getBindingOperations().size(); i++) {
-            BindingOperation bindingOperation = (BindingOperation) binding.getBindingOperations().get(i);
-            validateOperation(bindingOperation);
-        }
-    }
 
-    protected void validateOperation(BindingOperation bindingOperation) {
         BindingOutput output = bindingOperation.getBindingOutput();
         String outputContentType = WsdlUtils.getMimeContentType(output.getExtensibilityElements());
         if (!outputContentType.endsWith("text/xml")) {

Modified: ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java (original)
+++ ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodBuilder.java Wed May 21 17:13:24 2008
@@ -34,6 +34,8 @@
 import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
 import org.apache.ode.bpel.epr.MutableEndpoint;
 import org.apache.ode.utils.DOMUtils;
+import org.apache.ode.utils.Namespaces;
+import org.apache.ode.utils.stl.CollectionsX;
 import org.apache.ode.utils.wsdl.*;
 import org.apache.ode.utils.wsdl.Messages;
 import org.apache.ode.axis2.util.UrlReplacementTransformer;
@@ -49,13 +51,16 @@
 import javax.wsdl.Binding;
 import javax.wsdl.extensions.http.HTTPOperation;
 import javax.wsdl.extensions.http.HTTPBinding;
+import javax.wsdl.extensions.UnknownExtensibilityElement;
 import javax.xml.namespace.QName;
 import java.io.UnsupportedEncodingException;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Collection;
 
 import com.ibm.wsdl.PartImpl;
+import com.ibm.wsdl.util.StringUtils;
 
 /**
  * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
@@ -67,18 +72,16 @@
 
     protected static final org.apache.ode.utils.wsdl.Messages msgs = Messages.getMessages(Messages.class);
     protected Binding binding;
-    protected String verb;
 
     public HttpMethodBuilder(Binding binding) {
         this.binding = binding;
-        HTTPBinding httpBinding = (HTTPBinding) WsdlUtils.getBindingExtension(binding);
-        this.verb = httpBinding.getVerb();
     }
 
 
     public HttpMethod buildHttpMethod(PartnerRoleMessageExchange odeMex) throws UnsupportedEncodingException {
         Operation operation = odeMex.getOperation();
         BindingOperation bindingOperation = binding.getBindingOperation(operation.getName(), operation.getInput().getName(), operation.getOutput().getName());
+
         // message to be sent
         Element message = odeMex.getRequest().getMessage();
         Message msgDef = operation.getInput().getMessage();
@@ -89,8 +92,12 @@
         // extract part values into a map and check that all parts are assigned a value
         Map<String, Element> partElements = extractPartElements(msgDef, message);
 
-        // build the http method
-        HttpMethod method = prepareHttpMethod(bindingOperation, partElements, url);
+        // http method type
+        // the operation may override the verb, this is an extension for RESTful BPEL
+        String verb = WsdlUtils.resolveVerb(binding, bindingOperation);
+
+        // build the http method itself
+        HttpMethod method = prepareHttpMethod(bindingOperation, verb, partElements, url);
         return method;
     }
 
@@ -106,7 +113,7 @@
         return partValues;
     }
 
-    protected HttpMethod prepareHttpMethod(BindingOperation bindingOperation, Map<String, Element> partValues, final String rootUri) throws UnsupportedEncodingException {
+    protected HttpMethod prepareHttpMethod(BindingOperation bindingOperation, String verb, Map<String, Element> partValues, final String rootUri) throws UnsupportedEncodingException {
         if (log.isDebugEnabled()) log.debug("Preparing http request...");
         // convenience variables...
         BindingInput bindingInput = bindingOperation.getBindingInput();

Modified: ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java (original)
+++ ode/branches/APACHE_ODE_1.1/axis2/src/main/java/org/apache/ode/axis2/httpbinding/Messages.java Wed May 21 17:13:24 2008
@@ -31,6 +31,10 @@
  */
 public class Messages extends MessageBundle {
 
+    public String msgMissingVerb(Binding binding, BindingOperation operation) {
+        return format("No verb defined for binding: {0} operation: {1}", binding.getQName(), operation.getName());
+    }
+
     public String msgUnsupportedHttpMethod(Binding binding, String verb) {
         return format("Unsupported HTTP method! binding: {0} method: {1}", binding.getQName(), verb);
     }

Modified: ode/branches/APACHE_ODE_1.1/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpBindingValidatorTest.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpBindingValidatorTest.java?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpBindingValidatorTest.java (original)
+++ ode/branches/APACHE_ODE_1.1/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpBindingValidatorTest.java Wed May 21 17:13:24 2008
@@ -44,6 +44,8 @@
     private static final Log log = LogFactory.getLog(HttpBindingValidatorTest.class);
 
     private Definition definition;
+    private static final String SHOULD_FAIL = "shouldFail";
+    private static final String SHOULD_PASS = "shouldPass";
 
     protected void setUp() throws Exception {
         super.setUp();
@@ -65,14 +67,13 @@
                 continue;
             }
             String doc = DOMUtils.getTextContent(documentationElement);
-            boolean shouldFail = doc.startsWith("shouldFail");
-            boolean shouldPass = doc.startsWith("shouldPass");
+            boolean shouldFail = doc.startsWith(SHOULD_FAIL);
+            boolean shouldPass = doc.startsWith(SHOULD_PASS);
             if(!shouldFail && !shouldPass) {
-                log.warn("Binding skipped : "+ localName +", <wsdl:documentation> content must start with 'OK' or 'KO'. ");
-                continue;
+                fail("Binding: "+ localName +", <wsdl:documentation> content must start with '"+SHOULD_FAIL+"' or '"+SHOULD_PASS+"'. ");
             }
 
-            log.info("Testing Binding : "+localName);
+            log.debug("Testing Binding : "+localName);
             String msg = localName + " : " + doc;
             try {
                 new HttpBindingValidator(binding).validate();

Modified: ode/branches/APACHE_ODE_1.1/axis2/src/test/resources/http-binding-validator.wsdl
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/axis2/src/test/resources/http-binding-validator.wsdl?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/axis2/src/test/resources/http-binding-validator.wsdl (original)
+++ ode/branches/APACHE_ODE_1.1/axis2/src/test/resources/http-binding-validator.wsdl Wed May 21 17:13:24 2008
@@ -35,6 +35,15 @@
                 <soap:body use="literal"/>
             </wsdl:output>
         </wsdl:operation>
+        <wsdl:operation name="bye">
+            <soap:operation soapAction="urn:hello" style="document"/>
+            <wsdl:input>
+                <soap:body use="literal"/>
+            </wsdl:input>
+            <wsdl:output>
+                <soap:body use="literal"/>
+            </wsdl:output>
+        </wsdl:operation>
     </wsdl:binding>
     <!-- ###################################### -->
     <!-- Supported HTTP Method tests-->
@@ -400,5 +409,80 @@
             </wsdl:output>
         </wsdl:operation>
     </wsdl:binding>
+
+    <!-- ###################################### -->
+    <!-- Verb at the operation level -->
+    <!-- ###################################### -->
+    <wsdl:binding name="DummyServiceHttpBinding_no_verb" type="ns1:DummyServicePortType">
+        <wsdl:documentation>
+            shouldFail # A verb must be defined: it could be in the port tag, or in the operation
+        </wsdl:documentation>
+        <wsdl:operation name="hello">
+            <http:operation location="DummyService/hello"/>
+            <wsdl:input>
+                <http:urlEncoded/>
+            </wsdl:input>
+            <wsdl:output>
+                <mime:content type="text/xml" part="hello"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:binding name="DummyServiceHttpBinding_no_verb" type="ns1:DummyServicePortType">
+        <wsdl:documentation>
+            shouldFail # A verb must be defined for each operation: it could be in the port tag, or in the operation
+        </wsdl:documentation>
+        <wsdl:operation name="hello">
+            <http:operation location="DummyService/hello"/>
+            <http:binding verb="GET"/>
+            <wsdl:input>
+                <http:urlEncoded/>
+            </wsdl:input>
+            <wsdl:output>
+                <mime:content type="text/xml" part="hello"/>
+            </wsdl:output>
+        </wsdl:operation>
+        <wsdl:operation name="bye">
+            <http:operation location="DummyService/bye"/>
+            <wsdl:input>
+                <http:urlEncoded/>
+            </wsdl:input>
+            <wsdl:output>
+                <mime:content type="text/xml" part="hello"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:binding name="DummyServiceHttpBinding_no_verb_in_port" type="ns1:DummyServicePortType">
+        <wsdl:documentation>
+            shouldPass # Verb may be defined in the operation
+        </wsdl:documentation>
+        <wsdl:operation name="hello">
+            <http:operation location="DummyService/hello"/>
+            <http:binding verb="GET"/>
+            <wsdl:input>
+                <http:urlEncoded/>
+            </wsdl:input>
+            <wsdl:output>
+                <mime:content type="text/xml" part="hello"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+    <wsdl:binding name="DummyServiceHttpBinding_verb_overridden" type="ns1:DummyServicePortType">
+        <wsdl:documentation>
+            shouldPass # Operation may override the verb defined in the port.
+        </wsdl:documentation>
+        <http:binding verb="GET"/>
+        <wsdl:operation name="hello">
+            <http:operation location="DummyService/hello"/>
+            <http:binding verb="POST"/>
+            <wsdl:input>
+                <http:urlEncoded/>
+            </wsdl:input>
+            <wsdl:output>
+                <mime:content type="text/xml" part="hello"/>
+            </wsdl:output>
+        </wsdl:operation>
+    </wsdl:binding>
+
+
     <!-- no <service> tags needed -->
 </wsdl:definitions>

Modified: ode/branches/APACHE_ODE_1.1/utils/src/main/java/org/apache/ode/utils/wsdl/WsdlUtils.java
URL: http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.1/utils/src/main/java/org/apache/ode/utils/wsdl/WsdlUtils.java?rev=658952&r1=658951&r2=658952&view=diff
==============================================================================
--- ode/branches/APACHE_ODE_1.1/utils/src/main/java/org/apache/ode/utils/wsdl/WsdlUtils.java (original)
+++ ode/branches/APACHE_ODE_1.1/utils/src/main/java/org/apache/ode/utils/wsdl/WsdlUtils.java Wed May 21 17:13:24 2008
@@ -20,6 +20,8 @@
 package org.apache.ode.utils.wsdl;
 
 import org.apache.ode.utils.stl.CollectionsX;
+import org.apache.ode.utils.Namespaces;
+import org.w3c.dom.Element;
 
 import javax.wsdl.Binding;
 import javax.wsdl.Port;
@@ -28,6 +30,7 @@
 import javax.wsdl.Service;
 import javax.wsdl.Definition;
 import javax.wsdl.extensions.ExtensibilityElement;
+import javax.wsdl.extensions.UnknownExtensibilityElement;
 import javax.wsdl.extensions.mime.MIMEContent;
 import javax.wsdl.extensions.mime.MIMEMultipartRelated;
 import javax.wsdl.extensions.http.HTTPBinding;
@@ -64,7 +67,7 @@
 
 
     /**
-     * Test if the given binding uses a Http binding.
+     * Test if the given binding uses HTTP binding.
      *
      * @param binding
      * @return true if {@link HTTPBinding} is assignable from the binding
@@ -72,12 +75,22 @@
      */
     public static boolean useHTTPBinding(Binding binding) {
         ExtensibilityElement element = getBindingExtension(binding);
-        return HTTPBinding.class.isAssignableFrom(element.getClass());
+        // with a fully wsdl-compliant document, this element cannot be null.
+        // but ODE extends the HTTP binding and supports the HTTP verb at the operation level.
+        // A port using this extension may have no HTTPBinding at the port level.  
+        if (element == null) {
+            // in this case, we check the binding information of one operation
+            final BindingOperation anOperation = (BindingOperation) binding.getBindingOperations().get(0);
+            final ExtensibilityElement opExt = getOperationExtension(anOperation);
+            return HTTPOperation.class.isAssignableFrom(opExt.getClass());
+        } else {
+            return HTTPBinding.class.isAssignableFrom(element.getClass());
+        }
     }
 
 
     /**
-     * @see #useSOAPBinding(javax.wsdl.Binding) 
+     * @see #useSOAPBinding(javax.wsdl.Binding)
      */
     public static boolean useSOAPBinding(Port port) {
         return useSOAPBinding(port.getBinding());
@@ -118,18 +131,18 @@
 
     /**
      * Look up the ExtensibilityElement defining the binding for the given Port or
-     * throw an {@link IllegalArgumentException} if no or multiple bindings found.
+     * throw an {@link IllegalArgumentException} if multiple bindings found.
      *
-     * @param port
-     * @return an instance of {@link SOAPBinding} or {@link HTTPBinding}
+     * @param binding
+     * @return an instance of {@link SOAPBinding} or {@link HTTPBinding} or null
+     * @throws IllegalArgumentException if multiple bindings found.
      */
     public static ExtensibilityElement getBindingExtension(Binding binding) {
         Collection bindings = new ArrayList();
         CollectionsX.filter(bindings, binding.getExtensibilityElements(), HTTPBinding.class);
         CollectionsX.filter(bindings, binding.getExtensibilityElements(), SOAPBinding.class);
         if (bindings.size() == 0) {
-            // exception if no bindings found
-            throw new IllegalArgumentException(msgs.msgNoBinding(binding.getQName()));
+            return null;
         } else if (bindings.size() > 1) {
             // exception if multiple bindings found
             throw new IllegalArgumentException(msgs.msgMultipleBindings(binding.getQName()));
@@ -140,15 +153,25 @@
         }
     }
 
+    /**
+     * @see #getBindingExtension(javax.wsdl.Binding)
+     */
     public static ExtensibilityElement getBindingExtension(Port port) {
         Binding binding = port.getBinding();
         if (binding == null) {
             throw new IllegalArgumentException(msgs.msgBindingNotFound(port.getName()));
         }
-
         return getBindingExtension(binding);
     }
 
+    /**
+     * Extract the instance of {@link javax.wsdl.extensions.http.HTTPOperation] or {@link javax.wsdl.extensions.soap.SOAPOperation}
+     * from the list of extensibility elements of the given {@link javax.wsdl.BindingOperation}.
+     *
+     * @param bindingOperation
+     * @return an instance of {@link javax.wsdl.extensions.http.HTTPOperation} or {@link javax.wsdl.extensions.soap.SOAPOperation}
+     * @throws IllegalArgumentException if not exactly 1 element is found.
+     */
     public static ExtensibilityElement getOperationExtension(BindingOperation bindingOperation) {
         Collection operations = new ArrayList();
         CollectionsX.filter(operations, bindingOperation.getExtensibilityElements(), HTTPOperation.class);
@@ -168,21 +191,35 @@
 
     }
 
+    /**
+     * @return true if the extensibility elements of the given {@link javax.wsdl.BindingInput} contains an instance of {@link javax.wsdl.extensions.http.HTTPUrlEncoded}
+     */
     public static boolean useUrlEncoded(BindingInput bindingInput) {
         Collection<HTTPUrlEncoded> coll = CollectionsX.filter(bindingInput.getExtensibilityElements(), HTTPUrlEncoded.class);
         return !coll.isEmpty();
     }
 
+    /**
+     * @return true if the extensibility elements of the given {@link javax.wsdl.BindingInput} contains an instance of {@link javax.wsdl.extensions.http.HTTPUrlReplacement}
+     */
     public static boolean useUrlReplacement(BindingInput bindingInput) {
         Collection<HTTPUrlReplacement> coll = CollectionsX.filter(bindingInput.getExtensibilityElements(), HTTPUrlReplacement.class);
         return !coll.isEmpty();
     }
 
+    /**
+     * @return true if the extensibility elements of the given {@link javax.wsdl.BindingInput} contains an instance of {@link javax.wsdl.extensions.mime.MIMEMultipartRelated}
+     */
     public static boolean useMimeMultipartRelated(BindingInput bindingInput) {
         Collection<MIMEMultipartRelated> coll = CollectionsX.filter(bindingInput.getExtensibilityElements(), MIMEMultipartRelated.class);
         return !coll.isEmpty();
     }
 
+    /**
+     * @return the {@linkplain javax.wsdl.extensions.mime.MIMEContent#getType() type} of the instance of {@link javax.wsdl.extensions.mime.MIMEContent}
+     * contained in the extensibility element list. Or null if none.
+     * @throws IllegalArgumentException if more than 1 MIMEContent is found.
+     */
     public static String getMimeContentType(List extensibilityElements) {
         Collection<MIMEContent> coll = CollectionsX.filter(extensibilityElements, MIMEContent.class);
         if (coll.size() == 0) {
@@ -197,6 +234,14 @@
         }
     }
 
+    /**
+     * Extract the instance of {@link javax.wsdl.extensions.http.HTTPAddress] or {@link javax.wsdl.extensions.soap.SOAPAddress}
+     * from the list of extensibility elements of the given {@link javax.wsdl.Port}.
+     *
+     * @param port
+     * @return an instance of {@link javax.wsdl.extensions.http.HTTPAddress} or {@link javax.wsdl.extensions.soap.SOAPAddress}
+     * @throws IllegalArgumentException if not exactly 1 element is found.
+     */
     public static ExtensibilityElement getAddressExtension(Port port) {
         Collection operations = new ArrayList();
         CollectionsX.filter(operations, port.getExtensibilityElements(), HTTPAddress.class);
@@ -215,5 +260,42 @@
         }
     }
 
+    /**
+     * ODE extends the wsdl spec by allowing definition of the HTTP verb at the operation level.
+     * <br/> If you do so, an {@link UnknownExtensibilityElement} will be added to the list of extensibility elements of the {@link javax.wsdl.BindingOperation}.
+     * <br/> This method looks up for such an element and return the value of the verb attribute if the underlying {@link org.w3c.dom.Element} is {@literal <binding xmlns="http://schemas.xmlsoap.org/wsdl/http/"/>}
+     * or null.
+     * @param bindingOperation
+     */
+    public static String getOperationVerb(BindingOperation bindingOperation) {
+        final Collection<UnknownExtensibilityElement> unknownExtElements = CollectionsX.filter(bindingOperation.getExtensibilityElements(), UnknownExtensibilityElement.class);
+        for (UnknownExtensibilityElement extensibilityElement : unknownExtElements) {
+            final Element e = extensibilityElement.getElement();
+            if (Namespaces.HTTP_NS.equalsIgnoreCase(e.getNamespaceURI())
+                    && "binding".equals(extensibilityElement.getElement().getLocalName())
+                    && e.hasAttribute("verb")) {
+                return e.getAttribute("verb");
+            }
+        }
+        return null;
+    }
+
+    /**
+     * ODE extends the wsdl spec by allowing definition of the HTTP verb at the operation level.
+     * <br/>The current implementation implementations allows you to have a {@literal <binding xmlns="http://schemas.xmlsoap.org/wsdl/http/"/>} element
+     * at the port level <strong>and</strong> at the operation level. In such a case the operation's verb overrides the port's verb.
+     * <br/> This method applies the later rule.
+     * <br/> If defined the operation's verb is returned, else the port's verb.  
+     * @param binding
+     * @param bindingOperation
+     * @return If defined the operation's verb is returned, else the port's verb.
+     * @see #getOperationVerb(javax.wsdl.BindingOperation) 
+     */
+    public static String resolveVerb(Binding binding, BindingOperation bindingOperation) {
+        final HTTPBinding httpBinding = (HTTPBinding) WsdlUtils.getBindingExtension(binding);
+        String portVerb = httpBinding != null ? httpBinding.getVerb() : null;
+        String operationVerb = WsdlUtils.getOperationVerb(bindingOperation);
+        return operationVerb != null ? operationVerb : portVerb;
+    }
 
 }