From 219ae1935ec10aeb4b5a1955183272cda9a3a574 Mon Sep 17 00:00:00 2001 From: bdaniel Date: Wed, 18 Aug 2010 13:53:47 +0000 Subject: TUSCANY-3652 Inject callbacks at service invocation git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@986678 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/context/ReflectiveInstanceFactory.java | 5 ++- .../java/context/ReflectiveInstanceWrapper.java | 10 ++++- .../invocation/JavaAsyncImplementationInvoker.java | 7 +-- .../invocation/JavaComponentContextProvider.java | 23 ++++++++-- .../java/invocation/JavaImplementationInvoker.java | 50 +++++++++++++++++++--- .../invocation/JavaImplementationProvider.java | 6 +-- .../invocation/JavaInstanceFactoryProvider.java | 34 ++++++++++++--- 7 files changed, 112 insertions(+), 23 deletions(-) (limited to 'sca-java-2.x/trunk/modules/implementation-java-runtime/src') diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java index 209546ce2f..f5d9860130 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceFactory.java @@ -36,15 +36,18 @@ public class ReflectiveInstanceFactory implements InstanceFactory { private final Injector[] injectors; private final EventInvoker initInvoker; private final EventInvoker destroyInvoker; + private final Injector[] callbackInjectors; public ReflectiveInstanceFactory(Constructor ctr, ObjectFactory[] ctrArgs, Injector[] injectors, + Injector[] callbackInjectors, EventInvoker initInvoker, EventInvoker destroyInvoker) { this.ctr = ctr; this.ctrArgs = ctrArgs; this.injectors = injectors; + this.callbackInjectors = callbackInjectors; this.initInvoker = initInvoker; this.destroyInvoker = destroyInvoker; } @@ -88,6 +91,6 @@ public class ReflectiveInstanceFactory implements InstanceFactory { } } - return new ReflectiveInstanceWrapper(instance, initInvoker, destroyInvoker); + return new ReflectiveInstanceWrapper(instance, initInvoker, destroyInvoker, callbackInjectors); } } diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java index 7c96606cf6..a3ed16dde5 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/context/ReflectiveInstanceWrapper.java @@ -21,6 +21,7 @@ package org.apache.tuscany.sca.implementation.java.context; import org.apache.tuscany.sca.core.factory.InstanceWrapper; import org.apache.tuscany.sca.core.scope.TargetDestructionException; import org.apache.tuscany.sca.core.scope.TargetInitializationException; +import org.apache.tuscany.sca.implementation.java.injection.Injector; import org.apache.tuscany.sca.implementation.java.invocation.EventInvoker; /** @@ -30,11 +31,13 @@ public class ReflectiveInstanceWrapper implements InstanceWrapper { private final EventInvoker initInvoker; private final EventInvoker destroyInvoker; private final T instance; + private final Injector[] callbackInjectors; - public ReflectiveInstanceWrapper(T instance, EventInvoker initInvoker, EventInvoker destroyInvoker) { + public ReflectiveInstanceWrapper(T instance, EventInvoker initInvoker, EventInvoker destroyInvoker, Injector[] callbackInjectors) { this.instance = instance; this.initInvoker = initInvoker; this.destroyInvoker = destroyInvoker; + this.callbackInjectors = callbackInjectors; } public T getInstance() { @@ -61,4 +64,9 @@ public class ReflectiveInstanceWrapper implements InstanceWrapper { destroyInvoker.invokeEvent(instance); } } + + public Injector[] getCallbackInjectors() { + return this.callbackInjectors; + } + } diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java index de810a0f02..97b7570faa 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaAsyncImplementationInvoker.java @@ -21,12 +21,12 @@ package org.apache.tuscany.sca.implementation.java.invocation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.concurrent.TimeUnit; import org.apache.tuscany.sca.core.factory.InstanceWrapper; import org.apache.tuscany.sca.core.factory.ObjectCreationException; import org.apache.tuscany.sca.core.invocation.AsyncResponseException; import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.invocation.Message; @@ -41,8 +41,9 @@ import org.oasisopen.sca.ServiceRuntimeException; */ public class JavaAsyncImplementationInvoker extends JavaImplementationInvoker { - public JavaAsyncImplementationInvoker(Operation operation, Method method, RuntimeComponent component) { - super( operation, method, component); + public JavaAsyncImplementationInvoker(Operation operation, Method method, RuntimeComponent component, + InterfaceContract interfaceContract) { + super( operation, method, component, interfaceContract); assert method != null : "Operation method cannot be null"; assert ((JavaOperation) operation).isAsyncServer() : "Operation must be async"; } // end constructor diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java index ea9aec5238..1fa51315c3 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaComponentContextProvider.java @@ -52,10 +52,13 @@ import org.apache.tuscany.sca.core.scope.TargetResolutionException; import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; import org.apache.tuscany.sca.implementation.java.JavaConstructorImpl; import org.apache.tuscany.sca.implementation.java.JavaElementImpl; +import org.apache.tuscany.sca.implementation.java.JavaImplementation; import org.apache.tuscany.sca.implementation.java.JavaResourceImpl; +import org.apache.tuscany.sca.implementation.java.JavaScopeImpl; import org.apache.tuscany.sca.implementation.java.context.InstanceFactory; import org.apache.tuscany.sca.implementation.java.injection.JavaPropertyValueObjectFactory; import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; @@ -76,6 +79,7 @@ public class JavaComponentContextProvider { private JavaInstanceFactoryProvider instanceFactoryProvider; private ProxyFactory proxyFactory; private InstanceFactory instanceFactory; + private JavaScopeImpl scope; public JavaComponentContextProvider(RuntimeComponent component, JavaInstanceFactoryProvider configuration, @@ -93,6 +97,7 @@ public class JavaComponentContextProvider { // } this.component = component; this.propertyValueFactory = (JavaPropertyValueObjectFactory) propertyValueObjectFactory; + this.scope = ((JavaImplementation)component.getImplementation()).getJavaScope(); } InstanceWrapper createInstanceWrapper() throws ObjectCreationException { @@ -144,6 +149,16 @@ public class JavaComponentContextProvider { } void start() { + List callbackInjectionList = null; + + // If the component implementation is stateless, we need to inject the callbacks on service invocation + // rather than doing it once at the component level. + if ( scope.equals(JavaScopeImpl.STATELESS)) { + callbackInjectionList = instanceFactoryProvider.getCallbackInjectionSites(); + } else { + callbackInjectionList = instanceFactoryProvider.getInjectionSites(); + } + if (!instanceFactoryProvider.getImplementation().getCallbackMembers().isEmpty()) { Map> callbackWires = new HashMap>(); for (ComponentService service : component.getServices()) { @@ -179,7 +194,7 @@ public class JavaComponentContextProvider { factory = new CallbackWireObjectFactory(businessInterface, proxyFactory, wires); } if (!(element.getAnchor() instanceof Constructor)) { - instanceFactoryProvider.getInjectionSites().add(element); + callbackInjectionList.add(element); } instanceFactoryProvider.setObjectFactory(element, factory); } @@ -288,15 +303,15 @@ public class JavaComponentContextProvider { //cleanUpPolicyHandlers(); } - Invoker createInvoker(Operation operation) throws NoSuchMethodException { + Invoker createInvoker(Operation operation, InterfaceContract interfaceContract) throws NoSuchMethodException { Class implClass = instanceFactoryProvider.getImplementationClass(); Method method = JavaInterfaceUtil.findMethod(implClass, operation); if (operation instanceof JavaOperation && ((JavaOperation) operation).isAsyncServer() ) { - return new JavaAsyncImplementationInvoker(operation, method, component); + return new JavaAsyncImplementationInvoker(operation, method, component, interfaceContract); } else { - return new JavaImplementationInvoker(operation, method, component); + return new JavaImplementationInvoker(operation, method, component, interfaceContract); } // end if } // end diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java index 4d54fbd46c..13fcfbf413 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java @@ -22,17 +22,23 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.apache.tuscany.sca.assembly.EndpointReference; -import org.apache.tuscany.sca.core.factory.InstanceWrapper; import org.apache.tuscany.sca.core.factory.ObjectCreationException; +import org.apache.tuscany.sca.core.scope.Scope; import org.apache.tuscany.sca.core.scope.ScopeContainer; import org.apache.tuscany.sca.core.scope.ScopedRuntimeComponent; import org.apache.tuscany.sca.implementation.java.JavaImplementation; +import org.apache.tuscany.sca.implementation.java.context.ReflectiveInstanceWrapper; +import org.apache.tuscany.sca.implementation.java.injection.Injector; +import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHelper; import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.oasisopen.sca.ServiceReference; import org.oasisopen.sca.ServiceRuntimeException; /** @@ -48,19 +54,22 @@ public class JavaImplementationInvoker implements Invoker { @SuppressWarnings("unchecked") protected final ScopeContainer scopeContainer; + private final InterfaceContract interfaze; - public JavaImplementationInvoker(Operation operation, Method method, RuntimeComponent component) { + public JavaImplementationInvoker(Operation operation, Method method, RuntimeComponent component, InterfaceContract intf) { assert method != null : "Operation method cannot be null"; this.method = method; this.operation = operation; this.scopeContainer = ((ScopedRuntimeComponent)component).getScopeContainer(); this.allowsPBR = ((JavaImplementation)component.getImplementation()).isAllowsPassByReference(method); + this.interfaze = intf; } - public JavaImplementationInvoker(Operation operation, RuntimeComponent component) { + public JavaImplementationInvoker(Operation operation, RuntimeComponent component, InterfaceContract intf) { // used if the method can't be computed statically in advance this.operation = operation; this.scopeContainer = ((ScopedRuntimeComponent)component).getScopeContainer(); + this.interfaze = intf; } @SuppressWarnings("unchecked") @@ -83,8 +92,14 @@ public class JavaImplementationInvoker implements Invoker { try { // The following call might create a new conversation, as a result, the msg.getConversationID() might // return a new value - InstanceWrapper wrapper = scopeContainer.getWrapper(contextId); - + ReflectiveInstanceWrapper wrapper = (ReflectiveInstanceWrapper) scopeContainer.getWrapper(contextId); + + // If there is a callback interface and the implementation is stateless, we need to + // inject callbacks at invocation time. For Composite scope, this has already been done. + if (( interfaze.getCallbackInterface() != null ) && (scopeContainer.getScope().equals(Scope.STATELESS))){ + injectCallbacks(wrapper, (JavaInterface)interfaze.getCallbackInterface()); + } + Object instance = wrapper.getInstance(); // If the method couldn't be computed statically, or the instance being @@ -149,4 +164,29 @@ public class JavaImplementationInvoker implements Invoker { return msg; } + private void injectCallbacks(ReflectiveInstanceWrapper wrapper, + JavaInterface callbackInterface) { + + for (Injector injector : wrapper.getCallbackInjectors()) { + if (injector != null) { + try { + if (ServiceReference.class.isAssignableFrom(injector.getType())) { + Class intf = JavaIntrospectionHelper.getBusinessInterface(injector.getType(), injector.getGenericType()); + if ( intf.isAssignableFrom(callbackInterface.getJavaClass())) { + injector.inject(wrapper.getInstance()); + } + } else if (injector.getType().isAssignableFrom(callbackInterface.getJavaClass())) { + injector.inject(wrapper.getInstance()); + } else { + injector.injectNull(wrapper.getInstance()); + } + } catch (Exception e) { + throw new ObjectCreationException("Exception invoking injector - " + e.getMessage(), e); + } + } + } + + } + + } diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java index 3cee156d76..d7abd021f6 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationProvider.java @@ -118,7 +118,7 @@ public class JavaImplementationProvider implements ScopedImplementationProvider public Invoker createInvoker(RuntimeComponentService service, Operation operation) { try { - return componentContextProvider.createInvoker(operation); + return componentContextProvider.createInvoker(operation, service.getInterfaceContract()); } catch (NoSuchMethodException e) { // It's possible that the instance being invoked is a user-specified // callback object that isn't an instance of the component implementation @@ -132,12 +132,12 @@ public class JavaImplementationProvider implements ScopedImplementationProvider if (iface instanceof JavaInterface) { try { Method method = JavaInterfaceUtil.findMethod(((JavaInterface)iface).getJavaClass(), operation); - return new JavaImplementationInvoker(operation, method, componentContextProvider.getComponent()); + return new JavaImplementationInvoker(operation, method, componentContextProvider.getComponent(), service.getInterfaceContract()); } catch (NoSuchMethodException e1) { throw new IllegalArgumentException(e1); } } else { - return new JavaImplementationInvoker(operation, componentContextProvider.getComponent()); + return new JavaImplementationInvoker(operation, componentContextProvider.getComponent(), service.getInterfaceContract()); } } } diff --git a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java index 7fcfaad615..1f1f1eefdc 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java +++ b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaInstanceFactoryProvider.java @@ -57,6 +57,7 @@ public class JavaInstanceFactoryProvider implements InstanceFactoryProvider initInvoker; private final EventInvoker destroyInvoker; private final Map factories = new HashMap(); + private final List callbackInjectionSites; public JavaInstanceFactoryProvider(JavaImplementation definition) { this.definition = definition; @@ -65,6 +66,7 @@ public class JavaInstanceFactoryProvider implements InstanceFactoryProvider(definition .getDestroyMethod()); injectionSites = new ArrayList(); + callbackInjectionSites = new ArrayList(); } ProxyFactory getProxyFactory() { @@ -85,12 +87,15 @@ public class JavaInstanceFactoryProvider implements InstanceFactoryProvider createFactory() { ObjectFactory[] initArgs = getConstructorArgs(); - Injector[] injectors = getInjectors(); + Injector[] injectors = getInjectors(false); + Injector[] callbackInjectors = getInjectors(true); return new ReflectiveInstanceFactory((Constructor)definition.getConstructor().getConstructor(), - initArgs, injectors, initInvoker, destroyInvoker); + initArgs, injectors, callbackInjectors, initInvoker, destroyInvoker); } - private ObjectFactory[] getConstructorArgs() { + + + private ObjectFactory[] getConstructorArgs() { JavaConstructorImpl constructor = definition.getConstructor(); ObjectFactory[] initArgs = new ObjectFactory[constructor.getParameters().length]; for (int i = 0; i < initArgs.length; i++) { @@ -101,13 +106,21 @@ public class JavaInstanceFactoryProvider implements InstanceFactoryProvider[] getInjectors() { + private Injector[] getInjectors(boolean callback) { + List sites = null; + if ( callback ) + sites = callbackInjectionSites; + else + sites = injectionSites; + // work around JDK1.5 issue with allocating generic arrays - Injector[] injectors = new Injector[injectionSites.size()]; + Injector[] injectors = new Injector[sites.size()]; int i = 0; - for (JavaElementImpl element : injectionSites) { + for (JavaElementImpl element : sites) { Object obj = factories.get(element); if (obj != null) { if (obj instanceof ObjectFactory) { @@ -172,6 +185,13 @@ public class JavaInstanceFactoryProvider implements InstanceFactoryProvider getCallbackInjectionSites() { + return callbackInjectionSites; + } + /** * @return the factories */ @@ -179,4 +199,6 @@ public class JavaInstanceFactoryProvider implements InstanceFactoryProvider