Author: scheu
Date: Thu Jul  8 20:19:47 2010
New Revision: 961916

URL: http://svn.apache.org/viewvc?rev=961916&view=rev
Log:
AXIS2-4763
Contributor: Lori VanGulick
Summary:
Support for JAX-WS 2.2 Provider<T> implementations that return null.  
This is a JAX-WS 2.2 specification compliance issue.
Also provided verification test

Added:
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SoapMessageNullProviderTests.java
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/META-INF/
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/META-INF/MANIFEST.MF
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/SoapMessageNullProvider.java
Modified:
    axis/axis2/java/core/trunk/modules/jaxws-integration/pom.xml
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SourceProviderTests.java
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/StringProviderTests.java
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/source/SourceProvider.java
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/META-INF/echostring.wsdl
    
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/StringProvider.java
    
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/core/util/MessageContextUtils.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerInvokerUtils.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java
    
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/ProviderDispatcher.java

Modified: axis/axis2/java/core/trunk/modules/jaxws-integration/pom.xml
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/pom.xml?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- axis/axis2/java/core/trunk/modules/jaxws-integration/pom.xml (original)
+++ axis/axis2/java/core/trunk/modules/jaxws-integration/pom.xml Thu Jul  8 
20:19:47 2010
@@ -593,6 +593,20 @@
                                         />
                                 <delete 
dir="${servicejars.dir}/SoapMessageMUProviderService"/>
 
+                                <copy 
toDir="${servicejars.dir}/SoapMessageNullProviderService/">
+                                    <fileset dir="target/test-classes">
+                                        <include 
name="org/apache/axis2/jaxws/provider/soapmsgreturnnull/**"/>
+                                    </fileset>
+                                    <fileset 
dir="test/org/apache/axis2/jaxws/provider/soapmsgreturnnull">
+                                        <include name="META-INF/**"/>
+                                    </fileset>
+                                </copy>
+
+                                <zip 
destfile="${servicejars.dir}/SoapMessageNullProviderService.jar"
+                                     
basedir="${servicejars.dir}/SoapMessageNullProviderService"
+                                        />
+                                <delete 
dir="${servicejars.dir}/SoapMessageNullProviderService"/>
+
                                 <copy 
toDir="${servicejars.dir}/JAXBProviderService/">
                                     <fileset dir="target/test-classes">
                                         <include 
name="org/apache/axis2/jaxws/provider/jaxb/**"/>
@@ -1336,6 +1350,7 @@
                         <include>**/SourceProviderTests.java</include>
                         <include>**/SourceMessageProviderTests.java</include>
                         <include>**/SoapMessageMUProviderTests.java</include>
+                        <include>**/SoapMessageNullProviderTests.java</include>
                         
                         <include>**/ProxyTests.java</include>
                         <include>**/ProxyNonWrappedTests.java</include>

Added: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SoapMessageNullProviderTests.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SoapMessageNullProviderTests.java?rev=961916&view=auto
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SoapMessageNullProviderTests.java
 (added)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SoapMessageNullProviderTests.java
 Thu Jul  8 20:19:47 2010
