diff options
Diffstat (limited to 'sca-java-2.x/trunk')
12 files changed, 183 insertions, 63 deletions
diff --git a/sca-java-2.x/trunk/modules/binding-sca-runtime/META-INF/MANIFEST.MF b/sca-java-2.x/trunk/modules/binding-sca-runtime/META-INF/MANIFEST.MF index 6fa81c6834..90adf537f3 100644 --- a/sca-java-2.x/trunk/modules/binding-sca-runtime/META-INF/MANIFEST.MF +++ b/sca-java-2.x/trunk/modules/binding-sca-runtime/META-INF/MANIFEST.MF @@ -16,6 +16,7 @@ Import-Package: javax.xml.namespace, org.apache.tuscany.sca.contribution.processor;version="2.0.0",
org.apache.tuscany.sca.contribution.resolver;version="2.0.0";resolution:=optional,
org.apache.tuscany.sca.core;version="2.0.0",
+ org.apache.tuscany.sca.databinding;version="2.0.0",
org.apache.tuscany.sca.definitions;version="2.0.0",
org.apache.tuscany.sca.interfacedef;version="2.0.0",
org.apache.tuscany.sca.invocation;version="2.0.0",
diff --git a/sca-java-2.x/trunk/modules/binding-sca-runtime/pom.xml b/sca-java-2.x/trunk/modules/binding-sca-runtime/pom.xml index 40ca972851..3d260a30e6 100644 --- a/sca-java-2.x/trunk/modules/binding-sca-runtime/pom.xml +++ b/sca-java-2.x/trunk/modules/binding-sca-runtime/pom.xml @@ -58,7 +58,7 @@ <dependency> <groupId>org.apache.tuscany.sca</groupId> - <artifactId>tuscany-core-spi</artifactId> + <artifactId>tuscany-databinding</artifactId> <version>2.0-SNAPSHOT</version> </dependency> diff --git a/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/RuntimeSCAReferenceBindingProvider.java b/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/RuntimeSCAReferenceBindingProvider.java index 22b1e5bd99..ec4e893b5f 100644 --- a/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/RuntimeSCAReferenceBindingProvider.java +++ b/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/RuntimeSCAReferenceBindingProvider.java @@ -27,6 +27,8 @@ import org.apache.tuscany.sca.assembly.SCABinding; import org.apache.tuscany.sca.assembly.SCABindingFactory; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; +import org.apache.tuscany.sca.databinding.Mediator; import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.InvocationChain; @@ -63,6 +65,7 @@ public class RuntimeSCAReferenceBindingProvider implements ReferenceBindingProvi private BindingProviderFactory<DistributedSCABinding> distributedProviderFactory = null; private ReferenceBindingProvider distributedProvider = null; private SCABindingFactory scaBindingFactory; + private Mediator mediator; public RuntimeSCAReferenceBindingProvider(ExtensionPointRegistry extensionPoints, RuntimeEndpointReference endpointReference) { @@ -82,6 +85,7 @@ public class RuntimeSCAReferenceBindingProvider implements ReferenceBindingProvi (BindingProviderFactory<DistributedSCABinding>)factoryExtensionPoint .getProviderFactory(DistributedSCABinding.class); + this.mediator = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); } public boolean isTargetRemote() { @@ -185,7 +189,11 @@ public class RuntimeSCAReferenceBindingProvider implements ReferenceBindingProvi RuntimeComponentService service = (RuntimeComponentService)target.getService(); if (service != null) { // not a callback wire InvocationChain chain = ((RuntimeEndpoint) target).getInvocationChain(operation); - return chain == null ? null : new SCABindingInvoker(chain); + + // it turns out that the chain source and target operations are the same, and are the operation + // from the target, not sure if thats by design or a bug. The SCA binding invoker needs to know + // the source and target class loaders so pass in the real source operation in the constructor + return chain == null ? null : new SCABindingInvoker(chain, operation, mediator); } } return null; diff --git a/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java b/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java index 4dee1b8601..0f46e9390f 100644 --- a/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java +++ b/sca-java-2.x/trunk/modules/binding-sca-runtime/src/main/java/org/apache/tuscany/sca/binding/sca/provider/SCABindingInvoker.java @@ -19,25 +19,34 @@ package org.apache.tuscany.sca.binding.sca.provider; +import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.invocation.DataExchangeSemantics; import org.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.InvocationChain; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; -import org.apache.tuscany.sca.invocation.DataExchangeSemantics; /** * @version $Rev$ $Date$ */ public class SCABindingInvoker implements Interceptor, DataExchangeSemantics { private InvocationChain chain; + private Mediator mediator; + private Operation sourceOperation; + private Operation targetOperation; + private boolean copyArgs; /** * Construct a SCABindingInvoker that delegates to the service invocaiton chain - * @param chain */ - public SCABindingInvoker(InvocationChain chain) { + public SCABindingInvoker(InvocationChain chain, Operation sourceOperation, Mediator mediator) { super(); this.chain = chain; + this.mediator = mediator; + this.sourceOperation = sourceOperation; + this.targetOperation = chain.getTargetOperation(); + initCopyArgs(); } /** @@ -58,15 +67,65 @@ public class SCABindingInvoker implements Interceptor, DataExchangeSemantics { * @see org.apache.tuscany.sca.invocation.Invoker#invoke(org.apache.tuscany.sca.invocation.Message) */ public Message invoke(Message msg) { - return getNext().invoke(msg); + + if (copyArgs) { + msg.setBody(mediator.copyInput(msg.getBody(), sourceOperation, targetOperation)); + } + + Message resultMsg = getNext().invoke(msg); + + if (copyArgs) { + // Note source and target operation swapped so result is in source class loader + if (resultMsg.isFault()) { + resultMsg.setFaultBody(mediator.copyFault(resultMsg.getBody(), targetOperation, sourceOperation)); + } else { + if (sourceOperation.getOutputType() != null) { + resultMsg.setBody(mediator.copyOutput(resultMsg.getBody(), targetOperation, sourceOperation)); + } + } + } + + return resultMsg; + } + + /** + * Work out if pass-by-value copies or cross classloader copies need to be done + * - if source and target are in different classloaders + * - if the interfaces are remotable unless @AllowsPassByReference or + * a data transformation has been done in the chain + * - what else? + * - have a flag to optionally disable copies for individual composite/service/operation + * to improve the performance of specific local invocations? + */ + private void initCopyArgs() { + this.copyArgs = crossClassLoaders() || isRemotable(); } + private boolean crossClassLoaders() { + // TODO: for now if the operation is remotable the cross classloader copying will + // happen automatically but this needs also to check the non-remotable operation classloaders + return false; + } + + /** + * Pass-by-value copies are required if the interfaces are remotable unless the + * implementation uses the @AllowsPassByReference annotation. + */ + protected boolean isRemotable() { + if (!sourceOperation.getInterface().isRemotable()) { + return false; + } + if (!chain.getTargetOperation().getInterface().isRemotable()) { + return false; + } + return true; + } + /** * @see org.apache.tuscany.sca.invocation.DataExchangeSemantics#allowsPassByReference() */ public boolean allowsPassByReference() { return false; -// return chain.allowsPassByReference(); } } diff --git a/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java b/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java index 27c25e7f71..0e615519f1 100644 --- a/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java +++ b/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java @@ -123,29 +123,6 @@ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { return isTransformationRequired(sourceOperation, targetOperation); } - /** - * FIXME: TUSCANY-2586, temporary work around till the JIRA is fixed to prevent - * the PassByValueInterceptor being used for services when the binding protocol - * doesn't need the copies done. - */ - protected boolean isOnMessage(Operation op) { - return "onMessage".equals(op.getName()); - } - - /** - * Pass-by-value copies are required if the interfaces are remotable unless the - * implementation uses the @AllowsPassByReference annotation. - */ - protected boolean isRemotable(InvocationChain chain, Operation sourceOperation, Operation targetOperation) { - if (!sourceOperation.getInterface().isRemotable()) { - return false; - } - if (!targetOperation.getInterface().isRemotable()) { - return false; - } - return true; - } - public void process(RuntimeEndpoint endpoint) { InterfaceContract sourceContract = endpoint.getBindingInterfaceContract(); InterfaceContract targetContract = endpoint.getComponentTypeServiceInterfaceContract(); @@ -165,15 +142,7 @@ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { if (isTransformationRequired(sourceContract, sourceOperation, targetContract, targetOperation)) { // Add the interceptor to the source side because multiple // references can be wired to the same service - interceptor = - new DataTransformationInterceptor(endpoint, sourceOperation, targetOperation, mediator); - } else { - // assume pass-by-values copies are required if interfaces are remotable and there is no data binding - // transformation, i.e. a transformation will result in a copy so another pass-by-value copy is unnecessary - if (!isOnMessage(targetOperation) && isRemotable(chain, sourceOperation, targetOperation)) { - interceptor = - new PassByValueInterceptor(mediator, chain, targetOperation); - } + interceptor = new DataTransformationInterceptor(endpoint, sourceOperation, targetOperation, mediator); } if (interceptor != null) { String phase = Phase.SERVICE_INTERFACE; @@ -202,15 +171,7 @@ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { if (isTransformationRequired(sourceContract, sourceOperation, targetContract, targetOperation)) { // Add the interceptor to the source side because multiple // references can be wired to the same service - interceptor = - new DataTransformationInterceptor(endpointReference, sourceOperation, targetOperation, mediator); - } else { - // assume pass-by-values copies are required if interfaces are remotable and there is no data binding - // transformation, i.e. a transformation will result in a copy so another pass-by-value copy is unnecessary - if (!isOnMessage(targetOperation) && isRemotable(chain, sourceOperation, targetOperation)) { - interceptor = - new PassByValueInterceptor(mediator, chain, targetOperation); - } + interceptor = new DataTransformationInterceptor(endpointReference, sourceOperation, targetOperation, mediator); } if (interceptor != null) { String phase = Phase.REFERENCE_INTERFACE; diff --git a/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java b/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java index bd214cb02c..a23adc75bd 100644 --- a/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java +++ b/sca-java-2.x/trunk/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java @@ -95,9 +95,14 @@ public class JAXBDataBinding extends BaseDataBinding { return true; } - @SuppressWarnings("unchecked") @Override public Object copy(Object arg, DataType dataType, Operation operation) { + return copy(arg, dataType, operation, dataType); + } + + @SuppressWarnings("unchecked") + @Override + public Object copy(Object arg, DataType dataType, Operation operation, DataType targetDataType) { try { boolean isElement = false; if (dataType == null) { @@ -112,7 +117,15 @@ public class JAXBDataBinding extends BaseDataBinding { arg = JAXBContextHelper.createJAXBElement(context, dataType, arg); Document doc = domHelper.newDocument(); context.createMarshaller().marshal(arg, doc); - Object value = context.createUnmarshaller().unmarshal(doc, dataType.getPhysical()); + + Object value; + if (targetDataType != null && targetDataType.getPhysical() != dataType.getPhysical()) { + JAXBContext targetContext = contextHelper.createJAXBContext(targetDataType); + value = targetContext.createUnmarshaller().unmarshal(doc, targetDataType.getPhysical()); + } else { + value = context.createUnmarshaller().unmarshal(doc, dataType.getPhysical()); + } + if (isElement && value instanceof JAXBElement) { return value; } diff --git a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java index 7c4ed35eb3..95de3a02f0 100644 --- a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java +++ b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DataBinding.java @@ -83,6 +83,16 @@ public interface DataBinding { Object copy(Object object, DataType dataType, Operation operation); /** + * Make a copy of the object for "pass-by-value" semantics and cross classloader invocations. + * + * @param object source object to copy + * @param dataType The data type + * @param operation The operation + * @return copy of the object passed in as argument + */ + Object copy(Object object, DataType dataType, Operation operation, DataType targetdataType); + + /** * Get the XML type helper for Java types * @return The databinding-specific XML type helper class */ diff --git a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java index 19455fcd29..b9ed72203e 100644 --- a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java +++ b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java @@ -169,6 +169,10 @@ public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoi return getDataBinding().copy(object, dataType, operation); } + public Object copy(Object object, DataType dataType, Operation operation, DataType targetdataType) { + return getDataBinding().copy(object, dataType, operation, targetdataType); + } + public String getName() { return name; } diff --git a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java index 8184d739a8..5bffa477bb 100644 --- a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java +++ b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java @@ -100,6 +100,15 @@ public interface Mediator { Object copy(Object data, DataType dataType); /** + * Copy the data + * @param data The orginal data + * @param dataType The data type + * @param targetDataType The target data type + * @return The copy + */ + Object copy(Object data, DataType dataType, DataType targetDataType); + + /** * Copy an array of data objects passed to an operation * @param data array of objects to copy * @return the copy @@ -107,6 +116,13 @@ public interface Mediator { public Object copyInput(Object input, Operation operation); /** + * Copy an array of data objects passed to an operation + * @param data array of objects to copy + * @return the copy + */ + public Object copyInput(Object input, Operation operation, Operation targetOperation); + + /** * Copy the output data * @param data The orginal output * @param operation The operation @@ -115,6 +131,15 @@ public interface Mediator { Object copyOutput(Object data, Operation operation); /** + * Copy the output data + * @param data The orginal output + * @param operation The operation + * @param targetOperation The target operation + * @return The copy + */ + Object copyOutput(Object data, Operation operation, Operation targetOperation); + + /** * Copy the fault data * @param fault The orginal fault data * @param operation The operation @@ -123,6 +148,15 @@ public interface Mediator { Object copyFault(Object fault, Operation operation); /** + * Copy the fault data + * @param fault The orginal fault data + * @param operation The operation + * @param targetOperation The target operation + * @return The copy + */ + Object copyFault(Object fault, Operation operation, Operation targetOperation); + + /** * Get the DataBindings used by this mediator. * @return */ diff --git a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java index cb9f2969e2..3877fd50f7 100644 --- a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java +++ b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/BaseDataBinding.java @@ -100,6 +100,10 @@ public abstract class BaseDataBinding implements DataBinding { } public Object copy(Object object, DataType dataType, Operation operation) { + return copy(object, dataType, operation, dataType); + } + + public Object copy(Object object, DataType dataType, Operation operation, DataType targetDataType) { return object; } diff --git a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java index 195c04e9c2..48515f8f0f 100644 --- a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java +++ b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java @@ -443,7 +443,11 @@ public class MediatorImpl implements Mediator { } public Object copy(Object data, DataType dataType) { - return copy(data, dataType, null); + return copy(data, dataType, null, null); + } + + public Object copy(Object data, DataType dataType, DataType targetDataType) { + return copy(data, dataType, null, targetDataType); } /** @@ -452,7 +456,7 @@ public class MediatorImpl implements Mediator { * @param dataType * @return a copy of the data */ - private Object copy(Object data, DataType dataType, Operation operation) { + private Object copy(Object data, DataType dataType, Operation operation, DataType targetDataType) { if (data == null) { return null; } @@ -515,11 +519,11 @@ public class MediatorImpl implements Mediator { } } - if (dataBinding != null) { - return dataBinding.copy(data, dataType, operation); - } else { + if (dataBinding == null) { return data; } + + return dataBinding.copy(data, dataType, operation, targetDataType); } /** @@ -528,11 +532,15 @@ public class MediatorImpl implements Mediator { * @return the copy */ public Object copyInput(Object input, Operation operation) { + return copyInput(input, operation, null); + } + public Object copyInput(Object input, Operation operation, 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> inputTypesTarget = targetOperation == null ? null : targetOperation.getInputType().getLogical(); Object[] copy = new Object[data.length]; Map<Object, Object> map = new IdentityHashMap<Object, Object>(); for (int i = 0, size = inputTypes.size(); i < size; i++) { @@ -544,7 +552,7 @@ public class MediatorImpl implements Mediator { if (copiedArg != null) { copy[i] = copiedArg; } else { - copiedArg = copy(arg, inputTypes.get(i)); + copiedArg = copy(arg, inputTypes.get(i), inputTypesTarget == null ? null : inputTypesTarget.get(i)); map.put(arg, copiedArg); copy[i] = copiedArg; } @@ -554,14 +562,22 @@ public class MediatorImpl implements Mediator { } public Object copyOutput(Object data, Operation operation) { - return copy(data, operation.getOutputType(), operation); + return copyOutput(data, operation, null); + } + public Object copyOutput(Object data, Operation operation, Operation targetOperation) { + return copy(data, operation.getOutputType(), operation, targetOperation.getOutputType()); } public Object copyFault(Object fault, Operation operation) { + return copyFault(fault, operation, null); + } + public Object copyFault(Object fault, Operation operation, Operation targetOperation) { if (faultExceptionMapper == null) { return fault; } - for (DataType et : operation.getFaultTypes()) { + List<DataType> fts = operation.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 = @@ -569,9 +585,15 @@ public class MediatorImpl implements Mediator { faultExceptionMapper.introspectFaultDataType(exType, operation, false); DataType faultType = exType.getLogical(); Object faultInfo = faultExceptionMapper.getFaultInfo(ex, faultType.getPhysical(), operation); - faultInfo = copy(faultInfo, faultType); - fault = - faultExceptionMapper.wrapFaultInfo(exType, ex.getMessage(), faultInfo, ex.getCause(), 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); return fault; } } diff --git a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java index 4981699792..70637b756e 100644 --- a/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java +++ b/sca-java-2.x/trunk/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java @@ -59,7 +59,7 @@ public class JavaBeansDataBinding extends BaseDataBinding { } @Override - public Object copy(Object arg, DataType dataType, Operation operation) { + public Object copy(Object arg, DataType dataType, Operation operation, DataType targetDataType) { if (arg == null) { return null; } @@ -82,12 +82,16 @@ public class JavaBeansDataBinding extends BaseDataBinding { // Work out which ClassLoader to use for deserializing arg // We want to use: + // * The ClassLoader of the targetDataType if it is not the System ClassLoader // * The ClassLoader of arg if it is not the System ClassLoader // * The ThreadContext ClassLoader if the ClassLoader of arg is the System ClassLoader // because Collection classes are loaded by the System ClassLoader but their contents // may be loaded from another ClassLoader // - ClassLoader classLoaderToUse = clazz.getClassLoader(); + ClassLoader classLoaderToUse = targetDataType.getPhysical().getClassLoader(); + if (classLoaderToUse == null) { + classLoaderToUse = clazz.getClassLoader(); + } if (classLoaderToUse == null) { // ClassLoader of arg is the System ClassLoader so we will use the ThreadContext ClassLoader |