You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by jl...@apache.org on 2007/05/15 16:30:55 UTC

svn commit: r538188 - in /incubator/cxf/trunk: rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/ rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/ rt/frontend/jaxws/s...

Author: jliu
Date: Tue May 15 07:30:53 2007
New Revision: 538188

URL: http://svn.apache.org/viewvc?view=rev&rev=538188
Log:
Fixed several JAX-WS handler close related problems. 

Modified:
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/AbstractJAXWSHandlerInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/HandlerChainInvoker.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerInInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptor.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/AbstractProtocolHandlerInterceptorTest.java
    incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/HandlerChainInvokerTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/HandlerInvocationTest.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandler.java
    incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandlerBase.java

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/DispatchImpl.java Tue May 15 07:30:53 2007
@@ -134,6 +134,7 @@
         setExchangeProperties(exchange, endpoint);
 
         message.setContent(Object.class, obj);
+        message.put(Message.REQUESTOR_ROLE, Boolean.TRUE);
 
         PhaseInterceptorChain chain = getDispatchOutChain(endpoint);
         message.setInterceptorChain(chain);

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/AbstractJAXWSHandlerInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/AbstractJAXWSHandlerInterceptor.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/AbstractJAXWSHandlerInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/AbstractJAXWSHandlerInterceptor.java Tue May 15 07:30:53 2007
@@ -71,8 +71,28 @@
     }
     
     public void onCompletion(T message) {
-        if (isOutbound(message)) {
-            getInvoker(message).mepComplete(message);
-        }
-    }    
+        getInvoker(message).mepComplete(message);
+    }   
+    
+    public boolean isMEPComlete(T message) {
+        HandlerChainInvoker invoker = getInvoker(message);
+      
+        if (invoker.isRequestor()) {
+            //client inbound and client outbound with no response are end of MEP
+            if (invoker.isInbound()) {
+                return true;
+            } else if (!invoker.isResponseExpected()) {
+                return true;
+            }            
+        } else {
+            //server outbound and server inbound with no response are end of MEP
+            if (!invoker.isInbound()) {
+                return true;
+            } else if (!invoker.isResponseExpected()) {
+                return true;
+            }            
+        } 
+        
+        return false;
+    }
 }

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/HandlerChainInvoker.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/HandlerChainInvoker.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/HandlerChainInvoker.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/HandlerChainInvoker.java Tue May 15 07:30:53 2007
@@ -19,7 +19,6 @@
 
 package org.apache.cxf.jaxws.handler;
 
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -52,28 +51,26 @@
 import org.apache.cxf.jaxws.context.WrappedMessageContext;
 import org.apache.cxf.message.Message;
 
-
 /**
  * invoke invoke the handlers in a registered handler chain
- *
  */
 public class HandlerChainInvoker {
 
     private static final Logger LOG = LogUtils.getL7dLogger(HandlerChainInvoker.class);
 
     private final List<Handler> protocolHandlers = new ArrayList<Handler>();
-    private List<LogicalHandler> logicalHandlers  = new ArrayList<LogicalHandler>();
-    
-    
-    private final List<Handler> invokedHandlers  = new ArrayList<Handler>();
-    private final List<Handler> closeHandlers  = new ArrayList<Handler>();
-    
+    private List<LogicalHandler> logicalHandlers = new ArrayList<LogicalHandler>();
+
+    private final List<Handler> invokedHandlers = new ArrayList<Handler>();
+    private final List<Handler> closeHandlers = new ArrayList<Handler>();
+
     private boolean outbound;
     private boolean isRequestor;
     private boolean responseExpected = true;
     private boolean faultExpected;
-    private boolean handlerProcessingAborted;
+    //private boolean handlerProcessingAborted;
     private boolean closed;
+    private boolean messageDirectionReversed;
     private Exception fault;
     private MessageContext logicalMessageContext;
     private MessageContext protocolMessageContext;
@@ -110,6 +107,7 @@
     public MessageContext getLogicalMessageContext() {
         return logicalMessageContext;
     }
+
     public void setLogicalMessageContext(MessageContext mc) {
         logicalMessageContext = mc;
     }
@@ -117,6 +115,7 @@
     public MessageContext getProtocolMessageContext() {
         return protocolMessageContext;
     }
+
     public void setProtocolMessageContext(MessageContext mc) {
         protocolMessageContext = mc;
     }
@@ -126,28 +125,31 @@
         context.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, isOutbound());
         return invokeHandlerChain(logicalHandlers, context);
     }
-    
+
     public boolean invokeLogicalHandlersHandleFault(boolean requestor, LogicalMessageContext context) {
         // objectCtx.setRequestorRole(requestor);
         context.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, isOutbound());
         return invokeHandlerChainHandleFault(logicalHandlers, context);
     }
-    
+
     public boolean invokeProtocolHandlers(boolean requestor, MessageContext context) {
         // WrappedMessageContext context = new WrappedMessageContext(message);
-        // bindingContext.put(ObjectMessageContext.REQUESTOR_ROLE_PROPERTY, requestor);
+        // bindingContext.put(ObjectMessageContext.REQUESTOR_ROLE_PROPERTY,
+        // requestor);
         context.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, isOutbound());
 
         return invokeHandlerChain(protocolHandlers, context);
     }
+
     public boolean invokeProtocolHandlersHandleFault(boolean requestor, MessageContext context) {
         // WrappedMessageContext context = new WrappedMessageContext(message);
-        // bindingContext.put(ObjectMessageContext.REQUESTOR_ROLE_PROPERTY, requestor);
+        // bindingContext.put(ObjectMessageContext.REQUESTOR_ROLE_PROPERTY,
+        // requestor);
         context.put(MessageContext.MESSAGE_OUTBOUND_PROPERTY, isOutbound());
 
         return invokeHandlerChainHandleFault(protocolHandlers, context);
     }
-    
+
     public void setResponseExpected(boolean expected) {
         responseExpected = expected;
     }
@@ -163,18 +165,20 @@
     public boolean isInbound() {
         return !outbound;
     }
