<!--
  ~ 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.
  -->

<html>
<head>
    <meta http-equiv="content-type" content="">
    <title>:: Exception Handling using WSDL Faults ::</title>
</head>

<body>
<h1>Exception Handling using WSDL Faults</h1>

<p>This sample demonstrates how to specify a WSDL fault in order to allow
    your service to communicate exception pathways to your clients.</p>

<p>Running of this sample assumes that you are running this within the
    extracted release folder.</p>

<h2>Constructing the Service and Client</h2>

<p>The first step is to generate the service skeleton and other interface
    classes from the WSDL.</p>

<p>Look at <em><a href="../bank.wsdl">bank.wsdl</a></em>. It defines the
    interface for our service. Of particular interest are the
    <strong>AccountNotExistFault</strong> and
    <strong>InsufficientFundFault</strong> types defined in the wsdl:types
    element.</p>

<p>Using a command prompt, got to the folder of this example and type
    <strong>ant generate.service</strong> or just <strong> ant</strong>. This
    will:</p>
<ul>
    <li>Generate the source for all the service classes in
        <em>build/service/src/example</em></li>
    <li>Generate <em>services.xml</em> and a more complete
        <em>BankService.wsdl</em> into the <em>build/service/resources</em>
        folder.</li>
    <li>Generate a <em>build/service/build.xml</em></li>
    <li>Copies the pre-populated service skeleton class to the generated
        code</li>
    <li>Compile the Java classes for the service</li>
    <li>Create the service archive and copy it to Axis2 repository
        (<em>repository/services/</em>) as sample-faulthandling.aar.</li>
</ul>

<p>Open up <em>service/src/example/BankServiceSkeleton.java</em> and you will
    see the following code fragment inside <strong>#withdraw</strong> method.
    When <strong>generate.service</strong> has been executed, Axis2 generates a skeleton class
    (<em>build/service/src/example/BankServiceSkeleton.java</em>) which has an empty method.
    We replace it, the genedrated skeleton with a pre-populated skeleton class
    (<em>service/src/example/BankServiceSkeleton.java</em>) which has the
    following code inside it.</p>
<pre> final String account = param0.getAccount();
    if (account.equals("13")) {
    final AccountNotExistFault fault = new AccountNotExistFault();
    fault.setAccount(account);
    AccountNotExistFaultMessageException messageException = new
    AccountNotExistFaultMessageException("Account does
    not exist!");
    messageException.setFaultMessage(fault);
    throw messageException;
    }

    final int amount = param0.getAmount();
    if (amount &gt; 1000) {
    final InsufficientFundFault fault = new InsufficientFundFault();
    fault.setAccount(account);
    fault.setBalance(1000);
    fault.setRequestedFund(amount);
    InsufficientFundFaultMessageException messageException = new
    InsufficientFundFaultMessageException("Insufficient
    funds");
    messageException.setFaultMessage(fault);
    throw messageException;
    }

    final WithdrawResponse response = new WithdrawResponse();
    response.setBalance(1000 - amount);
    return response;
</pre>

<p>Note that the source generated for the client will include the 2 faults
    and the local Exceptions through which they will be transmitted. Also note
    that the Exceptions are generated within the <em>BankStub</em> class.</p>

<h2>Deploying the Service</h2>

<p>The above step must have already copied your BankService.aar file in to
    <em>repository/services/</em> folder. Then go to <em>bin</em> folder and run
    either of axis2server.bat or axis2server.sh, depending on your platform in
    order to startup Axis2 server.</p>

<p>With the default configuration, if you go to <a
        href="http://localhost:8080/axis2/"> http://localhost:8080/axis2/</a> you
    should see <em>BankService</em> was deployed.</p>

<h2>Running the Client</h2>

<p>Invoke the <em>client/src/example/BankClient</em>.java class. You may use
    the command scripts to do so. You need to supply 3 parameters to the command-
    url, account and amount.</p>
<ul>
    <li><strong>ant run.client
        -Durl=http://localhost:8080/axis2/services/BankService -Daccount=13
        -Damt=400</strong><br>
        Throws AccountNotExistFaultMessageException. You will see "Account#13
        does not exist"</li>
    <li><strong>ant run.client
        -Durl=http://localhost:8080/axis2/services/BankService -Daccount=88
        -Damt=1200</strong><br>
        Throws InsufficientFundsFaultMessageException. You will see "Account#88
        has balance of 1000. It cannot support withdrawal of 1200"<br>
 </li>
    <li><strong>ant run.client
        -Durl=http://localhost:8080/axis2/services/BankService -Daccount=88
        -Damt=400</strong><br>
        Succeeds with a balance of 600. You will see "Balance = 600"</li>
</ul>
When you call ant run.client with parameters, before running
<em>client/src/example/BankClient.java</em> class, it does the following as
well:
<ul>
    <li>Generate the stubs (for the client) from the WSDL</li>
    <li>Compile the client classes</li>
    <li>Create a Jar of the client classes and copy it to
        <em>build/client/BankService-test-client.jar</em></li>
</ul>
</body>
</html>