@@ -0,0 +1,84 @@
+/*
+ * 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.provider;
+
+import javax.xml.namespace.QName;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.ws.BindingProvider;
+import javax.xml.ws.Service;
+import javax.xml.ws.soap.SOAPBinding;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.axis2.jaxws.TestLogger;
+
+public class SoapMessageNullProviderTests extends ProviderTestCase {
+
+    private String endpointUrl = 
"http://localhost:6060/axis2/services/SoapMessageNullProviderService.SoapMessageNullProviderPort";;
+    private QName serviceName = new QName("http://ws.apache.org/axis2";, 
"SoapMessageNullProviderService");
+    public static final QName portName =
+        new QName("http://ws.apache.org/axis2";, "SoapMessageNullProviderPort");
+
+
+    public static final String bindingID = SOAPBinding.SOAP11HTTP_BINDING;
+    public static final Service.Mode mode = Service.Mode.MESSAGE;
+
+
+    public SoapMessageNullProviderTests() {
+        super();
+    }
+    
+    public static Test suite() {
+        return getTestSetup(new TestSuite(SoapMessageNullProviderTests.class));
+    }
+    /*
+     * Test that the custom property jaxws.provider.interpretNullAsOneway when 
set to true
+     * correctly causes the jaxws runtime to treat a null return from a 
provider as a one-way
+     */
+    public void testProviderReturnsNull() throws Exception {
+        TestLogger.logger.debug("---------------------------------------");
+        TestLogger.logger.debug("test: " + getName());
+        
+        Service svc = Service.create(serviceName);
+        svc.addPort(portName, bindingID, endpointUrl);
+
+        javax.xml.ws.Dispatch<SOAPMessage> dispatch = null;
+        dispatch = svc.createDispatch(portName, SOAPMessage.class, mode);
+
+        SOAPMessage message = 
AttachmentUtil.toSOAPMessage(AttachmentUtil.msgEnvPlain);
+        try {
+            dispatch.invokeOneWay(message);
+        }catch(Exception e){
+            e.printStackTrace();
+            fail("Caught exception " + e);
+        }
+        
+        // Try again to verify
+        try {
+            dispatch.invokeOneWay(message);
+        }catch(Exception e){
+            e.printStackTrace();
+            fail("Caught exception " + e);
+        }
+    } 
+
+            
+            }

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SourceProviderTests.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SourceProviderTests.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SourceProviderTests.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/SourceProviderTests.java
 Thu Jul  8 20:19:47 2010
@@ -235,6 +235,34 @@ public class SourceProviderTests extends
         assertTrue(response == null);
     }
     
+   
+    public void testProviderReturnsNull() throws Exception {
+        TestLogger.logger.debug("---------------------------------------");
+        TestLogger.logger.debug("test: " + getName());
+        
+        Dispatch<Source> dispatch = getDispatch();
+        
+        String request = "<test>ReturnNull</test>";
+        Source requestSource = getSource(request);
+        try {
+            requestSource = getSource(request);
+            dispatch.invokeOneWay(requestSource);
+        }catch(Exception e){
+            e.printStackTrace();
+            fail("Caught exception " + e);
+        }
+        
+        // Try again to verify
+        try {
+            requestSource = getSource(request);
+            dispatch.invokeOneWay(requestSource);
+        }catch(Exception e){
+            e.printStackTrace();
+            fail("Caught exception " + e);
+        }
+
+    }
+        
     public void testTwoElementsString() throws Exception {
         TestLogger.logger.debug("---------------------------------------");
         TestLogger.logger.debug("test: " + getName());

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/StringProviderTests.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/StringProviderTests.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/StringProviderTests.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/StringProviderTests.java
 Thu Jul  8 20:19:47 2010
@@ -54,6 +54,20 @@ public class StringProviderTests extends
         return dispatch;
         
     }
+    private Dispatch<String> getDispatchOneway() {
+        Service svc = Service.create(serviceName);
+        svc.addPort(portName, null, endpointUrl);
+        
+        Dispatch<String> dispatch = svc
+                .createDispatch(portName, String.class, Service.Mode.PAYLOAD);
+        
+        // Force soap action because we are passing junk over the wire
+        
dispatch.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, 
Boolean.TRUE);
+        
dispatch.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY,"http://stringprovider.sample.test.org/echoStringOneway";);
+        
+        return dispatch;
+        
+    }
     public void testNormal() throws Exception {
         TestLogger.logger.debug("---------------------------------------");
         TestLogger.logger.debug("test: " + getName());
@@ -219,4 +233,62 @@ public class StringProviderTests extends
             assertTrue(sf.getFaultString().equals("provider"));
         }
     }