-    
-    //We need HandlerChainInvoker behaves differently on client and server side. For 
-    //client side, as we do not have a faultChain, we need to call handleFault and close
-    //on handlers directly. 
-    protected boolean isRequestor() {
+
+    /**
+     * We need HandlerChainInvoker behaves differently on client and server
+     * side. For client side, as we do not have a faultChain, we need to call
+     * handleFault and close on within HandlerChainInvoker directly.
+     */
+    public boolean isRequestor() {
         return isRequestor;
     }
-    
-    protected void setRequestor(boolean requestor) {
+
+    public void setRequestor(boolean requestor) {
         isRequestor = requestor;
     }
-    
+
     public void setInbound() {
         outbound = false;
     }
@@ -183,9 +187,8 @@
         outbound = true;
     }
 
-
     public boolean faultRaised() {
-        return null != fault  || faultExpected;
+        return null != fault || faultExpected;
     }
 
     public Exception getFault() {
@@ -196,39 +199,43 @@
         faultExpected = fe;
     }
 
-    /** Invoke handlers at the end of an MEP calling close on each.
-     * The handlers must be invoked in the reverse order that they
-     * appear in the handler chain.  On the server side this will not
-     * be the reverse order in which they were invoked so use the
-     * handler chain directly and not simply the invokedHandler list.
+    /**
+     * Invoke handlers at the end of an MEP calling close on each. The handlers
+     * must be invoked in the reverse order that they appear in the handler
+     * chain. On the server side this will not be the reverse order in which
+     * they were invoked so use the handler chain directly and not simply the
+     * invokedHandler list.
      */
     public void mepComplete(Message message) {
-        WrappedMessageContext context = new WrappedMessageContext(message);
         if (LOG.isLoggable(Level.FINE)) {
             LOG.log(Level.FINE, "closing protocol handlers - handler count:" + invokedHandlers.size());
         }
-        invokeClose(protocolHandlers, context);
-        invokeClose(logicalHandlers, context);
+        
+        if (isClosed()) {
+            return;
+        }
+        
+        invokeReversedClose();
     }
 
-
-    /** Indicates that the invoker is closed.  When closed, only @see
-     * #mepComplete may be called.  The invoker will become closed if
-     * during a invocation of handlers, a handler throws a runtime
-     * exception that is not a protocol exception and no futher
-     * handler or message processing is possible.
-     *
+    /**
+     * Indicates that the invoker is closed. When closed, only
+     * 
+     * @see #mepComplete may be called. The invoker will become closed if during
+     *      a invocation of handlers, a handler throws a runtime exception that
+     *      is not a protocol exception and no futher handler or message
+     *      processing is possible.
      */
     public boolean isClosed() {
         return closed;
     }
 
     /**
-     * Allows an the logical handler chain for one invoker to be used
-     * as an alternate chain for another.
-     *
+     * Allows an the logical handler chain for one invoker to be used as an
+     * alternate chain for another.
+     * 
      * @param invoker the invoker encalsulting the alternate logical handler
-     * chain
+     *            chain
      */
     public void adoptLogicalHandlers(HandlerChainInvoker invoker) {
         logicalHandlers = invoker.getLogicalHandlers();
@@ -237,19 +244,26 @@
     List getInvokedHandlers() {
         return Collections.unmodifiableList(invokedHandlers);
     }
-
+    
+/*
     private <T extends Handler> void invokeClose(List<T> handlers, MessageContext context) {
-        handlers = reverseHandlerChain(handlers);
+        if (isOutbound()) {
+            handlers = reverseHandlerChain(handlers);
+        }
+        if (messageDirectionReversed) {
+            handlers = reverseHandlerChain(handlers);            
+        }
+
+        // handlers = reverseHandlerChain(handlers);
         for (Handler h : handlers) {
             if (closeHandlers.contains(h)) {
-                //System.out.println("===========invokeClose " + h.toString());
+                System.out.println("===========invokeClose " + h.toString());
                 h.close(context);
             }
         }
-    }
-    
-    private boolean invokeHandlerChainHandleFault(List<? extends Handler> handlerChain,
-                                       MessageContext ctx) {
+    }*/
+
+    private boolean invokeHandlerChainHandleFault(List<? extends Handler> handlerChain, MessageContext ctx) {
         if (handlerChain.isEmpty()) {
             LOG.log(Level.FINEST, "no handlers registered");
             return true;
@@ -272,18 +286,15 @@
 
         WebServiceContextImpl.setMessageContext(ctx);
 
-
         continueProcessing = invokeHandleFault(handlerChain, ctx);
 
-
-        if (!continueProcessing) {
+/*        if (!continueProcessing) {
             handlerProcessingAborted = true;
-        }
+        }*/
         return continueProcessing;
     }
-    
-    private boolean invokeHandlerChain(List<? extends Handler> handlerChain,
-                                       MessageContext ctx) {
+
+    private boolean invokeHandlerChain(List<? extends Handler> handlerChain, MessageContext ctx) {
         if (handlerChain.isEmpty()) {
             LOG.log(Level.FINEST, "no handlers registered");
             return true;
@@ -312,15 +323,14 @@
             continueProcessing = invokeHandleFault(handlerChain, ctx);
         }
 
-        if (!continueProcessing) {
+/*        if (!continueProcessing) {
             handlerProcessingAborted = true;
-        }
+        }*/
         return continueProcessing;
     }
 
     @SuppressWarnings("unchecked")
     private boolean invokeHandleFault(List<? extends Handler> handlerChain, MessageContext ctx) {
-
         boolean continueProcessing = true;
 
         try {
@@ -344,10 +354,12 @@
         return continueProcessing;
     }
 
+    private boolean isTheLastInvokedHandler(Handler h) {
+        return invokedHandlers.contains(h) && invokedHandlers.indexOf(h) == (invokedHandlers.size() - 1);
+    }
 
     @SuppressWarnings("unchecked")
     private boolean invokeHandleMessage(List<? extends Handler> handlerChain, MessageContext ctx) {
-
         boolean continueProcessing = true;
         try {
             for (Handler h : handlerChain) {
@@ -358,9 +370,10 @@
                     continueProcessing = h.handleMessage(ctx);
                 }
                 if (!continueProcessing) {
-                    changeMessageDirection(ctx);
-                    if (!responseExpected) {
-                        invokeReversedClose();
+                    if (responseExpected) {
+                        changeMessageDirection(ctx);
+                        messageDirectionReversed = true;
+                        //invokeReversedClose();
                     }
 
                     break;
@@ -368,26 +381,39 @@
             }
         } catch (ProtocolException e) {
             LOG.log(Level.FINE, "handleMessage raised exception", e);
+            messageDirectionReversed = true;
             
-            //this is the client outbound
-            if (isRequestor()) {
+            if (responseExpected) {
                 changeMessageDirection(ctx);
+                messageDirectionReversed = true;
+                //invokeReversedClose();
+            }
+
+            //special case for client side, this is because we do nothing in client fault
+            //observer, we have to call handleFault and close here.
+            if (isRequestor()) {
                 if (responseExpected) {
                     setFaultMessage(ctx, e);
                     invokeReversedHandleFault(ctx);
                 } else {
                     invokeReversedClose();
-                }               
+                }
             }
- 
+
             continueProcessing = false;
             setFault(e);
             throw e;
         } catch (RuntimeException e) {
             LOG.log(Level.WARNING, "HANDLER_RAISED_RUNTIME_EXCEPTION", e);
+ 
+            if (responseExpected) {
+                changeMessageDirection(ctx);
+                messageDirectionReversed = true;
+            }
             
+            //special case for client side, this is because we do nothing in client fault
+            //observer, we have to call close here.
             if (isRequestor()) {
-                changeMessageDirection(ctx);
                 invokeReversedClose();
             }
             
@@ -397,40 +423,40 @@
         }
         return continueProcessing;
     }
-    
-    //When the message direction is reversed, if the message is not already a fault message then it is 
-    //replaced with a fault message
+
+    /*
+     * When the message direction is reversed, if the message is not already a
+     * fault message then it is replaced with a fault message
+     */    
     private void setFaultMessage(MessageContext mc, Exception exception) {
         Message msg = ((WrappedMessageContext)mc).getWrappedMessage();
         msg.setContent(Exception.class, exception);
         msg.removeContent(XMLStreamReader.class);
         msg.removeContent(Source.class);
-        
+
         try {
             SOAPMessage soapMessage = null;
-            
-            if (!(msg instanceof SoapMessage)
-                || ((SoapMessage)msg).getVersion().getVersion() <= 1.11d) {
+
+            if (!(msg instanceof SoapMessage) || ((SoapMessage)msg).getVersion().getVersion() <= 1.11d) {
                 soapMessage = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createMessage();
             } else {
                 soapMessage = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage();
             }
             msg.setContent(SOAPMessage.class, soapMessage);
-            
+
             SOAPBody body = soapMessage.getSOAPBody();
             SOAPFault soapFault = body.addFault();
-            
+
             if (exception instanceof SOAPFaultException) {
                 SOAPFaultException sf = (SOAPFaultException)exception;
                 soapFault.setFaultString(sf.getFault().getFaultString());
                 soapFault.setFaultCode(sf.getFault().getFaultCode());
                 soapFault.setFaultActor(sf.getFault().getFaultActor());
-                Node nd = soapMessage.getSOAPPart()
-                    .importNode(sf.getFault().getDetail().getFirstChild(), true);
+                Node nd = soapMessage.getSOAPPart().importNode(sf.getFault().getDetail().getFirstChild(),
+                                                               true);
                 soapFault.addDetail().appendChild(nd);
             } else if (exception instanceof Fault) {
-                SoapFault sf = SoapFault.createFault((Fault)exception,
-                                                     ((SoapMessage)msg).getVersion());
+                SoapFault sf = SoapFault.createFault((Fault)exception, ((SoapMessage)msg).getVersion());
                 soapFault.setFaultString(sf.getReason());
                 soapFault.setFaultCode(sf.getFaultCode());
                 Node nd = soapMessage.getSOAPPart().importNode(sf.getOrCreateDetail(), true);
@@ -442,12 +468,15 @@
         } catch (SOAPException e) {
             e.printStackTrace();
             // do nothing
-        }            
+        }
     }
-        
-    // The message direction is reversed, if the message is not already a fault message then it
-    // is replaced with a fault message, and the runtime invokes handleFault on
-    // the next handler or dispatches the message if there are no further handlers.
+
+    /*
+     * The message direction is reversed, if the message is not already a fault
+     * message then it is replaced with a fault message, and the runtime invokes
+     * handleFault on the next handler or dispatches the message if there are no
+     * further handlers.
+     */    
     @SuppressWarnings("unchecked")
     private boolean invokeReversedHandleFault(MessageContext ctx) {
         boolean continueProcessing = true;
@@ -474,33 +503,26 @@
             invokeReversedClose();
             continueProcessing = false;
             closed = true;
-            
+
             throw e;
         }
         invokeReversedClose();
         return continueProcessing;
-/*
-        int index = invokedHandlers.size() - 2;
-        while (index >= 0) {
-            Handler handler = invokedHandlers.get(index);
-            if (handler instanceof LogicalHandler) {
-                if (Boolean.FALSE.equals(handler.
-                                         handleFault(logicalMessageContext))) {
-                    return false;
-                }
-            } else {
-                if (Boolean.FALSE.equals(handler.
-                                         handleFault(protocolMessageContext))) {
-                    return false;
-                }
-            }
-            index--;
-        }
-        return true;*/
+        /*
+         * int index = invokedHandlers.size() - 2; while (index >= 0) { Handler
+         * handler = invokedHandlers.get(index); if (handler instanceof
+         * LogicalHandler) { if (Boolean.FALSE.equals(handler.
+         * handleFault(logicalMessageContext))) { return false; } } else { if
+         * (Boolean.FALSE.equals(handler. handleFault(protocolMessageContext))) {
+         * return false; } } index--; } return true;
+         */
     }
 
-    //close is called on each previously invoked handler in the chain, the close method is 
-    //only called on handlers that were previously invoked via either handleMessage or handleFault
+    /*
+     * close is called on each previously invoked handler in the chain, the
+     * close method is only called on handlers that were previously invoked via
+     * either handleMessage or handleFault
+     */
     private void invokeReversedClose() {
         int index = invokedHandlers.size() - 1;
         while (index >= 0) {
@@ -515,22 +537,22 @@
         }
         closed = true;
     }
-    
+
     private boolean invokeThisHandler(Handler h) {
         boolean ret = true;
-        // when handler processing has been aborted, only invoked on
+        // when handler processing has been aborted, only invoke on
         // previously invoked handlers
-        //
-        if (handlerProcessingAborted || faultRaised()) {
-            ret = invokedHandlers.contains(h);
+        //Only invoke the next handler (take the reversed direction into account)
+        if (messageDirectionReversed) {
+            ret = invokedHandlers.contains(h) && !isTheLastInvokedHandler(h);
         }
+
         if (ret && LOG.isLoggable(Level.FINE)) {
             LOG.log(Level.FINE, "invoking handler of type " + h.getClass().getName());
         }
         return ret;
     }
 
-
     private void markHandlerInvoked(Handler h) {
         if (!invokedHandlers.contains(h)) {
             invokedHandlers.add(h);
@@ -562,11 +584,10 @@
 
     protected final void setFault(Exception ex) {
         /*
-        context.put(ObjectMessageContext.METHOD_FAULT, ex);
-        context.setScope(ObjectMessageContext.METHOD_FAULT, MessageContext.Scope.HANDLER);
-        */
+         * context.put(ObjectMessageContext.METHOD_FAULT, ex);
+         * context.setScope(ObjectMessageContext.METHOD_FAULT,
+         * MessageContext.Scope.HANDLER);
+         */
         fault = ex;
     }
 }
-
-

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerInInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerInInterceptor.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerInInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerInInterceptor.java Tue May 15 07:30:53 2007
@@ -57,10 +57,19 @@
         LogicalMessageContextImpl lctx = new LogicalMessageContextImpl(message);
         invoker.setLogicalMessageContext(lctx);
         boolean requestor = isRequestor(message);
-        if (!invoker.invokeLogicalHandlers(requestor, lctx) && !requestor) {
-            handleAbort(message, null);
+        if (!invoker.invokeLogicalHandlers(requestor, lctx)) {
+            if (!requestor) {
+                handleAbort(message, null);
+            } else {
+                //Client side inbound, thus no response expected, do nothing, the close will  
+                //be handled by MEPComplete later
+            }
+        }
+ 
+        //If this is the inbound and end of MEP, call MEP completion
+        if (!isOutbound(message) && isMEPComlete(message)) {
+            onCompletion(message);
         }
-        onCompletion(message);
     }
 
     private void handleAbort(T message, W3CDOMStreamWriter writer) {

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/logical/LogicalHandlerOutInterceptor.java Tue May 15 07:30:53 2007
@@ -129,11 +129,11 @@
                         responseMsg.put(PhaseInterceptorChain.STARTING_AT_INTERCEPTOR_ID,
                                         LogicalHandlerInInterceptor.class.getName());
                         observer.onMessage(responseMsg);
-                        invoker.mepComplete(responseMsg);
+                        //invoker.mepComplete(responseMsg);
                     }
                 } else {
-                    // server side - about
-                    System.out.println("Aborting");
+                    // server side - abort
+                    System.out.println("Logical handler server side aborting");
                 }
                 return;
             }

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptor.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptor.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/main/java/org/apache/cxf/jaxws/handler/soap/SOAPHandlerInterceptor.java Tue May 15 07:30:53 2007
@@ -125,11 +125,23 @@
         HandlerChainInvoker invoker = getInvoker(message);
         invoker.setProtocolMessageContext(context);
 
+/*        if (!invoker.invokeProtocolHandlers(isRequestor(message), context)) {
+            handleAbort(message, context);
+        } else {
+            //if message processing ends normally, close previously invoked handlers.
+            if (isOutbound(message)) {
+                onCompletion(message);
+            }
+        }*/
+        
         if (!invoker.invokeProtocolHandlers(isRequestor(message), context)) {
             handleAbort(message, context);
+        } 
+
+        //If this is the outbound and end of MEP, call MEP completion
+        if (isOutbound(message) && isMEPComlete(message)) {
+            onCompletion(message);
         }
-  
-        onCompletion(message);
     }
     
     private void handleAbort(SoapMessage message, MessageContext context) {
@@ -151,13 +163,18 @@
                         XMLStreamReader xmlReader = createXMLStreamReaderFromSOAPMessage(soapMessage);
                         responseMsg.setContent(XMLStreamReader.class, xmlReader);
                     }
-                    responseMsg.put(PhaseInterceptorChain.STARTING_AFTER_INTERCEPTOR_ID,
+                    responseMsg.put(PhaseInterceptorChain.STARTING_AT_INTERCEPTOR_ID,
                                     SOAPHandlerInterceptor.class.getName());
                     observer.onMessage(responseMsg);
                 }
+                
+                //We dont call onCompletion here, as onCompletion will be called by inbound 
+                //LogicalHandlerInterceptor
             } else {
                 // client side inbound - Normal handler message processing
-                // stops,, but the inbound interceptor chain still continues, dispatch the message
+                // stops, but the inbound interceptor chain still continues, dispatch the message
+                //By onCompletion here, we can skip following Logical handlers 
+                onCompletion(message);
                 System.out.println("SOAP Handler handleMessage returns false on client inbound, aborting");
             }
         } else {

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/AbstractProtocolHandlerInterceptorTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/AbstractProtocolHandlerInterceptorTest.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/AbstractProtocolHandlerInterceptorTest.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/AbstractProtocolHandlerInterceptorTest.java Tue May 15 07:30:53 2007
@@ -56,7 +56,7 @@
 
     public void testInterceptSuccess() {
         expect(message.getExchange()).andReturn(exchange).anyTimes();
-        expect(exchange.get(HandlerChainInvoker.class)).andReturn(invoker);
+        expect(exchange.get(HandlerChainInvoker.class)).andReturn(invoker).anyTimes();
         expect(
                 invoker.invokeProtocolHandlers(eq(false),
                         isA(MessageContext.class))).andReturn(true);
@@ -69,7 +69,7 @@
 
     public void testInterceptFailure() {
         expect(message.getExchange()).andReturn(exchange).anyTimes();
-        expect(exchange.get(HandlerChainInvoker.class)).andReturn(invoker);
+        expect(exchange.get(HandlerChainInvoker.class)).andReturn(invoker).anyTimes();
         expect(exchange.getOutMessage()).andReturn(message);
         expect(
                 invoker.invokeProtocolHandlers(eq(false),

Modified: incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/HandlerChainInvokerTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/HandlerChainInvokerTest.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/HandlerChainInvokerTest.java (original)
+++ incubator/cxf/trunk/rt/frontend/jaxws/src/test/java/org/apache/cxf/jaxws/handler/HandlerChainInvokerTest.java Tue May 15 07:30:53 2007
@@ -127,34 +127,38 @@
             .getInvokeOrderOfHandleMessage());
     }
 
-    public void testLogicalHandlerOutboundProcessingStoppedResponseExpected() {
+    public void testLogicalHandlerReturnFalseOutboundResponseExpected() {
 
         assertEquals(0, logicalHandlers[0].getHandleMessageCount());
         assertEquals(0, logicalHandlers[1].getHandleMessageCount());
+        assertEquals(0, logicalHandlers[2].getHandleMessageCount());
 
         assertTrue(invoker.isOutbound());
 
         // invoke the handlers.  when a handler returns false, processing
-        // of handlers is stopped and message direction is  reversed.
-        logicalHandlers[0].setHandleMessageRet(false);
+        // of handlers is stopped and message direction is reversed.
+        logicalHandlers[1].setHandleMessageRet(false);
+        
         boolean ret = invoker.invokeLogicalHandlers(false, lmc);
 
         assertEquals(false, ret);
         assertFalse(invoker.isClosed());
         assertEquals(1, logicalHandlers[0].getHandleMessageCount());
-        assertEquals(0, logicalHandlers[1].getHandleMessageCount());
+        assertEquals(1, logicalHandlers[1].getHandleMessageCount());
+        assertEquals(0, logicalHandlers[2].getHandleMessageCount());
         assertTrue(invoker.isInbound());
 
         // the next time invokeHandler is invoked, the 'next' handler is invoked.
         // As message direction has been reversed this means the that the previous
         // one on the list is actually invoked.
-        logicalHandlers[0].setHandleMessageRet(true);
+        logicalHandlers[1].setHandleMessageRet(true);
 
         ret = invoker.invokeLogicalHandlers(false, lmc);
         assertTrue(ret);
         assertFalse(invoker.isClosed());
         assertEquals(2, logicalHandlers[0].getHandleMessageCount());
-        assertEquals(0, logicalHandlers[1].getHandleMessageCount());
+        assertEquals(1, logicalHandlers[1].getHandleMessageCount());
+        assertEquals(0, logicalHandlers[2].getHandleMessageCount());
         assertTrue(invoker.isInbound());
     }
 
@@ -204,7 +208,7 @@
         assertEquals(2, logicalHandlers[3].getHandleMessageCount());
         assertEquals(2, protocolHandlers[0].getHandleMessageCount());
         assertEquals(2, protocolHandlers[1].getHandleMessageCount());
-        assertEquals(2, protocolHandlers[2].getHandleMessageCount());
+        assertEquals(1, protocolHandlers[2].getHandleMessageCount());
         assertEquals(0, protocolHandlers[3].getHandleMessageCount());
         assertTrue(logicalHandlers[3].getInvokeOrderOfHandleMessage()
                    < logicalHandlers[2].getInvokeOrderOfHandleMessage());
@@ -451,7 +455,7 @@
         
         assertEquals(2, logicalHandlers[0].getHandleMessageCount());
         assertEquals(2, logicalHandlers[1].getHandleMessageCount());
-        assertEquals(2, logicalHandlers[2].getHandleMessageCount());
+        assertEquals(1, logicalHandlers[2].getHandleMessageCount());
         assertEquals(0, logicalHandlers[3].getHandleMessageCount());
         assertTrue(logicalHandlers[3].getInvokeOrderOfHandleMessage()
                    < logicalHandlers[2].getInvokeOrderOfHandleMessage());
@@ -497,12 +501,11 @@
         assertTrue(logicalHandlers[1].getInvokeOrderOfHandleMessage()
                    < logicalHandlers[2].getInvokeOrderOfHandleMessage());
         
-        assertEquals(1, logicalHandlers[0].getCloseCount());
-        assertEquals(1, logicalHandlers[1].getCloseCount());
-        assertEquals(1, logicalHandlers[2].getCloseCount());
+        //Close is invoked outside HandlerChainInvoker, eg, in SOAPHandlerInterceptor
+        assertEquals(0, logicalHandlers[0].getCloseCount());
+        assertEquals(0, logicalHandlers[1].getCloseCount());
+        assertEquals(0, logicalHandlers[2].getCloseCount());
         assertEquals(0, logicalHandlers[3].getCloseCount());
-        assertTrue(logicalHandlers[1].getInvokeOrderOfClose()
-                   < logicalHandlers[0].getInvokeOrderOfClose());
 
         assertEquals(0, logicalHandlers[0].getHandleFaultCount());
         assertEquals(0, logicalHandlers[1].getHandleFaultCount());
@@ -920,7 +923,7 @@
         assertEquals(2, protocolHandlers[0].getHandleMessageCount());
         assertEquals(2, protocolHandlers[1].getHandleMessageCount());
 
-        assertEquals(2, logicalHandlers[1].getHandleMessageCount());
+        assertEquals(1, logicalHandlers[1].getHandleMessageCount());
         assertEquals(0, logicalHandlers[0].getHandleMessageCount());
         assertEquals(2, protocolHandlers[0].getHandleMessageCount());
         assertEquals(2, protocolHandlers[1].getHandleMessageCount());

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/HandlerInvocationTest.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/HandlerInvocationTest.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/HandlerInvocationTest.java (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/HandlerInvocationTest.java Tue May 15 07:30:53 2007
@@ -144,15 +144,22 @@
         assertEquals("handle message was not invoked", 2, handler2.getHandleMessageInvoked());
         assertEquals("handle message was not invoked", 2, soapHandler1.getHandleMessageInvoked());
         assertEquals("handle message was not invoked", 2, soapHandler2.getHandleMessageInvoked());
-        assertTrue("close must be  called", handler1.isCloseInvoked());
-        assertTrue("close must be  called", handler2.isCloseInvoked());
-        assertTrue("close must be  called", soapHandler1.isCloseInvoked());
-        assertTrue("close must be  called", soapHandler2.isCloseInvoked());
-
+        
+        assertEquals("close must be called", 1, handler1.getCloseInvoked());
+        assertEquals("close must be called", 1, handler2.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler1.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler2.getCloseInvoked());
+        
+        assertTrue(soapHandler2.getInvokeOrderOfClose()
+                   < soapHandler1.getInvokeOrderOfClose());   
+        assertTrue(soapHandler1.getInvokeOrderOfClose()
+                   < handler2.getInvokeOrderOfClose());          
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());  
+        
         // the server has encoded into the response the order in
         // which the handlers have been invoked, parse it and make
-        // sure everything is ok
-        // expected order for inbound interceptors
+        // sure everything is ok expected order for inbound interceptors
         String[] handlerNames = {"soapHandler4", "soapHandler3", "handler2", "handler1", "servant",
                                  "handler1", "handler2", "soapHandler3", "soapHandler4"};
 
@@ -183,27 +190,76 @@
                         resp.getHandlersInfo().add(clientHandlerMessage);
 
                         msg.setPayload(resp, jaxbCtx);
+                        return false;
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                     fail(e.toString());
                 }
-                return false;
+                return true;
             }
         };
+        TestHandler<LogicalMessageContext> handler3 = new TestHandler<LogicalMessageContext>(false);
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
 
-        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2);
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, handler3, soapHandler1);
 
         List<String> resp = handlerTest.ping();
         assertEquals(clientHandlerMessage, resp.get(0));
 
-        assertEquals("handler must be invoked for inbound & outbound message", 2, handler2
+        assertEquals("the first handler must be invoked twice", 2, handler1.getHandleMessageInvoked());
+        assertEquals("the second handler must be invoked once only on outbound", 1, handler2
             .getHandleMessageInvoked());
+        assertEquals("the third handler must not be invoked", 0, handler3.getHandleMessageInvoked());
+        assertEquals("the last handler must not be invoked", 0, soapHandler1.getHandleMessageInvoked());
 
-        assertEquals("the first handler must be invoked once", 1, handler1.getHandleMessageInvoked());
+        //outbound MEP processing ceased, the message direction was changed to inbound, essentially this is
+        //only one MEP. So close is called only once at the end of inbound MEP, and the close order is 
+        //reversed to the outbound handler invoking order.
+        assertEquals("close must be called", 1, handler1.getCloseInvoked());
+        assertEquals("close must be called", 1, handler2.getCloseInvoked());
+        assertEquals("close must be called", 0, handler3.getCloseInvoked());
+        assertEquals("close must be called", 0, soapHandler1.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());         
+    }
+    
+    @Test
+    public void testLogicalHandlerHandleMessageReturnFalseClientInBound() throws Exception {
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false) {
+            public boolean handleMessage(LogicalMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (!outbound) {
+                    return false;
+                }
 
-        //assertTrue("close must be called", handler1.isCloseInvoked());
-        //assertTrue("close must be called", handler2.isCloseInvoked());
+                return true;
+            }
+        };
+        TestHandler<LogicalMessageContext> handler3 = new TestHandler<LogicalMessageContext>(false);
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
+
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, handler3, soapHandler1);
+
+        handlerTest.ping();        
+
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(2, handler2.getHandleMessageInvoked());
+        assertEquals(2, handler3.getHandleMessageInvoked());
+        assertEquals(2, soapHandler1.getHandleMessageInvoked());
+
+        assertEquals("close must be called", 1, handler1.getCloseInvoked());
+        assertEquals("close must be called", 1, handler2.getCloseInvoked());
+        assertEquals("close must be called", 1, handler3.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler1.getCloseInvoked());
+        assertTrue(soapHandler1.getInvokeOrderOfClose()
+                   < handler3.getInvokeOrderOfClose());   
+        assertTrue(handler3.getInvokeOrderOfClose()
+                   < handler2.getInvokeOrderOfClose());          
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
     }
     
     @Test
@@ -237,8 +293,11 @@
         TestSOAPHandler soapHandler2 = new TestSOAPHandler<SOAPMessageContext>(false) {
             public boolean handleMessage(SOAPMessageContext ctx) {
                 super.handleMessage(ctx);
-
-                return false;
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (outbound) {
+                    return false;
+                }
+                return true;
             }
         };
         addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1, soapHandler2);
@@ -248,14 +307,61 @@
 
         assertEquals(2, handler1.getHandleMessageInvoked());
         assertEquals(2, handler2.getHandleMessageInvoked());
-        assertEquals(1, soapHandler1.getHandleMessageInvoked());
+        assertEquals(2, soapHandler1.getHandleMessageInvoked());
         assertEquals(1, soapHandler2.getHandleMessageInvoked());
+        
+        assertEquals("close must be called", 1, handler1.getCloseInvoked());
+        assertEquals("close must be called", 1, handler2.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler1.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler2.getCloseInvoked());
+        assertTrue(soapHandler2.getInvokeOrderOfClose()
+                   < soapHandler1.getInvokeOrderOfClose());   
+        assertTrue(soapHandler1.getInvokeOrderOfClose()
+                   < handler2.getInvokeOrderOfClose());          
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());     
+    }
+    
+    @Test
+    public void testSOAPHandlerHandleMessageReturnFalseClientInbound() throws Exception {
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false);
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
+        TestSOAPHandler soapHandler2 = new TestSOAPHandler<SOAPMessageContext>(false) {
+            public boolean handleMessage(SOAPMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (!outbound) {
+                    return false;
+                }
+                return true;
+            }
+        };
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1, soapHandler2);
+
+        handlerTest.ping();
+
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(1, handler2.getHandleMessageInvoked());
+        assertEquals(1, soapHandler1.getHandleMessageInvoked());
+        assertEquals(2, soapHandler2.getHandleMessageInvoked());
+        
+        assertEquals("close must be called", 1, handler1.getCloseInvoked());
+        assertEquals("close must be called", 1, handler2.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler1.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler2.getCloseInvoked());
+        assertTrue(soapHandler2.getInvokeOrderOfClose()
+                   < soapHandler1.getInvokeOrderOfClose());   
+        assertTrue(soapHandler1.getInvokeOrderOfClose()
+                   < handler2.getInvokeOrderOfClose());          
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());         
     }
     
     @Test
     public void testLogicalHandlerHandleMessageReturnsFalseServerInbound() throws PingException {
         String[] expectedHandlers = {"soapHandler4", "soapHandler3", "handler2", 
-                                     "handler2", "soapHandler3", "soapHandler4"};
+                                     "soapHandler3", "soapHandler4"};
 
         List<String> resp = handlerTest.pingWithArgs("handler2 inbound stop");     
 
