You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2004/12/09 15:36:14 UTC

cvs commit: ws-axis/java/src/org/apache/axis/handlers HandlerChainImpl.java

dims        2004/12/09 06:36:14

  Modified:    java/test/jaxrpc PackageTests.java TestSOAPService.java
               java/src/org/apache/axis/client AxisClient.java
               java/src/org/apache/axis/handlers HandlerChainImpl.java
  Added:       java/test/jaxrpc AJAXRPC.java TestAxisClient.java
  Log:
  Fix for  AXIS-1696 - JAXRPC Handlers behavior different from server-side to client-side
  from Guillaume Sauthier (guillaume.sauthier@objectweb.org)
  
  JIRA: http://nagoya.apache.org/jira/browse/AXIS-1696
  
  Revision  Changes    Path
  1.2       +1 -0      ws-axis/java/test/jaxrpc/PackageTests.java
  
  Index: PackageTests.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/test/jaxrpc/PackageTests.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PackageTests.java	7 Jul 2004 03:04:01 -0000	1.1
  +++ PackageTests.java	9 Dec 2004 14:36:14 -0000	1.2
  @@ -11,6 +11,7 @@
       public static junit.framework.Test suite() throws Exception {
           junit.framework.TestSuite suite = new junit.framework.TestSuite();
           suite.addTestSuite(test.jaxrpc.TestSOAPService.class);
  +        suite.addTestSuite(test.jaxrpc.TestAxisClient.class);
           return suite;
       }
   }
  
  
  
  1.2       +2 -112    ws-axis/java/test/jaxrpc/TestSOAPService.java
  
  Index: TestSOAPService.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/test/jaxrpc/TestSOAPService.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TestSOAPService.java	7 Jul 2004 03:04:01 -0000	1.1
  +++ TestSOAPService.java	9 Dec 2004 14:36:14 -0000	1.2
  @@ -22,37 +22,7 @@
   import java.util.Map;
   
   public class TestSOAPService
  -        extends TestCase {
  -    HandlerInfo handlerInfo0 = null;
  -    HandlerInfo handlerInfo1 = null;
  -    HandlerInfo handlerInfo2 = null;
  -
  -    Map handler0Config = null;
  -    Map handler1Config = null;
  -    Map handler2Config = null;
  -
  -    /**
  -     * Sets up the handlerInfo and handlerConfigs for all tests.
  -     * Each test has 3 JAX-RPC Handlers of the same type to keep things
  -     * simple.
  -     * 
  -     * @throws Exception 
  -     */
  -    protected void setUp() throws Exception {
  -        handlerInfo0 = new HandlerInfo();
  -        handlerInfo0.setHandlerClass(AAAHandler.class);
  -        handlerInfo1 = new HandlerInfo();
  -        handlerInfo1.setHandlerClass(AAAHandler.class);
  -        handlerInfo2 = new HandlerInfo();
  -        handlerInfo2.setHandlerClass(AAAHandler.class);
  -        handler0Config = new HashMap();
  -        handler1Config = new HashMap();
  -        handler2Config = new HashMap();
  -        handlerInfo0.setHandlerConfig(handler0Config);
  -        handlerInfo1.setHandlerConfig(handler1Config);
  -        handlerInfo2.setHandlerConfig(handler2Config);
  -    }
  -
  +        extends AJAXRPC {
       /**
        * All Handlers in Chain return true for handleRequest and handleResponse
        * <p/>
  @@ -371,87 +341,7 @@
               assertHandlerRuntime("handlerTwo", handlerTwo, 1, 0, 1);
           }
       }
  -
  -    /**
  -     * Convenience method to organize all test checking for a particular
  -     * handler.
  -     * <p/>
  -     * Checks to see if the expected number of calls to handleRequest, handleResponse
  -     * and handleFault reconciles with actuals
  -     * 
  -     * @param message           
  -     * @param handler           the target handler to reconcile
  -     * @param numHandleRequest  # of expected calls to handleRequest
  -     * @param numHandleResponse # of expected calls to handleResponse
  -     * @param numHandleFault    # of expected call to handleFault
  -     */
  -    protected void assertHandlerRuntime(String message, AAAHandler handler,
  -                                        int numHandleRequest,
  -                                        int numHandleResponse,
  -                                        int numHandleFault) {
  -        assertEquals(message + ": handleRequest", numHandleRequest,
  -                handler.getHandleRequestInvocations());
  -        assertEquals(message + ": handleResponse", numHandleResponse,
  -                handler.getHandleResponseInvocations());
  -        assertEquals(message + ": handleFault", numHandleFault,
  -                handler.getHandleFaultInvocations());
  -    }
  -
  -    /**
  -     * Convenience method to create a HandlerInfoChainFactory
  -     * 
  -     * @return 
  -     */
  -    protected TestHandlerInfoChainFactory buildInfoChainFactory() {
  -        List handlerInfos = new ArrayList();
  -        handlerInfos.add(handlerInfo0);
  -        handlerInfos.add(handlerInfo1);
  -        handlerInfos.add(handlerInfo2);
  -        TestHandlerInfoChainFactory factory = new TestHandlerInfoChainFactory(
  -                handlerInfos);
  -        return factory;
  -    }
  -
  -    /**
  -     * Mock Service Handler used to simulate a service object throwing
  -     * an AxisFault.
  -     */
  -    private class MockServiceHandler extends BasicHandler {
  -        public void invoke(MessageContext msgContext) throws AxisFault {
  -            throw new AxisFault();
  -        }
  -    }
  -
  -    /**
  -     * Helper class for keeping references to the JAX-RPC Handlers
  -     * that are created by the Factory.
  -     * <p/>
  -     * This class allows us to access the individual handlers after
  -     * the test case has been executed in order to make sure that
  -     * the expected methods of the handler instance have been invoked.
  -     */
  -    private class TestHandlerInfoChainFactory extends HandlerInfoChainFactory {
  -        AAAHandler[] handlers;
  -
  -        public TestHandlerInfoChainFactory(List handlerInfos) {
  -            super(handlerInfos);
  -        }
  -
  -        public HandlerChain createHandlerChain() {
  -            HandlerChain chain = super.createHandlerChain();
  -            handlers = new AAAHandler[chain.size()];
  -            for (int i = 0; i < chain.size(); i++) {
  -                handlers[i] = (AAAHandler) chain.get(i);
  -            }
  -            return chain;
  -        }
  -
  -        public AAAHandler[] getHandlers() {
  -            return handlers;
  -        }
  -
  -    }
  -
  +    
       private class TestMessageContext extends org.apache.axis.MessageContext {
   
           public String listByAreaCode = "<soap:Envelope\n" +
  
  
  
  1.1                  ws-axis/java/test/jaxrpc/AJAXRPC.java
  
  Index: AJAXRPC.java
  ===================================================================
  package test.jaxrpc;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import javax.xml.rpc.handler.HandlerChain;
  import javax.xml.rpc.handler.HandlerInfo;
  
  import junit.framework.TestCase;
  
  import org.apache.axis.AxisFault;
  import org.apache.axis.MessageContext;
  import org.apache.axis.handlers.BasicHandler;
  import org.apache.axis.handlers.HandlerInfoChainFactory;
  
  
  /**
   *
   *
   * @author Guillaume Sauthier
   */
  public abstract class AJAXRPC extends TestCase {
  
      HandlerInfo handlerInfo0 = null;
      HandlerInfo handlerInfo1 = null;
      HandlerInfo handlerInfo2 = null;
      Map handler0Config = null;
      protected Map handler1Config = null;
      protected Map handler2Config = null;
  
      /**
       * Sets up the handlerInfo and handlerConfigs for all tests.
       * Each test has 3 JAX-RPC Handlers of the same type to keep things
       * simple.
       * 
       * @throws Exception 
       */
      protected void setUp() throws Exception {
          handlerInfo0 = new HandlerInfo();
          handlerInfo0.setHandlerClass(AAAHandler.class);
          handlerInfo1 = new HandlerInfo();
          handlerInfo1.setHandlerClass(AAAHandler.class);
          handlerInfo2 = new HandlerInfo();
          handlerInfo2.setHandlerClass(AAAHandler.class);
          handler0Config = new HashMap();
          handler1Config = new HashMap();
          handler2Config = new HashMap();
          handlerInfo0.setHandlerConfig(handler0Config);
          handlerInfo1.setHandlerConfig(handler1Config);
          handlerInfo2.setHandlerConfig(handler2Config);
      }
  
      /**
       * Convenience method to organize all test checking for a particular
       * handler.
       * <p/>
       * Checks to see if the expected number of calls to handleRequest, handleResponse
       * and handleFault reconciles with actuals
       * 
       * @param message           
       * @param handler           the target handler to reconcile
       * @param numHandleRequest  # of expected calls to handleRequest
       * @param numHandleResponse # of expected calls to handleResponse
       * @param numHandleFault    # of expected call to handleFault
       */
      protected void assertHandlerRuntime(String message, AAAHandler handler, int numHandleRequest, int numHandleResponse, int numHandleFault) {
          assertEquals(message + ": handleRequest", numHandleRequest,
                  handler.getHandleRequestInvocations());
          assertEquals(message + ": handleResponse", numHandleResponse,
                  handler.getHandleResponseInvocations());
          assertEquals(message + ": handleFault", numHandleFault,
                  handler.getHandleFaultInvocations());
      }
  
      /**
       * Convenience method to create a HandlerInfoChainFactory
       * 
       * @return 
       */
      protected TestHandlerInfoChainFactory buildInfoChainFactory() {
          List handlerInfos = new ArrayList();
          handlerInfos.add(handlerInfo0);
          handlerInfos.add(handlerInfo1);
          handlerInfos.add(handlerInfo2);
          TestHandlerInfoChainFactory factory = new TestHandlerInfoChainFactory(
                  handlerInfos);
          return factory;
      }
      /**
       * Mock Service Handler used to simulate a service object throwing
       * an AxisFault.
       */
      protected class MockServiceHandler extends BasicHandler {
          public void invoke(MessageContext msgContext) throws AxisFault {
              throw new AxisFault();
          }
      }
  
      /**
       * Helper class for keeping references to the JAX-RPC Handlers
       * that are created by the Factory.
       * <p/>
       * This class allows us to access the individual handlers after
       * the test case has been executed in order to make sure that
       * the expected methods of the handler instance have been invoked.
       */
      protected class TestHandlerInfoChainFactory extends HandlerInfoChainFactory {
          AAAHandler[] handlers;
  
          public TestHandlerInfoChainFactory(List handlerInfos) {
              super(handlerInfos);
          }
  
          public HandlerChain createHandlerChain() {
              HandlerChain chain = super.createHandlerChain();
              handlers = new AAAHandler[chain.size()];
              for (int i = 0; i < chain.size(); i++) {
                  handlers[i] = (AAAHandler) chain.get(i);
              }
              return chain;
          }
  
          public AAAHandler[] getHandlers() {
              return handlers;
          }
  
      }
  
  }
  
  
  
  1.1                  ws-axis/java/test/jaxrpc/TestAxisClient.java
  
  Index: TestAxisClient.java
  ===================================================================
  package test.jaxrpc;
  
  import javax.xml.namespace.QName;
  import javax.xml.rpc.JAXRPCException;
  
  import org.apache.axis.AxisFault;
  import org.apache.axis.ConfigurationException;
  import org.apache.axis.Constants;
  import org.apache.axis.EngineConfiguration;
  import org.apache.axis.Handler;
  import org.apache.axis.Message;
  import org.apache.axis.MessageContext;
  import org.apache.axis.client.AxisClient;
  import org.apache.axis.client.Call;
  import org.apache.axis.client.Service;
  import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
  import org.apache.axis.configuration.FileProvider;
  import org.apache.axis.deployment.wsdd.WSDDDeployment;
  import org.apache.axis.deployment.wsdd.WSDDTransport;
  import org.apache.axis.handlers.soap.SOAPService;
  
  
  /**
   *
   *
   * @author Guillaume Sauthier
   */
  public class TestAxisClient extends AJAXRPC {
  
  
      /**
       *
       *
       * @author Guillaume Sauthier
       */
      protected class AxisFaultWSDDTransport extends WSDDTransport {
  
          /**
           * @see org.apache.axis.deployment.wsdd.WSDDDeployableItem#makeNewInstance(org.apache.axis.EngineConfiguration)
           */
          public Handler makeNewInstance(EngineConfiguration registry) throws ConfigurationException {
              return new MockServiceHandler();
          }
          /**
           * @see org.apache.axis.deployment.wsdd.WSDDDeployableItem#getQName()
           */
          public QName getQName() {
              return new QName("faulter");
          }
  }
      /*
       * @see TestCase#setUp()
       */
      protected void setUp() throws Exception {
          super.setUp();
      }
  
      /*
       * @see TestCase#tearDown()
       */
      protected void tearDown() throws Exception {
          super.tearDown();
      }
      /**
       * All Handlers in Chain return true for handleRequest and handleResponse
       * <p/>
       * <p/>
       * * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleResponse
       * H1.handleResponse
       * H0.handleResponse
       * 
       * @throws Exception 
       */
      public void testPositiveCourseFlow() throws Exception {
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
          client.invoke(context);
  
          AAAHandler handlerZero = factory.getHandlers()[0];
          AAAHandler handlerOne = factory.getHandlers()[1];
          AAAHandler handlerTwo = factory.getHandlers()[2];
          assertHandlerRuntime("handlerZero", handlerZero, 1, 1, 0);
          assertHandlerRuntime("handlerOne", handlerOne, 1, 1, 0);
          assertHandlerRuntime("handlerTwo", handlerTwo, 1, 1, 0);
      }
  
      /**
       * Tests scenario where one handler returns false on a call
       * to handleRequest(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest returns false
       * H1.handleResponse
       * H0.handleResponse
       * 
       * @throws Exception 
       */
      public void testRequestHandlerReturnsFalse() throws Exception {
          // SETUP THE 2nd HANDLER IN THE REQUEST CHAIN TO RETURN FALSE
          handler1Config.put("HANDLE_REQUEST_RETURN_VALUE", Boolean.FALSE);
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
          client.invoke(context);
  
          AAAHandler handlerZero = factory.getHandlers()[0];
          AAAHandler handlerOne = factory.getHandlers()[1];
          AAAHandler handlerTwo = factory.getHandlers()[2];
          assertHandlerRuntime("handlerZero", handlerZero, 1, 1, 0);
          assertHandlerRuntime("handlerOne", handlerOne, 1, 1, 0);
          assertHandlerRuntime("handlerTwo", handlerTwo, 0, 0, 0);
      }
  
      /**
       * Tests scenario where one handler throws a JAXRPCException
       * to handleRequest(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest throws JAXRPCException
       *
       * @throws Exception 
       */
      public void testRequestHandlerThrowsJAXRPCException() throws Exception {
          // SETUP THE 2nd HANDLER IN THE REQUEST CHAIN TO THROW JAXRPCException
          handler1Config.put("HANDLE_REQUEST_RETURN_VALUE",
                  new JAXRPCException());
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
          
          try {
              client.invoke(context);
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 0);
              assertHandlerRuntime("handlerTwo", handlerTwo, 0, 0, 0);
          }
      }
  
      /**
       * Tests scenario where one handler throws a RuntimeException
       * to handleRequest(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest throws JAXRPCException
       *
       * @throws Exception 
       */
      public void testRequestHandlerThrowsRuntimeException() throws Exception {
          // SETUP THE 2nd HANDLER IN THE REQUEST CHAIN TO THROW JAXRPCException
          handler1Config.put("HANDLE_REQUEST_RETURN_VALUE",
                  new RuntimeException());
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expected AxisFault to be thrown");
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 0);
              assertHandlerRuntime("handlerTwo", handlerTwo, 0, 0, 0);
          }
      }
  
      /**
       * Tests scenario where one handler returns false on a call
       * to handleResponse(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleResponse return false
       * 
       * @throws Exception 
       */
      public void testResponseHandlerReturnsFalse() throws Exception {
          // SETUP THE 3rd HANDLER IN THE CHAIN TO RETURN FALSE on handleResponse
          handler2Config.put("HANDLE_RESPONSE_RETURN_VALUE", Boolean.FALSE);
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
  
          client.invoke(context);
          
          AAAHandler handlerZero = factory.getHandlers()[0];
          AAAHandler handlerOne = factory.getHandlers()[1];
          AAAHandler handlerTwo = factory.getHandlers()[2];
          assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
          assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 0);
          assertHandlerRuntime("handlerTwo", handlerTwo, 1, 1, 0);
      }
  
      /**
       * Tests scenario where one handler throws JAXRPCException on a call
       * to handleResponse(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleResponse
       * H1.handlerResponse throws JAXRPCException
       * 
       * @throws Exception 
       */
      public void testResponseHandlerThrowsJAXRPCException() throws Exception {
          // SETUP THE 2nd HANDLER IN THE CHAIN TO THROW JAXRPCException on handleResponse
          handler1Config.put("HANDLE_RESPONSE_RETURN_VALUE",
                  new JAXRPCException());
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expected AxisFault to be thrown");
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 1, 0);
              assertHandlerRuntime("handlerTwo", handlerTwo, 1, 1, 0);
          }
      }
  
      /**
       * Tests scenario where one handler throws RuntimeException on a call
       * to handleResponse(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleResponse
       * H1.handlerResponse throws RuntimeException
       * 
       * @throws Exception 
       */
      public void testResponseHandlerThrowsRuntimeException() throws Exception {
          // SETUP THE 2nd HANDLER IN THE CHAIN TO THROW RuntimeException on handleResponse
          handler1Config.put("HANDLE_RESPONSE_RETURN_VALUE",
                  new RuntimeException());
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("local");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expected AxisFault to be thrown");
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 1, 0);
              assertHandlerRuntime("handlerTwo", handlerTwo, 1, 1, 0);
          }
      }
  
      /**
       * Tests scenario where one handler returns false on a call
       * to handleFault(...).
       * <p/>
       * Expected Chain invocation sequence looks like.....
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleFault
       * H1.handleFault return false
       * 
       * @throws Exception 
       */
      public void testHandleFaultReturnsFalse() throws Exception {
          // SETUP A MOCK SERVICE THAT SIMULATE A SOAPFAULT THROWN BY ENDPOINT
          handler1Config.put("HANDLE_FAULT_RETURN_VALUE", Boolean.FALSE);
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          SOAPService soapService = new SOAPService();
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();        
          addFaultTransport(client);
  
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("faulter");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expecting an AxisFault");
          } catch (AxisFault f) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 1);
              assertHandlerRuntime("handlerTwo", handlerTwo, 1, 0, 1);   
          }
      }
  
      /**
       * Tests to see if we handle the scenario of a handler throwing a
       * runtime exception during the handleFault(...) processing correctly
       * <p/>
       * Expected chain sequence:
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleFault
       * H1.handleFault throws JAXRPCException
       * 
       * @throws Exception 
       */
      public void testFaultHandlerThrowsJAXRPCException() throws Exception {
          handler1Config.put("HANDLE_FAULT_RETURN_VALUE", new JAXRPCException());
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          Handler serviceHandler = new MockServiceHandler();
          SOAPService soapService = new SOAPService(null, serviceHandler, null);
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();        
          addFaultTransport(client);
  
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("faulter");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expected AxisFault to be thrown");
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 1);
              assertHandlerRuntime("handlerTwo", handlerTwo, 1, 0, 1);
          }
      }
  
      /**
       * Tests to see if we handle the scenario of a handler throwing a
       * runtime exception during the handleFault(...) processing correctly
       * <p/>
       * Expected chain sequence:
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * H2.handleFault
       * H1.handleFault throws RuntimeException
       * 
       * @throws Exception 
       */
      public void testFaultHandlerThrowsRuntimeException() throws Exception {
          // SETUP THE LAST HANDLER IN THE REQUEST CHAIN TO THROW SOAPFaultException
          handler1Config.put("HANDLE_FAULT_RETURN_VALUE", new RuntimeException());
  
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          Handler serviceHandler = new MockServiceHandler();
          SOAPService soapService = new SOAPService(null, serviceHandler, null);
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();        
          addFaultTransport(client);
  
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("faulter");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expected AxisFault to be thrown");
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 0);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 1);
              assertHandlerRuntime("handlerTwo", handlerTwo, 1, 0, 1);
          }
      }
  
      /**
       * Tests scenario where service object throws Axis Fault.
       * <p/>
       * Expected chain sequence:
       * H0.handleRequest
       * H1.handleRequest
       * H2.handleRequest
       * ServiceObject.invoke() throws AxisFault
       * H2.handleFault
       * H1.handleFault
       * H0.handleFault
       * 
       * @throws Exception 
       */
      public void testServiceObjectThrowsAxisFault() throws Exception {
          TestHandlerInfoChainFactory factory = buildInfoChainFactory();
          Handler serviceHandler = new MockServiceHandler();
          SOAPService soapService = new SOAPService(null, serviceHandler, null);
          soapService.setOption(Constants.ATTR_HANDLERINFOCHAIN, factory);
          soapService.setOption(Call.WSDL_SERVICE, new Service());
          soapService.setOption(Call.WSDL_PORT_NAME, new QName("Fake"));
          soapService.init();
          AxisClient client = new AxisClient();        
          addFaultTransport(client);
  
          MessageContext context = new TestMessageContext(client);
          context.setTransportName("faulter");
          context.setService(soapService);
  
          try {
              client.invoke(context);
              fail("Expected AxisFault to be thrown");
          } catch (AxisFault e) {
              AAAHandler handlerZero = factory.getHandlers()[0];
              AAAHandler handlerOne = factory.getHandlers()[1];
              AAAHandler handlerTwo = factory.getHandlers()[2];
              assertHandlerRuntime("handlerZero", handlerZero, 1, 0, 1);
              assertHandlerRuntime("handlerOne", handlerOne, 1, 0, 1);
              assertHandlerRuntime("handlerTwo", handlerTwo, 1, 0, 1);
          }
      }
      
      /**
       * Configure a transport handler that simulate a Fault on server-side
       * @param client AxisClient
       */
      private void addFaultTransport(AxisClient client) {
  
          FileProvider config = (FileProvider) client.getConfig();
  
          WSDDDeployment depl = config.getDeployment();
          if (depl == null) {
              depl = new WSDDDeployment();
          }
          WSDDTransport trans = new AxisFaultWSDDTransport();
          depl.deployTransport(trans);
          
      }
  
      private class TestMessageContext extends org.apache.axis.MessageContext {
  
          public String listByAreaCode = "<soap:Envelope\n" +
                  "xmlns:s0=\"http://www.tilisoft.com/ws/LocInfo/literalTypes\"\n" +
                  "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
                  "xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n" +
                  "<soap:Header>\n" +
                  "<WSABIHeader>\n" +
                  "<SubscriptionId>192168001100108165800640600008</SubscriptionId>\n" +
                  "</WSABIHeader>\n" +
                  "</soap:Header>\n" +
                  "<soap:Body>\n" +
                  "<s0:ListByAreaCode>\n" +
                  "<s0:AreaCode>617</s0:AreaCode>\n" +
                  "</s0:ListByAreaCode>\n" +
                  "</soap:Body>\n" +
                  "</soap:Envelope>\n";
  
          public TestMessageContext(AxisClient client) {
              super(client);
              Message message = new Message(listByAreaCode);
              message.setMessageType(Message.REQUEST);
              setRequestMessage(message);
          }
      }
  
  }
  
  
  
  1.69      +79 -50    ws-axis/java/src/org/apache/axis/client/AxisClient.java
  
  Index: AxisClient.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/src/org/apache/axis/client/AxisClient.java,v
  retrieving revision 1.68
  retrieving revision 1.69
  diff -u -r1.68 -r1.69
  --- AxisClient.java	30 Nov 2004 21:54:32 -0000	1.68
  +++ AxisClient.java	9 Dec 2004 14:36:14 -0000	1.69
  @@ -1,12 +1,12 @@
   /*
    * Copyright 2001-2004 The Apache Software Foundation.
  - * 
  + *
    * Licensed 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.
  @@ -16,6 +16,9 @@
   
   package org.apache.axis.client ;
   
  +import javax.xml.namespace.QName;
  +import javax.xml.rpc.handler.HandlerChain;
  +
   import org.apache.axis.AxisEngine;
   import org.apache.axis.AxisFault;
   import org.apache.axis.Constants;
  @@ -24,15 +27,12 @@
   import org.apache.axis.MessageContext;
   import org.apache.axis.components.logger.LogFactory;
   import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
  -import org.apache.axis.handlers.HandlerChainImpl;
   import org.apache.axis.handlers.HandlerInfoChainFactory;
  -import org.apache.axis.handlers.soap.SOAPService;
   import org.apache.axis.handlers.soap.MustUnderstandChecker;
  +import org.apache.axis.handlers.soap.SOAPService;
   import org.apache.axis.utils.Messages;
   import org.apache.commons.logging.Log;
   
  -import javax.xml.namespace.QName;
  -
   /**
    * Provides the equivalent of an "Axis engine" on the client side.
    * Subclasses hardcode initialization & setup logic for particular
  @@ -45,7 +45,7 @@
   public class AxisClient extends AxisEngine {
       protected static Log log =
               LogFactory.getLog(AxisClient.class.getName());
  -    
  +
       MustUnderstandChecker checker = new MustUnderstandChecker(null);
   
       public AxisClient(EngineConfiguration config) {
  @@ -134,42 +134,74 @@
                       h.invoke(msgContext);
   
                   /* Process the JAXRPC Handlers */
  -                invokeJAXRPCHandlers(msgContext);
  +                /*******************************/
  +                HandlerChain handlerImpl = getJAXRPChandlerChain(msgContext);
  +                boolean result = true;
  +                try {
  +                    if (handlerImpl != null) {
  +                        result = handlerImpl.handleRequest(msgContext);
  +                    }
   
  -                /** Process the Transport Specific stuff
  -                 *
  -                 * NOTE: Somewhere in here there is a handler which actually
  -                 * sends the message and receives a response.  Generally
  -                 * this is the pivot point in the Transport chain.
  -                 */
  -                hName = msgContext.getTransportName();
  -                if ( hName != null && (h = getTransport( hName )) != null ) {
  -                    h.invoke(msgContext);
  -                }
  -                else {
  -                    throw new AxisFault(
  -                            Messages.getMessage("noTransport00", hName));
  +                    if (result) {
  +                            /** Process the Transport Specific stuff
  +                            *
  +                            * NOTE: Somewhere in here there is a handler which actually
  +                            * sends the message and receives a response.  Generally
  +                            * this is the pivot point in the Transport chain.
  +                            */
  +                           hName = msgContext.getTransportName();
  +                           if ( hName != null && (h = getTransport( hName )) != null ) {
  +                               try {
  +                                   h.invoke(msgContext);
  +                               } catch (AxisFault e) {
  +                                   // server-side processing went wrong
  +                                   msgContext.setPastPivot(true);
  +                                   if (handlerImpl != null) {
  +                                       // invoke handleFault on JAXRPC Handlers
  +                                       handlerImpl.handleFault(msgContext);
  +                                   }
  +                                   throw e;
  +                               }
  +                           }
  +                           else {
  +                               throw new AxisFault(
  +                                       Messages.getMessage("noTransport00", hName));
  +                           }
  +                    } else {
  +                        msgContext.setPastPivot(true);
  +                    }
  +                    /********************************************/
  +                    /*               Pivot past                 */
  +                    /********************************************/
  +
  +                    if ((handlerImpl != null) && !msgContext.isPropertyTrue(Call.ONE_WAY)) {
  +                        handlerImpl.handleResponse(msgContext);
  +                    }
  +
  +                } catch (RuntimeException e) {
  +                    throw AxisFault.makeFault(e);
  +                } finally {
  +                    if (handlerImpl != null) {
  +                        handlerImpl.destroy();
  +                    }
                   }
   
                   if (!msgContext.isPropertyTrue(Call.ONE_WAY)) {
  -
  -                    /* Process the JAXRPC Handlers */
  -                    invokeJAXRPCHandlers(msgContext);
  -                    
                       /* Process the Global Response Chain */
  -                    /***********************************/
  +                    /** ******************************** */
                       if ((h = getGlobalResponse()) != null) {
                           h.invoke(msgContext);
                       }
   
  -                    if ( service != null ) {
  +                    if (service != null) {
                           h = service.getResponseHandler();
  -                        if ( h != null ) {
  +                        if (h != null) {
                               h.invoke(msgContext);
                           }
                       }
   
  -                    // Do SOAP Semantics checks here - this needs to be a call to
  +                    // Do SOAP Semantics checks here - this needs to be a call
  +                    // to
                       // a pluggable object/handler/something
                       if (msgContext.isPropertyTrue(Call.CHECK_MUST_UNDERSTAND, true)) {
                           checker.invoke(msgContext);
  @@ -179,9 +211,12 @@
   
           } catch ( Exception e ) {
               // Should we even bother catching it ?
  -            log.debug(Messages.getMessage("exception00"), e);
  -            throw AxisFault.makeFault(e);
  -
  +            if (e instanceof AxisFault) {
  +                throw (AxisFault) e;
  +            } else {
  +                log.debug(Messages.getMessage("exception00"), e);
  +                throw AxisFault.makeFault(e);
  +            }
           } finally {
               // restore previous state
               setCurrentMessageContext(previousContext);
  @@ -192,20 +227,23 @@
           }
       }
   
  -    protected void invokeJAXRPCHandlers(MessageContext context){
  +    /**
  +     * @param context Stores the Service, port QName and optionnaly a HandlerInfoChainFactory
  +     * @return Returns a HandlerChain if one has been specified
  +     */
  +    protected HandlerChain getJAXRPChandlerChain(MessageContext context) {
           java.util.List chain = null;
           HandlerInfoChainFactory hiChainFactory = null;
           boolean clientSpecified = false;
   
  -        Service service
  -                = (Service)context.getProperty(Call.WSDL_SERVICE);
  +        Service service = (Service) context.getProperty(Call.WSDL_SERVICE);
           if(service == null) {
  -            return;
  +            return null;
           }
   
           QName portName = (QName) context.getProperty(Call.WSDL_PORT_NAME);
           if(portName == null) {
  -            return;
  +            return null;
           }
   
           javax.xml.rpc.handler.HandlerRegistry registry;
  @@ -230,19 +268,10 @@
           }
   
           if (hiChainFactory == null) {
  -            return;
  +            return null;
           }
   
  -        HandlerChainImpl impl =
  -                (HandlerChainImpl) hiChainFactory.createHandlerChain();
  -
  -        if(!context.getPastPivot()) {
  -            impl.handleRequest(context);
  -        }
  -        else {
  -            impl.handleResponse(context);
  -        }
  -        impl.destroy();
  +        return hiChainFactory.createHandlerChain();
       }
  -}
   
  +}
  
  
  
  1.15      +5 -1      ws-axis/java/src/org/apache/axis/handlers/HandlerChainImpl.java
  
  Index: HandlerChainImpl.java
  ===================================================================
  RCS file: /home/cvs/ws-axis/java/src/org/apache/axis/handlers/HandlerChainImpl.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- HandlerChainImpl.java	7 Jul 2004 03:04:01 -0000	1.14
  +++ HandlerChainImpl.java	9 Dec 2004 14:36:14 -0000	1.15
  @@ -128,7 +128,11 @@
       }
   
       public void destroy() {
  -        for (int i = 0; i < size(); i++) {
  +        int endIdx = size() - 1;
  +        if (falseIndex != -1) {
  +            endIdx = falseIndex;
  +        }
  +        for (int i = endIdx; i >= 0; i--) {
               getHandlerInstance(i).destroy();
           }
           falseIndex = -1;