+    /**
+     * Test that for an Operation defined as two-way in WSDL returns a 
+     * response even if the Provider returns null and 
+     * jaxws.provider.interpretNullAsOneway property is set
+     * @throws Exception
+     */
+    public void testProviderReturnsNull() throws Exception {
+        TestLogger.logger.debug("---------------------------------------");
+        TestLogger.logger.debug("test: " + getName());
+        
+        Dispatch<String> dispatch = getDispatch();
+        String request = "<invoke>returnNull</invoke>";
+        try {
+            String response = dispatch.invoke(request);
+            assertTrue(response == null);
+        } catch (SOAPFaultException e) {
+            fail("Exception caught : " + e);
+}        
+        // Try again to verify
+        try {
+            String response = dispatch.invoke(request);
+            assertTrue(response == null);
+        } catch (SOAPFaultException e) {
+            fail("Exception caught : " + e);
+        }
+        
+    }
+    /**
+     * Test that for an Operation defined as one-way in WSDL is 
+     * not effected if the Provider returns null, even if the 
+     * jaxws.provider.interpretNullAsOneway property is set
+     * @throws Exception
+     */
+    public void testProviderReturnsNullOneway() throws Exception {
+        TestLogger.logger.debug("---------------------------------------");
+        TestLogger.logger.debug("test: " + getName());
+
+        Dispatch<String> dispatch = getDispatchOneway();
+        // Because the operation is defined in WSDL, it should not be 
+        // effected by the property
+        ((BindingProvider) dispatch).getRequestContext()
+        .put(org.apache.axis2.jaxws.Constants.JAXWS_PROVIDER_NULL_ONEWAY, 
Boolean.FALSE);
+
+        String request = "<invoke>returnNull</invoke>";
+        try {
+            dispatch.invokeOneWay(request);
+        } catch (SOAPFaultException e) {
+            fail("Exception caught : " + e);
+        }
+
+        // Try again to verify
+        try {
+            dispatch.invokeOneWay(request);
+        } catch (SOAPFaultException e) {
+            fail("Exception caught : " + e);
+        }
+    }
+
 }
\ No newline at end of file

Added: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/META-INF/MANIFEST.MF
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/META-INF/MANIFEST.MF?rev=961916&view=auto
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/META-INF/MANIFEST.MF
 (added)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/META-INF/MANIFEST.MF
 Thu Jul  8 20:19:47 2010
@@ -0,0 +1 @@
+Manifest-Version: 1.0

Added: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/SoapMessageNullProvider.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/SoapMessageNullProvider.java?rev=961916&view=auto
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/SoapMessageNullProvider.java
 (added)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/soapmsgreturnnull/SoapMessageNullProvider.java
 Thu Jul  8 20:19:47 2010
