Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
980 views
in Technique[技术] by (71.8m points)

web services - Custom faultcode using Axis2

I've created a webservice and used Axis2 to generate all "skeleton" java classes. Then I of course implemented the service operations myself.

In the implementation, I can throw a MyException which is then caught by the generated classes and converted to an AxisFault object, which in turn is converted to a soap fault (deep down in the Axis framework) with the attribute <faultcode>soapenv:Server</faultcode>

My problem is I would like a custom dynamic faultcode, not "soapenv:Server".

I tried to manually create an AxisFault object and throw this, but AxisFault is a RemoteException, and the generated interface which my implementation must implement, does not allow to throw RemoteException.

Is it possible to get some kind of hook or filter on the output, so that I can change the faultcode? Or any other way to control the faultcode?

Thanks in advance
Ulrik

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The SOAP specification describes how custom fault information appears under the detail tag. The faultcode is a fixed set of value dealing with where in the SOAP processing the error was thrown.

The following is an example of throwing a custom fault message

WSDL

Declare the faults in your WSDL so that the associated classes are generated:

<wsdl:definitions targetNamespace="http://example"
    xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:tns="http://example"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <wsdl:types>
        <schema elementFormDefault="qualified" targetNamespace="http://example"
            xmlns="http://www.w3.org/2001/XMLSchema"
            xmlns:apachesoap="http://xml.apache.org/xml-soap"
            xmlns:tns="http://example" xmlns:intf="http://example"
            xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">

            <element name="withdraw">
                <complexType>
                    <sequence>
                        <element name="account" type="xsd:string"/>
                        <element name="amount" type="xsd:int"/>
                    </sequence>
                </complexType>
            </element>

            <element name="withdrawResponse">
                <complexType>
                    <sequence>
                        <element name="balance" type="xsd:int"/>
                    </sequence>
                </complexType>
            </element>

            <element name="AccountNotExistFault">
                <complexType>
                    <sequence>
                        <element name="account" type="xsd:string"/>
                    </sequence>
                </complexType>
            </element>

            <element name="InsufficientFundFault">
                <complexType>
                    <sequence>
                        <element name="account" type="xsd:string"/>
                        <element name="balance" type="xsd:int"/>
                        <element name="requestedFund" type="xsd:int"/>
                    </sequence>
                </complexType>
            </element>

        </schema>
    </wsdl:types>

    <wsdl:message name="withdrawRequest">
        <wsdl:part element="tns:withdraw" name="parameters"/>
    </wsdl:message>

    <wsdl:message name="withdrawResponse">
        <wsdl:part element="tns:withdrawResponse" name="return"/>
    </wsdl:message>

    <wsdl:message name="InsufficientFundFaultMessage">
        <wsdl:part element="tns:InsufficientFundFault" name="fault"/>
    </wsdl:message>

    <wsdl:message name="AccountNotExistFaultMessage">
        <wsdl:part element="tns:AccountNotExistFault" name="fault"/>
    </wsdl:message>

    <wsdl:portType name="Bank">
        <wsdl:operation name="withdraw">
            <wsdl:input message="tns:withdrawRequest" name="withdrawRequest"/>
            <wsdl:output message="tns:withdrawResponse" name="withdrawResponse"/>
            <wsdl:fault message="tns:AccountNotExistFaultMessage" name="AccountNotExistException"/>
            <wsdl:fault message="tns:InsufficientFundFaultMessage" name="InsufficientFundException"/>
        </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="BankSoapBinding" type="tns:Bank">
        <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="withdraw">
            <wsdlsoap:operation soapAction=""/>
            <wsdl:input name="withdrawRequest">
                <wsdlsoap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="withdrawResponse">
                <wsdlsoap:body use="literal"/>
            </wsdl:output>
            <wsdl:fault name="InsufficientFundException">
                <wsdlsoap:fault name="InsufficientFundException" use="literal"/>
            </wsdl:fault>
            <wsdl:fault name="AccountNotExistException">
                <wsdlsoap:fault name="AccountNotExistException" use="literal"/>
            </wsdl:fault>
        </wsdl:operation>
    </wsdl:binding>

    <wsdl:service name="BankService">
        <wsdl:port binding="tns:BankSoapBinding" name="Bank">
            <wsdlsoap:address location="http://localhost:8080/bank/services/Bank"/>
        </wsdl:port>
    </wsdl:service>

</wsdl:definitions>

Service code

The following code demonstrates how the custom fault messages are thrown:

package example;

public class BankServiceSkeleton {

    public  WithdrawResponse withdraw(Withdraw param1) throws InsufficientFundFaultMessage, AccountNotExistFaultMessage {

        //
        // Parameter handling
        //
        String account = param1.getAccount();
        int amount     = param1.getAmount();

        //
        // Error checks
        //
        if ("13".equals(account)) {
            AccountNotExistFault fault = new AccountNotExistFault();

            fault.setAccount(account);

            AccountNotExistFaultMessage ex = new AccountNotExistFaultMessage("Account does not exist!");
            ex.setFaultMessage(fault);
            throw ex;
        }

        if (amount > 1000) {
            InsufficientFundFault fault = new InsufficientFundFault();

            fault.setAccount(account);
            fault.setBalance(1000);
            fault.setRequestedFund(amount);

            InsufficientFundFaultMessage ex = new InsufficientFundFaultMessage("Insufficient funds");
            ex.setFaultMessage(fault);
            throw ex;
        }

        //
        // Normal response
        //
        WithdrawResponse response = new WithdrawResponse();

        response.setBalance(1000 - amount);

        return response;
    }
}

TESTING

The following SOAP message

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:exam="http://example">
   <soapenv:Header/>
   <soapenv:Body>
      <exam:withdraw>
         <exam:account>10</exam:account>
         <exam:amount>2000</exam:amount>
      </exam:withdraw>
   </soapenv:Body>
</soapenv:Envelope>

Generates the following SOAP fault response

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server</faultcode>
         <faultstring>Insufficient funds</faultstring>
         <detail>
            <ns1:InsufficientFundFault xmlns:ns1="http://example">
               <ns1:account>10</ns1:account>
               <ns1:balance>1000</ns1:balance>
               <ns1:requestedFund>2000</ns1:requestedFund>
            </ns1:InsufficientFundFault>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...