I know it's bad manners to reply to my own post but I thought I should update anyone who might be interested.

After further study I realized that the internal fault I was causing was due to the fact that I was returning a null from my service implementation method and the generated service code expects a reference to an instance of the correct return type (it was also occurring in both the SOAP 1.2 and SOAP 1.1 cases).

After looking at this example (http://tinyurl.com/6t7bnk) I realized I'm supposed to throw an AxisFault after loading the MessageContext with my fault information. This avoids the NPE caused by the attempt to dereference the non-existent return type object. Unfortunately, I'm working from a WSDL and the generated endpoint interface does not contain a "throw AxisFault" declaration, so the best I can do is throw a RuntimeException.

Again, for the SOAP 1.2 case this seems to work. The properties I've set in the MC seem to override the mapping of the RuntimeException to the SOAP Fault. However, in the SOAP 1.1 case, this does not work. What I basically end up with is the same SOAP Fault message I would get if I just threw the RuntimeException; populating the MC doesn't seem to have any effect.

The upside is I've figured out that, in the SOAP 1.1 case:

throw new RuntimeException("invalid input");

causes the <faultstring> element to contain "invalid input" (<faultcode> is still "Server" though).

- gp

Gilbert Pilz wrote:
Hi,

I'm trying to figure out make my service return a custom SOAP Faults for both SOAP 1.1 and SOAP 1.2. Basically all I want is the appropriate code for "the client/sender screwed up" and a simple string that says "you sent me some bad text". While this page (http://wso2.org/library/171) was super-helpful in building the SOAP 1.2 Fault, the example code it provides doesn't seem to apply to SOAP 1.1.

Here's my code:

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAP11Constants;
import org.apache.axiom.soap.SOAP12Constants;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPFaultCode;
import org.apache.axiom.soap.SOAPFaultReason;
import org.apache.axiom.soap.SOAPFaultText;
import org.apache.axiom.soap.SOAPFaultValue;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axis2.context.MessageContext;

. . .

String faultString = "invalid input: \"" + text + "\"";

SOAPFactory soapFactory;
String faultCodeLocalName;
QName faultValueQName;
String faultReasonLocalName;

if (inMessageContext.isSOAP11())
{
    soapFactory = OMAbstractFactory.getSOAP11Factory();
    faultCodeLocalName = SOAP11Constants.SOAP_FAULT_CODE_LOCAL_NAME;
    faultValueQName = SOAP11Constants.QNAME_SENDER_FAULTCODE;
    faultReasonLocalName = SOAP11Constants.SOAP_FAULT_STRING_LOCAL_NAME;
}
else
{
    soapFactory = OMAbstractFactory.getSOAP12Factory();
    faultCodeLocalName = SOAP12Constants.SOAP_FAULT_CODE_LOCAL_NAME;
    faultValueQName = SOAP12Constants.QNAME_SENDER_FAULTCODE;
    faultReasonLocalName = SOAP12Constants.SOAP_FAULT_REASON_LOCAL_NAME;
}
           
SOAPFaultCode soapFaultCode = soapFactory.createSOAPFaultCode();
SOAPFaultValue soapFaultValue = soapFactory.createSOAPFaultValue(soapFaultCode);
soapFaultValue.setText(faultValueQName);
inMessageContext.setProperty(faultCodeLocalName, soapFaultCode);
           
SOAPFaultReason soapFaultReason = soapFactory.createSOAPFaultReason();
SOAPFaultText soapFaultText = soapFactory.createSOAPFaultText(soapFaultReason);
soapFaultText.setText(faultString);
inMessageContext.setProperty(faultReasonLocalName, soapFaultReason);

When I run this in the context of a SOAP 1.2 request I get the correct response, which is the following:

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Body>
      <soapenv:Fault>
         <soapenv:Code>
            <soapenv:Value>soapenv:Sender</soapenv:Value>
         </soapenv:Code>
         <soapenv:Reason>
            <soapenv:Text>invalid input: "fault"</soapenv:Text>
         </soapenv:Reason>
         <soapenv:Detail/>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

However, when I run this in the context of a SOAP 1.1 request I get the following:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server</faultcode>
         <faultstring>unknown</faultstring>
         <detail/>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

Notice that the faultcode is "Server" (even though the code sets it to "Client") and the faultstring is "unknown". It's pretty obvious that I'm doing something that caused an internal fault.

Can anyone tell me what I'm doing wrong in the SOAP 1.1 case? Is there a better/simpler way of generating and returning custom SOAP Faults?

- gp


Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to