@@ -0,0 +1,47 @@
+/*
+ * 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.provider.soapmsgreturnnull;
+
+import javax.xml.soap.SOAPMessage;
+import javax.xml.ws.BindingType;
+import javax.xml.ws.Provider;
+import javax.xml.ws.Service;
+import javax.xml.ws.ServiceMode;
+import javax.xml.ws.WebServiceProvider;
+import javax.xml.ws.soap.SOAPBinding;
+import javax.xml.ws.soap.SOAPFaultException;
+
+import org.apache.axis2.jaxws.TestLogger;
+
+...@webserviceprovider(serviceName="SoapMessageNullProviderService",
+               
targetNamespace="http://soapmsgreturnnull.provider.jaxws.axis2.apache.org";,
+               portName="SoapMessageNullProviderPort")
+...@bindingtype(SOAPBinding.SOAP11HTTP_BINDING)
+...@servicemode(value=Service.Mode.MESSAGE)
+public class SoapMessageNullProvider implements Provider<SOAPMessage> {
+      
+    
+    public SOAPMessage invoke(SOAPMessage soapMessage) throws 
SOAPFaultException {
+        TestLogger.logger.debug(">> SoapMessageNullProvider: Request 
received.");
+        return null;
+    }
+    
+
+}

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/source/SourceProvider.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/source/SourceProvider.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/source/SourceProvider.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/source/SourceProvider.java
 Thu Jul  8 20:19:47 2010
@@ -80,6 +80,8 @@ public class SourceProvider implements P
            "<detail>sample SOAP Fault details</detail>" +
            "</soapenv:Fault>";
            text = userFault;
+        }  else if (text != null && text.contains("ReturnNull")) {
+            return null;
        }
         
        

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/META-INF/echostring.wsdl
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/META-INF/echostring.wsdl?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/META-INF/echostring.wsdl
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/META-INF/echostring.wsdl
 Thu Jul  8 20:19:47 2010
@@ -36,6 +36,13 @@
                </xsd:sequence>
        </xsd:complexType>
       </xsd:element>
+            <xsd:element name="echoOneway">
+       <xsd:complexType>
+               <xsd:sequence>
+                       <xsd:element name="A" type="xsd:string"></xsd:element>
+               </xsd:sequence>
+       </xsd:complexType>
+      </xsd:element>
     </xsd:schema>
   </wsdl:types>
   <wsdl:message name="echoResponse">
@@ -44,11 +51,17 @@
   <wsdl:message name="echo">
     <wsdl:part element="tns:echo" name="echo"/>
   </wsdl:message>
+  <wsdl:message name="echoOneway">
+    <wsdl:part element="tns:echoOneway" name="echoOneway"/>
+  </wsdl:message>
   <wsdl:portType name="StringProviderPortType">
     <wsdl:operation name="echoString">
       <wsdl:input message="tns:echo"/>
       <wsdl:output message="tns:echoResponse"/>
     </wsdl:operation>
+    <wsdl:operation name="echoStringOneway">
+      <wsdl:input message="tns:echoOneway"/>
+    </wsdl:operation>
   </wsdl:portType>
   <wsdl:binding name="StringProviderBinding" type="tns:StringProviderPortType">
     <soap:binding style="document" 
transport="http://schemas.xmlsoap.org/soap/http"/>
@@ -61,6 +74,12 @@
         <soap:body use="literal"/>
       </wsdl:output>
     </wsdl:operation>
+    <wsdl:operation name="echoStringOneway">
+      <soap:operation 
soapAction="http://stringprovider.sample.test.org/echoStringOneway"/>
+      <wsdl:input>
+        <soap:body use="literal"/>
+      </wsdl:input>
+    </wsdl:operation>
   </wsdl:binding>
   <wsdl:service name="StringProviderService">
     <wsdl:port binding="tns:StringProviderBinding" name="StringProviderPort">

Modified: 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/StringProvider.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/StringProvider.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/StringProvider.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws-integration/test/org/apache/axis2/jaxws/provider/string/StringProvider.java
 Thu Jul  8 20:19:47 2010
@@ -42,6 +42,8 @@ public class StringProvider implements P
             return " ";
         } else if (text.contains("throwWebServiceException")) {
             throw new WebServiceException("provider");
+        } else if (text.contains("returnNull")) {
+            return null;
         } else if (text.contains("<Code>") && 
text.contains("SOAPFaultProviderTests")) { 
             // Make sure the received fault has the Reason string
             if (text.contains("<Reason>")) {

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=961916&r1=961915&r2=961916&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
 Thu Jul  8 20:19:47 2010
@@ -78,6 +78,37 @@ public interface Constants {
     public static final String JAXWS_PAYLOAD_HIGH_FIDELITY =
         "jaxws.payload.highFidelity";
     
+    /**
+     * Context Property:
+     * Name: jaxws.provider.interpretNullAsOneway
+     * Value: Boolean.TRUE or Boolean.FALSE
+     * Default: TRUE.
+     * 
+     * Configuration Parameter
+     * Name: jaxws.provider.interpretNullAsOneway
+     * Value: String or Boolean representing true or false
+     * Default: true
+     * 
+     * Description:
+     * If the value is false, the jax-ws engine will interpret a null response 
from a provider as an empty
+     * response to a two-way operation.  As a result it will create a 
SOAPEnvelope with an empty SOAPBody and send that
+     * as a response.
+     * 
+     * If the value is true, the jax-ws engine will intrepret a null return 
value from a provider as an indication of 
+     * a one-way operation.  As a result, the engine will halt processing on 
the response.  Response handlers will not
+     * be invoked.  An HTTP acknowledgment will be sent back to the client.  
No SOAPEnvelope will be sent.  You must use
+     * one-way client when invoking a Provider which returns null if this 
property is true.
+     * 
+     * This is only true for operations which are not defined in WSDL.  If the 
operation is defined in WSDL, the WSDL
+     * determine the response for a Provider that returns null.  If the WSDL 
defines a two-way operation, a null
+     * from a provider will continue to produce a SOAPEnvelope with and empty 
SOAPBody as the response.
+     * 
+     * The engine will first examine the Context property.  If not set, the 
value of the Configuration
+     * property is used.
+     */
+    public static final String JAXWS_PROVIDER_NULL_ONEWAY =
+        "jaxws.provider.interpretNullAsOneway";
+    
     public static final String MEP_CONTEXT = 
         "org.apache.axis2.jaxws.handler.MEPContext";
     

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/core/util/MessageContextUtils.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/core/util/MessageContextUtils.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/core/util/MessageContextUtils.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/core/util/MessageContextUtils.java
 Thu Jul  8 20:19:47 2010