@@ -268,9 +374,26 @@
     }
     
     @Test
+    @Ignore
+    public void testLogicalHandlerHandleMessageReturnsFalseServerOutbound() throws PingException {
+        String[] expectedHandlers = {"handler2 outbound stop", "soapHandler4", "soapHandler3", "handler2",
+                                     "handler1", "handler1", "handler2"};
+
+        List<String> resp = handlerTest.pingWithArgs("handler2 outbound stop");     
+        for (String expected1 : resp) {
+            System.out.println(expected1);
+        }
+        assertEquals(expectedHandlers.length, resp.size());
+
+        int i = 0;
+        for (String expected : expectedHandlers) {
+            assertEquals(expected, resp.get(i++));
+        }
+    }
+    
+    @Test
     public void testSOAPHandlerHandleMessageReturnsFalseServerInbound() throws PingException {
-        String[] expectedHandlers = {"soapHandler4", "soapHandler3",
-                                     "soapHandler3", "soapHandler4"};
+        String[] expectedHandlers = {"soapHandler4", "soapHandler3", "soapHandler4"};
         List<String> resp = handlerTest.pingWithArgs("soapHandler3 inbound stop");
         assertEquals(expectedHandlers.length, resp.size());
         int i = 0;
@@ -300,11 +423,16 @@
         TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false) {
             public boolean handleMessage(LogicalMessageContext ctx) {
                 super.handleMessage(ctx);
-                throw new ProtocolException(clientHandlerMessage);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (outbound) {
+                    throw new ProtocolException(clientHandlerMessage);
+                }   
+                return true;
             }
         };
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
 
