You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by rf...@apache.org on 2010/03/11 05:44:12 UTC

svn commit: r921689 - in /tuscany/sca-java-2.x/trunk: itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/ itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/ modules/binding-sca-runtim...

Author: rfeng
Date: Thu Mar 11 04:44:11 2010
New Revision: 921689

URL: http://svn.apache.org/viewvc?rev=921689&view=rev
Log:
Fix for TUSCANY-3489

Added:
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java   (with props)
Modified:
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/ClientImpl.java
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/Remote.java
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/RemoteServiceImpl.java
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/SCAClientImpl.java
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/BindingSCATestCase.java
    tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/ClientSharedLocalTestCase.java
    tuscany/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java
    tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java
    tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java

Modified: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/ClientImpl.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/ClientImpl.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/ClientImpl.java (original)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/ClientImpl.java Thu Mar 11 04:44:11 2010
@@ -34,7 +34,12 @@ public class ClientImpl implements Clien
     protected Remote remote;
 
     public String getName(String id) {
-        Customer customer = remote.getCustomer(id);
+        Customer customer = null;
+        try {
+            customer = remote.getCustomer(id);
+        } catch (CustomerNotFoundException e) {
+            return null;
+        }
         customer.dump("Client.getName()");
         return local.getName(customer);
     }

Added: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java?rev=921689&view=auto
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java (added)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java Thu Mar 11 04:44:11 2010
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.tuscany.sca.itest.bindingsca;
+
+/**
+ * 
+ */
+public class CustomerNotFoundException extends Exception {
+    private String customerId;
+
+    /**
+     * 
+     */
+    public CustomerNotFoundException() {
+    }
+
+    /**
+     * @param message
+     */
+    public CustomerNotFoundException(String message) {
+        super(message);
+    }
+
+    /**
+     * @param cause
+     */
+    public CustomerNotFoundException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * @param message
+     * @param cause
+     */
+    public CustomerNotFoundException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public String getCustomerId() {
+        return customerId;
+    }
+
+    public void setCustomerId(String customerId) {
+        this.customerId = customerId;
+    }
+
+}

Propchange: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/CustomerNotFoundException.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/Remote.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/Remote.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/Remote.java (original)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/Remote.java Thu Mar 11 04:44:11 2010
@@ -30,7 +30,7 @@ public interface Remote {
 
     String getId(Customer customer);
 
-    Customer getCustomer(String id);
+    Customer getCustomer(String id) throws CustomerNotFoundException;
 
     Customer createCustomer(String id, String name);
 }

Modified: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/RemoteServiceImpl.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/RemoteServiceImpl.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/RemoteServiceImpl.java (original)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/RemoteServiceImpl.java Thu Mar 11 04:44:11 2010
@@ -45,8 +45,13 @@ public class RemoteServiceImpl implement
         return customer.getId();
     }
 
-    public Customer getCustomer(String id) {
+    public Customer getCustomer(String id) throws CustomerNotFoundException {
         Customer customer = customers.get(id);
+        if (customer == null) {
+            CustomerNotFoundException ex = new CustomerNotFoundException("Customer not found");
+            ex.setCustomerId(id);
+            throw ex;
+        }
         customer.dump("Remote.getCustomer()");
         return customer;
     }

Modified: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/SCAClientImpl.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/SCAClientImpl.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/SCAClientImpl.java (original)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/main/java/org/apache/tuscany/sca/itest/bindingsca/SCAClientImpl.java Thu Mar 11 04:44:11 2010
@@ -37,7 +37,12 @@ public class SCAClientImpl implements Cl
     }
 
     public String getName(String id) {
-        Customer customer = remote.getCustomer(id);
+        Customer customer = null;
+        try {
+            customer = remote.getCustomer(id);
+        } catch (CustomerNotFoundException e) {
+            return null;
+        }
         customer.dump("Client.getName()");
         return local.getName(customer);
     }

Modified: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/BindingSCATestCase.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/BindingSCATestCase.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/BindingSCATestCase.java (original)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/BindingSCATestCase.java Thu Mar 11 04:44:11 2010
@@ -134,6 +134,11 @@ public class BindingSCATestCase {
         String id = client.create("Ray");
         Assert.assertEquals("Ray", client.getName(id));
     }