@@ -20,12 +20,17 @@
 package org.apache.axis2.jaxws.core.util;
 
 import org.apache.axis2.AxisFault;
+import org.apache.axis2.description.Parameter;
 import org.apache.axis2.jaxws.ExceptionFactory;
 import org.apache.axis2.jaxws.core.MessageContext;
+import org.apache.axis2.util.JavaUtils;
 import org.apache.axis2.util.MessageContextBuilder;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 
 /** A utility class for handling some of the common issues related to the 
JAX-WS MessageContext. */
 public class MessageContextUtils {
+    private static Log log = LogFactory.getLog(MessageContextUtils.class);
 
     /**
      * Given a request MessageContext, create a new MessageContext from there 
with the necessary
@@ -93,5 +98,43 @@ public class MessageContextUtils {
             throw ExceptionFactory.makeWebServiceException(e);
         }
     }
+    
+    public static boolean getJaxwsProviderInterpretNullOneway(MessageContext 
mc){
+        boolean retval = true;  // default is true
+        org.apache.axis2.context.MessageContext ac = 
mc.getAxisMessageContext();
+        if (ac == null) {
+            if (log.isDebugEnabled()) {
+                log.debug("getJaxwsProviderInterpretNullOneway returns true 
due to missing MessageContext");
+            }
+            return retval;
+        }
+        // First examine the JaxwsProviderInterpretNullOneway flag on the 
context hierarchy
+        Boolean providerNullOneway = (Boolean) ac.getProperty(
+                org.apache.axis2.jaxws.Constants.JAXWS_PROVIDER_NULL_ONEWAY);
+        if (providerNullOneway != null) {
+            retval = providerNullOneway.booleanValue();
+            if (log.isDebugEnabled()) {
+                log.debug("getJaxwsProviderInterpretNullOneway returns " + 
retval + " per Context property " + 
+                        
org.apache.axis2.jaxws.Constants.JAXWS_PROVIDER_NULL_ONEWAY);
+            }
+            return retval;
+        }
+        
+        // Now look at the JaxwsProviderInterpretNullOneway parameter
+        Parameter p = 
ac.getParameter(org.apache.axis2.jaxws.Constants.JAXWS_PROVIDER_NULL_ONEWAY);
+        if (p != null) {
+            retval = JavaUtils.isTrue(p.getValue());
+            if (log.isDebugEnabled()) {
+                log.debug("getJaxwsProviderInterpretNullOneway returns " + 
retval + " per inspection of Configuration property " + 
+                        
org.apache.axis2.jaxws.Constants.JAXWS_PROVIDER_NULL_ONEWAY);
+            }
+            return retval;
+        }
+      
+        if (log.isDebugEnabled()) {
+            log.debug("getJaxwsProviderInterpretNullOneway returns the default 
value: " + retval);
+        }
+        return retval;
+    }
 
 }

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerChainProcessor.java
 Thu Jul  8 20:19:47 2010
@@ -216,8 +216,20 @@ public class HandlerChainProcessor {
 
        }
 
+    public boolean processChainForClose(MEPContext mepCtx, Direction 
direction) {
 
-    /*
+        boolean result = true;
+        if (handlers.size() == 0)
+            return true;
+        
+        this.mepCtx = mepCtx;
+        sortChain();
+        initContext(direction);
+        callCloseHandlers(handlers.size() - 1, 0, direction);
+        return result;
+    }
+    
+     /*
       * This is the implementation of JAX-WS 2.0 section 9.3.2.1
       */
     private boolean callGenericHandlers(MEP mep, boolean expectResponse, int 
start, int end,

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerInvokerUtils.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerInvokerUtils.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerInvokerUtils.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/handler/HandlerInvokerUtils.java
 Thu Jul  8 20:19:47 2010
@@ -152,5 +152,49 @@ public class HandlerInvokerUtils {
         return true;
 
     }
+    /**
+     * Invoke Inbound Handlers
+     * @param requestMsgCtx
+     */
+    public static boolean invokeInboundHandlersForClosure(MEPContext 
mepMessageCtx, List<Handler> handlers,
+                                                HandlerChainProcessor.MEP mep) 
{
 
+        if (handlers == null || handlers.isEmpty()) 
+            return true;
+        if(log.isDebugEnabled()){
+            log.debug("invokeInboundHandlersForClosure Entry");
+        }
+
+        String bindingProto = null;
+        if (mep.equals(HandlerChainProcessor.MEP.REQUEST)) // inbound request; 
must be on the server
+            bindingProto = mepMessageCtx.getEndpointDesc().getBindingType();
+        else {
+            // inbound response; must be on the client
+            bindingProto = 
mepMessageCtx.getEndpointDesc().getClientBindingID();
+        }
+        Protocol proto = Protocol.getProtocolForBinding(bindingProto);
+
+        HandlerChainProcessor processor = new HandlerChainProcessor(handlers, 
proto);
+        // if not one-way, expect a response
+        boolean success = true;
+        try {
+                success =
+                        processor.processChainForClose(mepMessageCtx,
+                                               
HandlerChainProcessor.Direction.OUT);
+        } catch (RuntimeException re) {
+            /*
+             * handler framework should never throw an exception on close
+             */
+            if(log.isDebugEnabled()){
+                log.debug("invokeInboundHandlersForClosure caught exception 
from close: " + re);
+                log.debug("invokeInboundHandlersForClosure returning false");
+            }
+            return false;
+        }
+        if(log.isDebugEnabled()){
+            log.debug("invokeInboundHandlersForClosure Exit");
+        }
+
+        return true;
+    }
 }

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/EndpointController.java
 Thu Jul  8 20:19:47 2010
@@ -35,6 +35,7 @@ import org.apache.axis2.jaxws.descriptio
 import org.apache.axis2.jaxws.handler.HandlerChainProcessor;
 import org.apache.axis2.jaxws.handler.HandlerInvocationContext;
 import org.apache.axis2.jaxws.handler.HandlerInvoker;
+import org.apache.axis2.jaxws.handler.HandlerInvokerUtils;
 import org.apache.axis2.jaxws.handler.HandlerResolverImpl;
 import org.apache.axis2.jaxws.handler.HandlerUtils;
 import org.apache.axis2.jaxws.handler.factory.HandlerInvokerFactory;
@@ -108,6 +109,7 @@ public class EndpointController {
             EndpointDispatcher dispatcher = eic.getDispatcher();
             if (request != null && dispatcher != null) {
                 response = dispatcher.invoke(request);    
+                // Note that response may be null in the case of a Provider 
returning null
                 eic.setResponseMessageContext(response);
             }
             else {
@@ -390,6 +392,14 @@ public class EndpointController {
                     handlerInvoker.invokeOutboundHandlers(hiContext);
                     
                }
+           } else {  // reponse is null.  
+               if 
(MessageContextUtils.getJaxwsProviderInterpretNullOneway(request)){
+                   // Provider must have returned null, and property is set.
+                   // so now we only need to call closure
+                   
HandlerInvokerUtils.invokeInboundHandlersForClosure(request.getMEPContext(),
+                           eic.getHandlers(),
+                           HandlerChainProcessor.MEP.RESPONSE);
+               }
            } 
         } catch (Exception e) {
             // TODO for now, throw it.  We probably should try to make an 
XMLFault object and set it on the message

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/JAXWSMessageReceiver.java
 Thu Jul  8 20:19:47 2010
@@ -31,7 +31,8 @@ import org.apache.axis2.engine.MessageRe
 import org.apache.axis2.jaxws.ExceptionFactory;
 import org.apache.axis2.jaxws.core.InvocationContextFactory;
 import org.apache.axis2.jaxws.core.MessageContext;
-import org.apache.axis2.jaxws.description.DescriptionFactory;
+import org.apache.axis2.jaxws.core.util.MessageContextUtils;
+
 import org.apache.axis2.jaxws.description.EndpointDescription;
 import org.apache.axis2.jaxws.description.ServiceDescription;
 import org.apache.axis2.jaxws.handler.AttachmentsAdapter;
@@ -42,6 +43,7 @@ import org.apache.axis2.jaxws.i18n.Messa
 import org.apache.axis2.jaxws.message.util.MessageUtils;
 import org.apache.axis2.jaxws.registry.InvocationListenerRegistry;
 import org.apache.axis2.jaxws.util.Constants;
+import org.apache.axis2.transport.RequestResponseTransport;
 import org.apache.axis2.util.JavaUtils;
 import org.apache.axis2.util.ThreadContextMigratorUtil;
 import org.apache.axis2.wsdl.WSDLConstants.WSDL20_2004_Constants;
@@ -163,31 +165,42 @@ public class JAXWSMessageReceiver implem
                 // the Message data out of there and set it on the Axis2 
                 // MessageContext.
                 MessageContext responseMsgCtx = 
eic.getResponseMessageContext();
-                org.apache.axis2.context.MessageContext axisResponseMsgCtx =
+                // Note that responseMsgCtx may be null if the Provider 
returned null
+                // and no wsdl was specified.
+                // In JAX-WS 2.2 for Providers that return null we should send 
back
+                // an empty payload, not a SOAPEnvelope.
+                if (responseMsgCtx == null &&
+                        
MessageContextUtils.getJaxwsProviderInterpretNullOneway(requestMsgCtx)) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Detected a null return from a Provider, 
sending back an ack instead of a response.");
+                    }
+                    sendAckBack(axisRequestMsgCtx);                   
+                } else {
+                    org.apache.axis2.context.MessageContext axisResponseMsgCtx 
=
                         responseMsgCtx.getAxisMessageContext();
-                if (loader != null) {
-                    
responseMsgCtx.setProperty(org.apache.axis2.jaxws.spi.Constants.CACHE_CLASSLOADER,
-                            loader);
-                }
-                
MessageUtils.putMessageOnMessageContext(responseMsgCtx.getMessage(),
-                                                        axisResponseMsgCtx);
+                    if (loader != null) {
+                        
responseMsgCtx.setProperty(org.apache.axis2.jaxws.spi.Constants.CACHE_CLASSLOADER,
+                                loader);
+                    }
+                    
MessageUtils.putMessageOnMessageContext(responseMsgCtx.getMessage(),
+                            axisResponseMsgCtx);
 
-                OperationContext opCtx = 
axisResponseMsgCtx.getOperationContext();
-                opCtx.addMessageContext(axisResponseMsgCtx);
+                    OperationContext opCtx = 
axisResponseMsgCtx.getOperationContext();
+                    opCtx.addMessageContext(axisResponseMsgCtx);
 
-                // If this is a fault message, we want to throw it as an
-                // exception so that the transport can do the appropriate 
things
-                if (responseMsgCtx.getMessage().isFault()) {
-                    
-                    //Rather than create a new AxisFault, we should use the 
AxisFault that was
-                    //created at the causedBy
-                    if (responseMsgCtx.getCausedByException() != null)
-                        faultToReturn = responseMsgCtx.getCausedByException();
-                    else {
-                        faultToReturn = new AxisFault("An error was detected 
during JAXWS processing",
-                                                          axisResponseMsgCtx);
-                    }
-                } else {
+                    // If this is a fault message, we want to throw it as an
+                    // exception so that the transport can do the appropriate 
things
+                    if (responseMsgCtx.getMessage().isFault()) {
+
+                        //Rather than create a new AxisFault, we should use 
the AxisFault that was
+                        //created at the causedBy
+                        if (responseMsgCtx.getCausedByException() != null)
+                            faultToReturn = 
responseMsgCtx.getCausedByException();
+                        else {
+                            faultToReturn = new AxisFault("An error was 
detected during JAXWS processing",
+                                    axisResponseMsgCtx);
+                        }
+                    } else {
                     //This assumes that we are on the ultimate execution thread
                     ThreadContextMigratorUtil.performMigrationToContext(
                             Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, 
axisResponseMsgCtx);
@@ -199,7 +212,7 @@ public class JAXWSMessageReceiver implem
                             Constants.THREAD_CONTEXT_MIGRATOR_LIST_ID, 
axisResponseMsgCtx);
                 }
             }
-
+            }
         } catch (AxisFault af) {
             throw af;
         } catch (Exception e) {
@@ -227,8 +240,29 @@ public class JAXWSMessageReceiver implem
             throw faultToReturn;
         }
     }