-        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2);
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1);
 
         try {
             handlerTest.ping();
@@ -312,15 +440,64 @@
         } catch (ProtocolException e) {
             assertEquals(clientHandlerMessage, e.getMessage());
         }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(1, handler2.getHandleMessageInvoked());
+        assertEquals(0, soapHandler1.getHandleMessageInvoked());
 
         assertEquals(0, handler2.getHandleFaultInvoked());
         assertEquals(1, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
 
         assertEquals(1, handler1.getCloseInvoked());
         assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(0, soapHandler1.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
     }
 
     @Test
+    public void testLogicalHandlerHandleMessageThrowsProtocolExceptionClientInbound() throws Exception {
+        final String clientHandlerMessage = "handler1 client side";
+
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false) {
+            public boolean handleMessage(LogicalMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (!outbound) {
+                    throw new ProtocolException(clientHandlerMessage);
+                }   
+                return true;
+            }
+        };
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
+
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1);
+
+        try {
+            handlerTest.ping();
+            fail("did not get expected exception");
+        } catch (ProtocolException e) {
+            assertEquals(clientHandlerMessage, e.getMessage());
+        }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(2, handler2.getHandleMessageInvoked());
+        assertEquals(2, soapHandler1.getHandleMessageInvoked());
+
+        assertEquals(0, handler2.getHandleFaultInvoked());
+        assertEquals(0, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
+
+        assertEquals(1, handler1.getCloseInvoked());
+        assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(1, soapHandler1.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
+    }
+    
+    @Test
     public void testLogicalHandlerHandleMessageThrowsRuntimeExceptionClientOutbound() throws Exception {
         final String clientHandlerMessage = "handler1 client side";
 
@@ -328,11 +505,16 @@
         TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false) {
             public boolean handleMessage(LogicalMessageContext ctx) {
                 super.handleMessage(ctx);
-                throw new RuntimeException(clientHandlerMessage);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (outbound) {
+                    throw new RuntimeException(clientHandlerMessage);
+                }   
+                return true;
             }
         };
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
 
-        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2);
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1);
 
         try {
             handlerTest.ping();
@@ -340,12 +522,195 @@
         } catch (RuntimeException e) {
             assertTrue(e.getMessage().contains(clientHandlerMessage));
         }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(1, handler2.getHandleMessageInvoked());