+    
+    static void runClientNotFound(Client client) {
+        String id = "not-there";
+        Assert.assertNull(client.getName(id));
+    }
 
     static String createCustomer(Node node) {
         Client client = node.getService(Client.class, "ClientComponent/Client");

Modified: tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/ClientSharedLocalTestCase.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/ClientSharedLocalTestCase.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/ClientSharedLocalTestCase.java (original)
+++ tuscany/sca-java-2.x/trunk/itest/nodes/binding-sca-tribes/src/test/java/org/apache/tuscany/sca/itest/bindingsca/ClientSharedLocalTestCase.java Thu Mar 11 04:44:11 2010
@@ -36,7 +36,7 @@ public class ClientSharedLocalTestCase {
     public static void setUpBeforeClass() throws Exception {
         runner =
             new TestCaseRunner(ServiceNode.class, Remote.class.getName(), RemoteServiceImpl.class.getName(),
-                               Customer.class.getName());
+                               Customer.class.getName(), CustomerNotFoundException.class.getName());
         runner.beforeClass();
         client = new SCAClientImpl(BindingSCATestCase.DOMAIN_URI);
         Thread.sleep(1000);
@@ -46,6 +46,12 @@ public class ClientSharedLocalTestCase {
     public void testClient() throws Exception {
         BindingSCATestCase.runClient(client);
     }
+    
+    @Test
+    public void testClientNotFound() throws Exception {
+        BindingSCATestCase.runClientNotFound(client);
+    }
+
 
     @AfterClass
     public static void tearDownAfterClass() throws Exception {

Modified: tuscany/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java Thu Mar 11 04:44:11 2010
@@ -78,10 +78,10 @@ public class SCABindingInvoker implement
         if (passByValue) {
             // Note source and target operation swapped so result is in source class loader
             if (resultMsg.isFault()) {
-                resultMsg.setFaultBody(mediator.copyFault(resultMsg.getBody(), targetOperation, sourceOperation));
+                resultMsg.setFaultBody(mediator.copyFault(resultMsg.getBody(), sourceOperation, targetOperation));
             } else {
                 if (sourceOperation.getOutputType() != null) {
-                    resultMsg.setBody(mediator.copyOutput(resultMsg.getBody(), targetOperation, sourceOperation));
+                    resultMsg.setBody(mediator.copyOutput(resultMsg.getBody(), sourceOperation, targetOperation));
                 }
             }
         }

Modified: tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java Thu Mar 11 04:44:11 2010
@@ -132,10 +132,11 @@ public interface Mediator {
 
     /**
      * Copy an array of data objects passed to an operation
-     * @param data array of objects to copy
+     * @param sourceOperation The source operation
+     * @param targetOperation The target operation
      * @return the copy
      */
-    public Object copyInput(Object input, Operation operation, Operation targetOperation);
+    public Object copyInput(Object input, Operation sourceOperation, Operation targetOperation);
 
     /**
      * Copy the output data
@@ -146,13 +147,13 @@ public interface Mediator {
     Object copyOutput(Object data, Operation operation);
 
     /**
-     * Copy the output data
+     * Copy the output data from target operation into source operation
      * @param data The orginal output
-     * @param operation The operation
+     * @param sourceOperation The operation
      * @param targetOperation The target operation
      * @return The copy
      */
-    Object copyOutput(Object data, Operation operation, Operation targetOperation);
+    Object copyOutput(Object data, Operation sourceOperation, Operation targetOperation);
 
     /**
      * Copy the fault data
@@ -163,13 +164,13 @@ public interface Mediator {
     Object copyFault(Object fault, Operation operation);
 
     /**
-     * Copy the fault data
+     * Copy the fault data from target operation into source operation
      * @param fault The orginal fault data
-     * @param operation The operation
+     * @param sourceOperation The operation
      * @param targetOperation The target operation
      * @return The copy
      */
-    Object copyFault(Object fault, Operation operation, Operation targetOperation);
+    Object copyFault(Object fault, Operation sourceOperation, Operation targetOperation);
 
     /**
      * Get the DataBindings used by this mediator.

Modified: tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java
URL: http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java?rev=921689&r1=921688&r2=921689&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java (original)
+++ tuscany/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java Thu Mar 11 04:44:11 2010
@@ -49,6 +49,7 @@ import org.apache.tuscany.sca.databindin
 import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding;
 import org.apache.tuscany.sca.interfacedef.DataType;
 import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper;
+import org.apache.tuscany.sca.interfacedef.InterfaceContractMapper;
 import org.apache.tuscany.sca.interfacedef.Operation;
 import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
 import org.apache.tuscany.sca.interfacedef.util.FaultException;
@@ -67,6 +68,7 @@ public class MediatorImpl implements Med
     private ExtensionPointRegistry registry;
     private DataBindingExtensionPoint dataBindings;
     private TransformerExtensionPoint transformers;
+    private InterfaceContractMapper interfaceContractMapper;
     private FaultExceptionMapper faultExceptionMapper;
 
     MediatorImpl(DataBindingExtensionPoint dataBindings, TransformerExtensionPoint transformers) {
@@ -78,8 +80,9 @@ public class MediatorImpl implements Med
         this.registry = registry;
         this.dataBindings = registry.getExtensionPoint(DataBindingExtensionPoint.class);
         this.transformers = registry.getExtensionPoint(TransformerExtensionPoint.class);
-        this.faultExceptionMapper =
-            registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(FaultExceptionMapper.class);
+        UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
+        this.interfaceContractMapper = utilities.getUtility(InterfaceContractMapper.class);
+        this.faultExceptionMapper = utilities.getUtility(FaultExceptionMapper.class);
 
     }
 
@@ -207,6 +210,11 @@ public class MediatorImpl implements Med
         return transformers;
     }
 
+    /**
+     * Find the fault data type behind the exception data type
+     * @param exceptionType The exception data type
+     * @return The fault data type
+     */
     private DataType getFaultType(DataType exceptionType) {
         return exceptionType == null ? null : (DataType)exceptionType.getLogical();
     }
@@ -277,30 +285,11 @@ public class MediatorImpl implements Med
         if (result instanceof InvocationTargetException) {
             result = ((InvocationTargetException)result).getCause();
         }
-        DataType targetDataType = null;
-        for (DataType exType : targetOperation.getFaultTypes()) {
-            if (((Class)exType.getPhysical()).isInstance(result)) {
-                if (result instanceof FaultException) {
-                    DataType faultType = (DataType)exType.getLogical();
-                    if (((FaultException)result).isMatchingType(faultType.getLogical())) {
-                        targetDataType = exType;
-                        break;
-                    }
-                } else {
-                    targetDataType = exType;
-                    break;
-                }
-            }
-        }
+        
+        DataType targetDataType = findFaultDataType(targetOperation, result);
+        DataType targetFaultType = getFaultType(targetDataType);
 
-        /*
-        if (targetDataType == null) {
-            // Not a business exception
-            return resultMsg;
-        }
-        */
 
-        DataType targetFaultType = getFaultType(targetDataType);
         if (targetFaultType == null) {
             // No matching fault type, it's a system exception
             Throwable cause = (Throwable)result;
@@ -345,6 +334,31 @@ public class MediatorImpl implements Med
 
     }
 
+    /**
+     * Look up the fault data type that matches the fault or exception instance 
+     * @param operation The operation
+     * @param faultOrException The fault or exception
+     * @return The matching fault data type
+     */
+    private DataType findFaultDataType(Operation operation, Object faultOrException) {
+        DataType targetDataType = null;
+        for (DataType exType : operation.getFaultTypes()) {
+            if (((Class)exType.getPhysical()).isInstance(faultOrException)) {
+                if (faultOrException instanceof FaultException) {
+                    DataType faultType = (DataType)exType.getLogical();
+                    if (((FaultException)faultOrException).isMatchingType(faultType.getLogical())) {
+                        targetDataType = exType;
+                        break;
+                    }
+                } else {
+                    targetDataType = exType;
+                    break;
+                }
+            }
+        }
+        return targetDataType;
+    }
+
     private boolean typesMatch(Object first, Object second) {
         if (first.equals(second)) {
             return true;
@@ -525,14 +539,14 @@ public class MediatorImpl implements Med
      * @return the copy
      */
     public Object copyInput(Object input, Operation operation) {
-        return copyInput(input, operation, null);
+        return copyInput(input, operation, operation);
     }
-    public Object copyInput(Object input, Operation operation, Operation targetOperation) {
+    public Object copyInput(Object input, Operation sourceOperation, Operation targetOperation) {
         if (input == null) {
             return null;
         }
         Object[] data = (input instanceof Object[]) ? (Object[])input : new Object[] {input};
-        List<DataType> inputTypes = operation.getInputType().getLogical();
+        List<DataType> inputTypes = sourceOperation.getInputType().getLogical();
         List<DataType> inputTypesTarget = targetOperation == null ? null : targetOperation.getInputType().getLogical();
         Object[] copy = new Object[data.length];
         Map<Object, Object> map = new IdentityHashMap<Object, Object>();
@@ -545,7 +559,12 @@ public class MediatorImpl implements Med
                 if (copiedArg != null) {
                     copy[i] = copiedArg;
                 } else {
-                    copiedArg = copy(arg, inputTypes.get(i), inputTypesTarget == null ? null : inputTypesTarget.get(i));
+                    copiedArg =
+                        copy(arg,
+                             inputTypes.get(i),
+                             inputTypesTarget == null ? null : inputTypesTarget.get(i),
+                             sourceOperation,
+                             targetOperation);
                     map.put(arg, copiedArg);
                     copy[i] = copiedArg;
                 }
@@ -555,42 +574,55 @@ public class MediatorImpl implements Med
     }
 
     public Object copyOutput(Object data, Operation operation) {
-        return copyOutput(data, operation, null);
+        return copyOutput(data, operation, operation);
     }
-    public Object copyOutput(Object data, Operation operation, Operation targetOperation) {
-        return copy(data, operation.getOutputType(), targetOperation.getOutputType(), operation, targetOperation);
+    
+    public Object copyOutput(Object data, Operation sourceOperation, Operation targetOperation) {
+        return copy(data, targetOperation.getOutputType(), sourceOperation.getOutputType(), targetOperation, sourceOperation);
     }
 
     public Object copyFault(Object fault, Operation operation) {
-        return copyFault(fault, operation, null);
+        return copyFault(fault, operation, operation);
     }
-    public Object copyFault(Object fault, Operation operation, Operation targetOperation) {
+    
+    public Object copyFault(Object fault, Operation sourceOperation, Operation targetOperation) {
         if (faultExceptionMapper == null) {
             return fault;
         }
-        List<DataType> fts = operation.getFaultTypes();
-        for (int i=0; i<fts.size(); i++) {
+        List<DataType> fts = targetOperation.getFaultTypes();
+        for (int i = 0; i < fts.size(); i++) {
             DataType et = fts.get(i); 
             if (et.getPhysical().isInstance(fault)) {
                 Throwable ex = (Throwable)fault;
-                DataType<DataType> exType =
-                    new DataTypeImpl<DataType>(ex.getClass(), new DataTypeImpl<XMLType>(ex.getClass(), XMLType.UNKNOWN));
-                faultExceptionMapper.introspectFaultDataType(exType, operation, false);
-                DataType faultType = exType.getLogical();
-                Object faultInfo = faultExceptionMapper.getFaultInfo(ex, faultType.getPhysical(), operation);
-                DataType targetFaultType;
-                try {
-                    targetFaultType = (DataType)faultType.clone();
-                } catch (CloneNotSupportedException e) {
-                    throw new IllegalStateException(e);
-                }
-                targetFaultType.setPhysical(targetOperation.getFaultTypes().get(i).getPhysical());
-                faultInfo = copy(faultInfo, faultType, targetFaultType);
-                fault = faultExceptionMapper.wrapFaultInfo(exType, ex.getMessage(), faultInfo, ex.getCause(), operation);
+                DataType<DataType> exType = findFaultDataType(targetOperation, fault);
+                DataType faultType = getFaultType(exType);
+                Object faultInfo = faultExceptionMapper.getFaultInfo(ex, faultType.getPhysical(), targetOperation);
+                DataType targetExType = findSourceFaultDataType(sourceOperation, exType);
+                DataType targetFaultType = getFaultType(targetExType);
+                faultInfo = copy(faultInfo, faultType, targetFaultType, targetOperation, sourceOperation);
+                fault = faultExceptionMapper.wrapFaultInfo(targetExType, ex.getMessage(), faultInfo, ex.getCause(), sourceOperation);
                 return fault;
             }
         }
         return fault;
     }
+    
+    /**
+     * Lookup a fault data type from the source operation which matches the target fault data type
+     * @param sourceOperation The source operation
+     * @param targetExceptionType The target fault data type
+     * @return The matching source target fault type
+     */
+    private DataType findSourceFaultDataType(Operation sourceOperation, DataType targetExceptionType) {
+        boolean remotable = sourceOperation.getInterface().isRemotable();
+        DataType targetFaultType = getFaultType(targetExceptionType);
+        for (DataType dt : sourceOperation.getFaultTypes()) {
+            DataType sourceFaultType = getFaultType(dt);
+            if (interfaceContractMapper.isCompatible(targetFaultType, sourceFaultType, remotable)) {
+                return dt;
+            }
+        }
+        return null;
+    }
 
 }