+    
+    private void sendAckBack(org.apache.axis2.context.MessageContext 
axisMsgCtx){
+        if (log.isDebugEnabled()) {
+            log.debug("sendAckBack entry");
+        }
 
+        try {
+            Object requestResponseTransport =
+                
axisMsgCtx.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
+            if (requestResponseTransport != null) {
+                ((RequestResponseTransport) 
requestResponseTransport).acknowledgeMessage(axisMsgCtx);
+            }
+        }catch (Exception e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Ignoring exception from acknowledgeMessage.", e);
+            }
+        }
+        if (log.isDebugEnabled()) {
+            log.debug("sendAckBack exit");
+        }
 
+    }
+ 
     private boolean isMepInOnly(String mep) {
         boolean inOnly = 
mep.equals(WSDL20_2004_Constants.MEP_URI_ROBUST_IN_ONLY) ||
                 mep.equals(WSDL20_2004_Constants.MEP_URI_IN_ONLY) ||

Modified: 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/ProviderDispatcher.java
URL: 
http://svn.apache.org/viewvc/axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/ProviderDispatcher.java?rev=961916&r1=961915&r2=961916&view=diff
==============================================================================
--- 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/ProviderDispatcher.java
 (original)
+++ 
axis/axis2/java/core/trunk/modules/jaxws/src/org/apache/axis2/jaxws/server/dispatcher/ProviderDispatcher.java
 Thu Jul  8 20:19:47 2010
@@ -146,6 +146,20 @@ public class ProviderDispatcher extends 
             // MessageContext, than in the response path.
             responseMsgCtx = createFaultResponse(request, fault);
             setExceptionProperties(responseMsgCtx, target, fault);
+        } else if(responseParamValue == null && 
+                
MessageContextUtils.getJaxwsProviderInterpretNullOneway(request) &&
+                
!request.getAxisMessageContext().getAxisService().isWsdlFound()) {
+            // If the Provider returned null, we will interpret this as a 
one-way op if
+            // - the custom property jaxws.provider.interpretNullAsOneway is 
true AND
+            // - the operation was NOT wsdl defined.   
+            if (log.isDebugEnabled()) {
+                log.debug("detected null return from Provider, " + target + 
+                        "and operation is not wsdl defined and " +
+                "interpretNullAsOneway property is true.");
+            }
+            // JAXWS 2.2 If Provider returns null, an empty response is given 
(no SOAPEnvelope)
+            responseMsgCtx = null; // return null, JAXWSMessageReceiver will 
interpret as one-way
+
         } else {
             responseMsgCtx = createResponse(request, input, 
responseParamValue);
         }


Reply via email to