+        assertEquals(0, soapHandler1.getHandleMessageInvoked());
+        
+        assertEquals(0, handler2.getHandleFaultInvoked());
+        assertEquals(0, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
+
+        assertEquals(1, handler1.getCloseInvoked());
+        assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(0, soapHandler1.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
+    }
+    
+    @Test
+    public void testLogicalHandlerHandleMessageThrowsRuntimeExceptionClientInbound() throws Exception {
+        final String clientHandlerMessage = "handler1 client side";
+
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false) {
+            public boolean handleMessage(LogicalMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (!outbound) {
+                    throw new RuntimeException(clientHandlerMessage);
+                }   
+                return true;
+            }
+        };
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler(false);
+
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1);
+
+        try {
+            handlerTest.ping();
+            fail("did not get expected exception");
+        } catch (RuntimeException e) {
+            assertTrue(e.getMessage().contains(clientHandlerMessage));
+        }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(2, handler2.getHandleMessageInvoked());
+        assertEquals(2, soapHandler1.getHandleMessageInvoked());
+        
+        assertEquals(0, handler2.getHandleFaultInvoked());
+        assertEquals(0, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
+
+        assertEquals(1, handler1.getCloseInvoked());
+        assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(1, soapHandler1.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
+    }
+    
+    @Test
+    public void testSOAPHandlerHandleMessageThrowsProtocolExceptionClientOutbound() throws Exception {
+        final String clientHandlerMessage = "handler1 client side";
+
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false);
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler<SOAPMessageContext>(false) {
+            public boolean handleMessage(SOAPMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (outbound) {
+                    throw new ProtocolException(clientHandlerMessage);
+                }   
+                return true;
+            }
+        };
+        TestSOAPHandler soapHandler2 = new TestSOAPHandler(false);
+        
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1, soapHandler2);
+
+        try {
+            handlerTest.ping();
+            fail("did not get expected exception");
+        } catch (ProtocolException e) {
+            assertEquals(clientHandlerMessage, e.getMessage());
+        }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(1, handler2.getHandleMessageInvoked());
+        assertEquals(1, soapHandler1.getHandleMessageInvoked());
+        assertEquals(0, soapHandler2.getHandleMessageInvoked());
+
+        assertEquals(1, handler2.getHandleFaultInvoked());
+        assertEquals(1, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler2.getHandleFaultInvoked());
+
+        assertEquals(1, handler1.getCloseInvoked());
+        assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(1, soapHandler1.getCloseInvoked());
+        assertEquals(0, soapHandler2.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
+    }
+
+    @Test
+    public void testSOAPHandlerHandleMessageThrowsProtocolExceptionClientInbound() throws Exception {
+        final String clientHandlerMessage = "handler1 client side";
+
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false);
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler<SOAPMessageContext>(false) {
+            public boolean handleMessage(SOAPMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (!outbound) {
+                    throw new ProtocolException(clientHandlerMessage);
+                }   
+                return true;
+            }
+        };
+        TestSOAPHandler soapHandler2 = new TestSOAPHandler(false);
+        
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1, soapHandler2);
+
+        try {
+            handlerTest.ping();
+            fail("did not get expected exception");
+        } catch (ProtocolException e) {
+            assertEquals(clientHandlerMessage, e.getMessage());
+        }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(1, handler2.getHandleMessageInvoked());
+        assertEquals(2, soapHandler1.getHandleMessageInvoked());
+        assertEquals(2, soapHandler2.getHandleMessageInvoked());
 
         assertEquals(0, handler2.getHandleFaultInvoked());
         assertEquals(0, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler2.getHandleFaultInvoked());
 
         assertEquals(1, handler1.getCloseInvoked());
         assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(1, soapHandler1.getCloseInvoked());
