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); }