How do I return a (custom) SOAPFault from an Axis web service?

The Archetypal Paul picture The Archetypal Paul · Jun 12, 2011 · Viewed 7.4k times · Source

I have some WSDL from which I need to generate a web service implementation. I'm using Eclipse, and Axis1.4, and running on Weblogic9.2.

Generating the server stubs goes fine, and I've implemented the code I need to. However, for compatibility with the exising implementation we are emulating, I need to return SOAP faults for some specified error conditions.

That is, I need the SOAP body of the response to look like this example:

<soapenv:Body>
    <soapenv:Fault>
        <faultcode xmlns:ns1="foobar">ns1:1234</faultcode>
        <faultstring>The supplied parameter name ABCD is not recognised.</faultstring>
        <detail>
            <FaultDetail>An error processing the web service [MyService]: Unknown parameter:ABCD</FaultDetail>
            <ns2:hostname xmlns:ns2="http://xml.apache.org/axis/">planet</ns2:hostname>
        </detail>
    </soapenv:Fault>
</soapenv:Body>

From (much) googling, I think I should be able to do this by throwing a SOAPFaultException. But the message stub throws only java.rmi.RemoteException, so I've tried passing the SOAPFaultException to the RemoteException. That gives me something like this:

   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server.userException</faultcode>
         <faultstring>java.rmi.RemoteException: My remote exception; nested exception is: 
    javax.xml.rpc.soap.SOAPFaultException: soap fault string</faultstring>
         <detail>
            <ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">myhostname</ns1:hostname>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>

... in other words, it hasn't resulted in a SOAP fault.

I've tried a lot of other stuff, and I'm pretty much stuck. So can someone tell me (ideally with an example) how to return a SOAP fault response with content I can specify, in my environment?

I'm not wedded to using Axis (but I've more experience with that than anything else). If you suggest an alternative, please note I need in the web service method to invoke another (authenticated) web service, and I've only been able to get that to work in Axis1.4...

Answer

Al Baker picture Al Baker · Jun 12, 2011

Your second code post is a SOAP fault (note the soapenv:Fault inside the soapenv:Body).

Basically all of the frameworks's default behavior is to return the standard SOAP fault and provide you the ability to enter your own information in the fault code, fault string, and fault detail fields.

See the docs on the Axis 1 exception: http://ws.apache.org/axis/java/apiDocs/org/apache/axis/AxisFault.html

It has constructors for setting the qname of various fields, so you should be able to reference your own items there.

Many people will use the fault detail field and serialize their own XML type inside it using DOM.

Last but not least Axis1's prime time was circa 2000-2004, you will find it difficult to get answers and support around it. Most people have moved from Axis1 to Apache CXF, Axis2, or just straight up
JAX-WS (now included in JDK6+). There is also the Spring Web Services project, which provides full customization of all of the behaviors in the stack (marshalling, which bean gets executed, etc).

Just all of these frameworks use WSS4J for their web service security, and can support the standard username token, x509 token, etc. Nevertheless, once you get the basic messages being passed back and forth, you'll likely have to work through the details of WS-Security.