+        assertEquals(1, soapHandler2.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
+    }
+    
+    @Test
+    public void testSOAPHandlerHandleMessageThrowsRuntimeExceptionClientOutbound() throws Exception {
+        final String clientHandlerMessage = "handler1 client side";
+
+        TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
+        TestHandler<LogicalMessageContext> handler2 = new TestHandler<LogicalMessageContext>(false);
+        TestSOAPHandler soapHandler1 = new TestSOAPHandler<SOAPMessageContext>(false) {
+            public boolean handleMessage(SOAPMessageContext ctx) {
+                super.handleMessage(ctx);
+                Boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+                if (outbound) {
+                    throw new RuntimeException(clientHandlerMessage);
+                }   
+                return true;
+            }
+        };
+        TestSOAPHandler soapHandler2 = new TestSOAPHandler(false);
+
+        addHandlersToChain((BindingProvider)handlerTest, handler1, handler2, soapHandler1, soapHandler2);
+        try {
+            handlerTest.ping();
+            fail("did not get expected exception");
+        } catch (RuntimeException e) {
+            assertTrue(e.getMessage().contains(clientHandlerMessage));
+        }
+        
+        assertEquals(1, handler1.getHandleMessageInvoked());
+        assertEquals(1, handler2.getHandleMessageInvoked());
+        assertEquals(1, soapHandler1.getHandleMessageInvoked());
+        assertEquals(0, soapHandler2.getHandleMessageInvoked());
+        
+        assertEquals(0, handler2.getHandleFaultInvoked());
+        assertEquals(0, handler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler1.getHandleFaultInvoked());
+        assertEquals(0, soapHandler2.getHandleFaultInvoked());
+
+        assertEquals(1, handler1.getCloseInvoked());
+        assertEquals(1, handler2.getCloseInvoked());
+        assertEquals(1, soapHandler1.getCloseInvoked());
+        assertEquals(0, soapHandler2.getCloseInvoked());
+        assertTrue(handler2.getInvokeOrderOfClose()
+                   < handler1.getInvokeOrderOfClose());   
     }
     
     @Test
@@ -443,7 +808,6 @@
 
     @Test
     public void testHandlersInvokedForDispatch() throws Exception {
-
         Dispatch<SOAPMessage> disp = service
             .createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE);
         TestHandler<LogicalMessageContext> handler1 = new TestHandler<LogicalMessageContext>(false);
@@ -463,11 +827,11 @@
         assertEquals("handle message was not invoked", 2, handler2.getHandleMessageInvoked());
         assertEquals("handle message was not invoked", 2, soapHandler1.getHandleMessageInvoked());
         assertEquals("handle message was not invoked", 2, soapHandler2.getHandleMessageInvoked());
-        // TODO: commented out, need to fix
-        // assertTrue("close must be called", handler1.isCloseInvoked());
-        // assertTrue("close must be called", handler2.isCloseInvoked());
-        // assertTrue("close must be called", soapHandler1.isCloseInvoked());
-        // assertTrue("close must be called", soapHandler2.isCloseInvoked());
+         
+        assertEquals("close must be called", 1, handler1.getCloseInvoked());
+        assertEquals("close must be called", 1, handler2.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler1.getCloseInvoked());
+        assertEquals("close must be called", 1, soapHandler2.getCloseInvoked());
 
         // the server has encoded into the response the order in
         // which the handlers have been invoked, parse it and make

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandler.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandler.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandler.java (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandler.java Tue May 15 07:30:53 2007
@@ -66,7 +66,7 @@
         printHandlerInfo("handleMessage", isOutbound(ctx));
 
         boolean outbound = (Boolean)ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
-        boolean ret = handleMessageRet; 
+        boolean ret = getHandleMessageRet(); 
 
         if (!isServerSideHandler()) {
             return true;
@@ -154,7 +154,7 @@
 
         LogicalMessage msg = ctx.getMessage();
         addHandlerId(msg, ctx, outbound);
-        return handleMessageRet;
+        return getHandleMessageRet();
     } 
 
     private void addHandlerId(LogicalMessage msg, T ctx, boolean outbound) { 

Modified: incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandlerBase.java
URL: http://svn.apache.org/viewvc/incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandlerBase.java?view=diff&rev=538188&r1=538187&r2=538188
==============================================================================
--- incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandlerBase.java (original)
+++ incubator/cxf/trunk/systests/src/test/java/org/apache/cxf/systest/handlers/TestHandlerBase.java Tue May 15 07:30:53 2007
@@ -40,13 +40,19 @@
  * @version 1.0
  */
 public abstract class TestHandlerBase {
-
+   
     private static final Logger LOG = Logger.getLogger(TestHandlerBase.class.getName());
 
-    private static int sid; 
+    private static int sid;
+    private static int sinvokedOrder;
+
+    private boolean handleMessageRet = true;
+
+    private int invokeOrderOfHandleMessage;
+    private int invokeOrderOfHandleFault;
+    private int invokeOrderOfClose;
 
-    protected boolean handleMessageRet = true; 
-    Map<String, Integer> methodCallCount = new HashMap<String, Integer>();
+    private Map<String, Integer> methodCallCount = new HashMap<String, Integer>();
     private final int id;
     private final boolean isServerSideHandler;
 
@@ -60,10 +66,29 @@
         if (methodCallCount.keySet().contains(methodName)) { 
             val = methodCallCount.get(methodName);
         } 
+        if ("handleMessage".equals(methodName)) {
+            invokeOrderOfHandleMessage = ++sinvokedOrder;
+        } else if ("handleFault".equals(methodName)) {
+            invokeOrderOfHandleFault = ++sinvokedOrder;
+        } else if ("close".equals(methodName)) {
+            invokeOrderOfClose = ++sinvokedOrder;
+        }
+
         val++; 
         methodCallCount.put(methodName, val);
     } 
 
+    public int getInvokeOrderOfHandleMessage() {
+        return invokeOrderOfHandleMessage;
+    }
+    
+    public int getInvokeOrderOfHandleFault() {
+        return invokeOrderOfHandleFault;
+    }
+    
+    public int getInvokeOrderOfClose() {
+        return invokeOrderOfClose;
+    }  
     
     public int getId() {
         return id; 
@@ -112,6 +137,10 @@
         handleMessageRet = ret; 
     }
 
+    public boolean getHandleMessageRet() { 
+        return handleMessageRet; 
+    }
+    
     public boolean isServerSideHandler() {
         return isServerSideHandler; 
     }