summaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/sca/modules/binding-rmi-runtime/pom.xml8
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java210
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java63
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java297
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java64
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java24
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java78
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java30
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java7
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java52
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType3
-rw-r--r--java/sca/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite19
12 files changed, 529 insertions, 326 deletions
diff --git a/java/sca/modules/binding-rmi-runtime/pom.xml b/java/sca/modules/binding-rmi-runtime/pom.xml
index 7214f8cea8..fbeb11dfe7 100644
--- a/java/sca/modules/binding-rmi-runtime/pom.xml
+++ b/java/sca/modules/binding-rmi-runtime/pom.xml
@@ -56,11 +56,17 @@
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
+ <artifactId>tuscany-core</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-implementation-java-runtime</artifactId>
<version>2.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
-
+
<dependency>
<groupId>org.apache.tuscany.sca</groupId>
<artifactId>tuscany-node-impl</artifactId>
diff --git a/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java b/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java
index 7754fb5485..f06dfbc83b 100644
--- a/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java
+++ b/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIBindingInvoker.java
@@ -23,61 +23,193 @@ import java.lang.reflect.Method;
import java.rmi.Remote;
import org.apache.tuscany.sca.host.rmi.RMIHost;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil;
+import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
import org.apache.tuscany.sca.invocation.Invoker;
import org.apache.tuscany.sca.invocation.Message;
-import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
/**
* Invoker for RMI References.
- *
+ *
+ * When invoke is fire, the Service Interface can be Conversational or not, when
+ * Service Interface is conversational, so the Conversational Service Interface
+ * is created and loaded. Conversational Service Interface is responsable to
+ * carry conversationId to server side.
+ *
* @version $Rev$ $Date$
*/
public class RMIBindingInvoker implements Invoker, DataExchangeSemantics {
- private RMIHost rmiHost;
- private String uri;
- private Method remoteMethod;
- private Remote proxy;
+ private RMIHost rmiHost;
+ private String uri;
+ private Method referenceMethod;
+ private Remote proxy;
+ private Class<?> serviceInterface;
- public RMIBindingInvoker(RMIHost rmiHost, String uri, Method remoteMethod) {
- this.rmiHost = rmiHost;
- this.remoteMethod = remoteMethod;
- this.uri = uri;
- }
+ public RMIBindingInvoker(RMIHost rmiHost, String uri,
+ Class<?> serviceInterface, Operation operation) {
+ this.rmiHost = rmiHost;
+ this.uri = uri;
+ this.serviceInterface = serviceInterface;
+ try {
+ this.referenceMethod = JavaInterfaceUtil.findMethod(
+ serviceInterface, operation);
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(e);
+ }
+ ;
+ }
- public Message invoke(Message msg) {
- try {
+ public Message invoke(Message msg) {
+ try {
+ Object conversationId = msg.getFrom().getReferenceParameters().getConversationID();
+ boolean isConversational = conversationId != null;
+ Object resp;
+ if (isConversational) {
+ initProxy(serviceInterface, true);
+ resp = invokeConversational(conversationId, msg.getBody());
+ } else {
+ initProxy(serviceInterface, false);
+ resp = invokeTarget(msg.getBody());
+ }
+ msg.setBody(resp);
+ } catch (InvocationTargetException e) {
+ Throwable cause = getCause(e);
+ if (cause == null) {
+ cause = e.getCause();
+ }
+ msg.setFaultBody(cause);
+ } catch (Throwable e) {
+ msg.setFaultBody(e);
+ }
+ return msg;
+ }
- Object[] args = msg.getBody();
- Object resp = invokeTarget(args);
- msg.setBody(resp);
-
- } catch (InvocationTargetException e) {
- msg.setFaultBody(e.getCause());
- } catch (Throwable e) {
- msg.setFaultBody(e);
- }
+ /**
+ * Find Remote Service
+ *
+ * If Service Interface is conversational the Conversational Service
+ * Interface is created and loaded, this is necessary because RMI looking
+ * for Conversational Service Interface in client side, when any method in
+ * conversational service interface is called.
+ *
+ * @param serviceInterface
+ * The Service Interface
+ * @param isConversational
+ * Indicate if Service Interface is Conversational.
+ */
+ private void initProxy(Class<?> serviceInterface, boolean isConversational) {
+ if (proxy == null) {
+ if (isConversational) {
+ ConversationalServiceInterfaceFactory.create(serviceInterface);
+ }
+ proxy = rmiHost.findService(uri);
+ }
+ }
- return msg;
- }
+ /**
+ * Get the original throwable.
+ *
+ * If throwable was throws by Service Interface, than original throwable is
+ * returned, else null is returned.
+ *
+ * @param e The final Throwable
+ * @return The Original Throwable or null
+ */
+ private Throwable getCause(Throwable e) {
+ Throwable cause = e.getCause();
+ Throwable expectedCause = null;
+ for (Class<?> declaredType : referenceMethod.getExceptionTypes()) {
+ if (declaredType.isInstance(cause)) {
+ expectedCause = cause;
+ break;
+ }
+ }
+ if (expectedCause == null) {
+ expectedCause = getCause(cause);
+ }
+ return expectedCause;
+ }
- public Object invokeTarget(final Object payload) throws InvocationTargetException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException {
- if (proxy == null) {
- proxy = rmiHost.findService(uri);
- }
+ /**
+ * Invoke the Method in Conversational Service Interface. This method verify
+ * the parameters of reference method and create a new argument, that take the
+ * conversationId.
+ *
+ * @param conversationId
+ * The ConversationId generated by SCA
+ * @param args
+ * The parameters of Method of Service Interface
+ * @return The result of Method executed.
+ * @throws InvocationTargetException
+ * @throws SecurityException
+ * @throws NoSuchMethodException
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ */
+ private Object invokeConversational(Object conversationId, Object args)
+ throws InvocationTargetException, SecurityException,
+ NoSuchMethodException, IllegalArgumentException,
+ IllegalAccessException {
+ Object[] newParameters = null;
+ Class<?>[] newParametersType = null;
+ if (isWithoutParameters(args)) {
+ newParameters = new Object[1];
+ newParametersType = new Class[1];
+ } else {
+ Object[] parameters = (Object[]) args;
+ newParameters = new Object[parameters.length + 1];
+ System.arraycopy(args, 0, newParameters, 0, parameters.length);
+ Class<?>[] refParameters = referenceMethod.getParameterTypes();
+ newParametersType = new Class[refParameters.length + 1];
+ System.arraycopy(refParameters, 0, newParametersType, 0, refParameters.length);
+ }
+ newParameters[newParameters.length - 1] = new ConversationalParameter(conversationId);
+ newParametersType[newParametersType.length - 1] = ConversationalParameter.class;
+ Method conversationalMethod = proxy.getClass().getMethod(referenceMethod.getName(), newParametersType);
+ return invoke(conversationalMethod, proxy, newParameters);
+ }
- remoteMethod = proxy.getClass().getMethod(remoteMethod.getName(), remoteMethod.getParameterTypes());
+ /**
+ * Invoke the Method in Service Interface
+ *
+ * @param parameters
+ * The parameters of Method of Service Interface
+ * @return The result of Method executed.
+ * @throws InvocationTargetException
+ * @throws SecurityException
+ * @throws NoSuchMethodException
+ * @throws IllegalArgumentException
+ * @throws IllegalAccessException
+ */
+ private Object invokeTarget(final Object parameters)
+ throws InvocationTargetException, SecurityException,
+ NoSuchMethodException, IllegalArgumentException,
+ IllegalAccessException {
+
+ Method remoteMethod = proxy.getClass().getMethod(referenceMethod.getName(), referenceMethod.getParameterTypes());
+ return invoke(remoteMethod, proxy, parameters);
+ }
- if (payload != null && !payload.getClass().isArray()) {
- return remoteMethod.invoke(proxy, payload);
- } else {
- return remoteMethod.invoke(proxy, (Object[])payload);
- }
- }
+ private Object invoke(Method remoteMethod, Remote proxy,
+ final Object parameters) throws InvocationTargetException,
+ SecurityException, NoSuchMethodException, IllegalArgumentException,
+ IllegalAccessException {
+
+ if (parameters != null && !parameters.getClass().isArray()) {
+ return remoteMethod.invoke(proxy, parameters);
+ } else {
+ return remoteMethod.invoke(proxy, (Object[]) parameters);
+ }
+ }
- public boolean allowsPassByReference() {
- // RMI always pass by value
- return true;
- }
+ public boolean allowsPassByReference() {
+ // RMI always pass by value
+ return true;
+ }
+ private boolean isWithoutParameters(Object parameters) {
+ return (parameters == null || (parameters.getClass().isArray() && ((Object[]) parameters).length == 0));
+ }
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java b/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java
index 8a368a26c3..c9b6927222 100644
--- a/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java
+++ b/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIReferenceBindingProvider.java
@@ -19,14 +19,11 @@
package org.apache.tuscany.sca.binding.rmi.provider;
-import java.lang.reflect.Method;
-
import org.apache.tuscany.sca.binding.rmi.RMIBinding;
import org.apache.tuscany.sca.host.rmi.RMIHost;
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.provider.ReferenceBindingProvider;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
@@ -39,43 +36,37 @@ import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
*/
public class RMIReferenceBindingProvider implements ReferenceBindingProvider {
- private RuntimeComponentReference reference;
- private RMIBinding binding;
- private RMIHost rmiHost;
-
- public RMIReferenceBindingProvider(RuntimeComponent component,
- RuntimeComponentReference reference,
- RMIBinding binding,
- RMIHost rmiHost) {
- this.reference = reference;
- this.binding = binding;
- this.rmiHost = rmiHost;
- }
+ private RuntimeComponentReference reference;
+ private RMIBinding binding;
+ private RMIHost rmiHost;
+
+ public RMIReferenceBindingProvider(RuntimeComponent component,
+ RuntimeComponentReference reference, RMIBinding binding,
+ RMIHost rmiHost) {
+ this.reference = reference;
+ this.binding = binding;
+ this.rmiHost = rmiHost;
+ }
- public InterfaceContract getBindingInterfaceContract() {
- return reference.getInterfaceContract();
- }
-
- public Invoker createInvoker(Operation operation) {
- Class<?> iface = ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass();
- Method remoteMethod;
- try {
- remoteMethod = JavaInterfaceUtil.findMethod(iface, operation);
- } catch (NoSuchMethodException e) {
- throw new IllegalArgumentException(e);
- }
+ public InterfaceContract getBindingInterfaceContract() {
+ return reference.getInterfaceContract();
+ }
- return new RMIBindingInvoker(rmiHost, binding.getURI(), remoteMethod);
- }
+ public Invoker createInvoker(Operation operation) {
+ Class<?> serviceInterface = ((JavaInterface) reference
+ .getInterfaceContract().getInterface()).getJavaClass();
+ return new RMIBindingInvoker(rmiHost, binding.getURI(),
+ serviceInterface, operation);
+ }
- public void start() {
- }
+ public void start() {
+ }
- public void stop() {
- }
+ public void stop() {
+ }
- public boolean supportsOneWayInvocation() {
- return false;
- }
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java b/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java
index e277160aae..f8aa7dcf4a 100644
--- a/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java
+++ b/java/sca/modules/binding-rmi-runtime/src/main/java/org/apache/tuscany/sca/binding/rmi/provider/RMIServiceBindingProvider.java
@@ -19,29 +19,24 @@
package org.apache.tuscany.sca.binding.rmi.provider;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.Remote;
+import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.List;
import net.sf.cglib.asm.ClassWriter;
import net.sf.cglib.asm.Type;
import net.sf.cglib.core.Constants;
import net.sf.cglib.proxy.Enhancer;
-import net.sf.cglib.proxy.MethodInterceptor;
-import net.sf.cglib.proxy.MethodProxy;
import org.apache.tuscany.sca.binding.rmi.RMIBinding;
import org.apache.tuscany.sca.host.rmi.RMIHost;
import org.apache.tuscany.sca.host.rmi.RMIHostException;
import org.apache.tuscany.sca.interfacedef.Interface;
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.provider.ServiceBindingProvider;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeComponentService;
@@ -50,162 +45,140 @@ import org.osoa.sca.ServiceRuntimeException;
/**
* Implementation of a Service for the RMIBinding.
- *
+ *
* @version $Rev$ $Date$
*/
public class RMIServiceBindingProvider implements ServiceBindingProvider {
- private RuntimeComponent component;
- private RuntimeComponentService service;
- private RMIBinding binding;
- private RMIHost rmiHost;
- private RuntimeWire wire;
-
- public RMIServiceBindingProvider(RuntimeComponent rc, RuntimeComponentService rcs, RMIBinding binding, RMIHost rmiHost) {
- this.component = rc;
- this.service = rcs;
- this.binding = binding;
- this.rmiHost = rmiHost;
- }
-
- public void start() {
- // URI uri = URI.create(component.getURI() + "/" + binding.getName());
- // binding.setURI(uri.toString());
-
- wire = service.getRuntimeWire(binding);
- Interface serviceInterface = service.getInterfaceContract().getInterface();
-
- Remote rmiProxy = createRmiService(serviceInterface);
-
- try {
-
- rmiHost.registerService(binding.getURI(), rmiProxy);
-
- } catch (RMIHostException e) {
- throw new ServiceRuntimeException(e);
- }
- }
-
- public void stop() {
- rmiHost.unregisterService(binding.getURI());
- }
-
- private int getPort(String port) {
- int portNumber = RMIHost.RMI_DEFAULT_PORT;
- if (port != null && port.length() > 0) {
- portNumber = Integer.decode(port);
- }
- return portNumber;
- }
-
- private Remote createRmiService(final Interface serviceInterface) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(UnicastRemoteObject.class);
- enhancer.setCallback(new MethodInterceptor() {
- public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
- try {
- return invokeTarget(JavaInterfaceUtil.findOperation(method, serviceInterface.getOperations()), args);
- } catch (InvocationTargetException e) {
- final Throwable cause = e.getCause();
- for (Class<?> declaredType : method.getExceptionTypes()) {
- if (declaredType.isInstance(cause)) {
- throw e;
- }
- }
-
- if (cause.getCause() != null) {
- // TUSCANY-2545: don't inlcude nested cause object
- AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- Field field = Throwable.class.getDeclaredField("cause");
- field.setAccessible(true);
- field.set(cause, null);
- field.setAccessible(false);
- return null;
- }
- });
- }
-
- throw cause;
- }
- }
- });
- Class targetJavaInterface = getTargetJavaClass(serviceInterface);
- if (!Remote.class.isAssignableFrom(targetJavaInterface)) {
- RMIServiceClassLoader classloader = new RMIServiceClassLoader(targetJavaInterface.getClassLoader());
- final byte[] byteCode = generateRemoteInterface(targetJavaInterface);
- targetJavaInterface = classloader.defineClass(targetJavaInterface.getName(), byteCode);
- enhancer.setClassLoader(classloader);
- }
- enhancer.setInterfaces(new Class[] {targetJavaInterface});
- return (Remote)enhancer.create();
- }
-
- private Object invokeTarget(Operation op, Object[] args) throws InvocationTargetException {
- return wire.invoke(op, args);
- }
-
- /**
- * if the interface of the component whose serviceBindings must be exposed as RMI Service, does not
- * implement java.rmi.Remote, then generate such an interface. This method will stop with just
- * generating the bytecode. Defining the class from the byte code must be the responsibility of the
- * caller of this method, since it requires a ClassLoader to be created to define and load this interface.
- */
- private byte[] generateRemoteInterface(Class serviceInterface) {
- String interfazeName = serviceInterface.getName();
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-
- String simpleName = serviceInterface.getSimpleName();
- cw.visit(Constants.V1_5, Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT + Constants.ACC_INTERFACE, interfazeName
- .replace('.', '/'), null, "java/lang/Object", new String[] {"java/rmi/Remote"});
-
- StringBuffer argsAndReturn = null;
- Method[] methods = serviceInterface.getMethods();
- for (Method method : methods) {
- argsAndReturn = new StringBuffer("(");
- Class[] paramTypes = method.getParameterTypes();
- Class returnType = method.getReturnType();
-
- for (Class paramType : paramTypes) {
- argsAndReturn.append(Type.getType(paramType));
- }
- argsAndReturn.append(")");
- argsAndReturn.append(Type.getType(returnType));
-
- cw.visitMethod(Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT,
- method.getName(),
- argsAndReturn.toString(),
- null,
- new String[] {"java/rmi/RemoteException"});
- }
- cw.visitEnd();
- return cw.toByteArray();
- }
-
- private Class<?> getTargetJavaClass(Interface targetInterface) {
- // TODO: right now assume that the target is always a Java
- // Implementation. Need to figure out
- // how to generate Java Interface in cases where the target is not a
- // Java Implementation
- return ((JavaInterface)targetInterface).getJavaClass();
- }
-
- protected class RMIServiceClassLoader extends ClassLoader {
- public RMIServiceClassLoader(ClassLoader parent) {
- super(parent);
- }
-
- public Class defineClass(String name, byte[] byteArray) {
- return defineClass(name, byteArray, 0, byteArray.length);
- }
- }
-
- public InterfaceContract getBindingInterfaceContract() {
- return service.getInterfaceContract();
- }
-
- public boolean supportsOneWayInvocation() {
- return false;
- }
-
+ private RuntimeComponent component;
+ private RuntimeComponentService service;
+ private RMIBinding binding;
+ private RMIHost rmiHost;
+ private RuntimeWire wire;
+
+ public RMIServiceBindingProvider(RuntimeComponent component,
+ RuntimeComponentService service, RMIBinding binding, RMIHost rmiHost) {
+ this.component = component;
+ this.service = service;
+ this.binding = binding;
+ this.rmiHost = rmiHost;
+ }
+
+ public void start() {
+ wire = service.getRuntimeWire(binding);
+ Interface serviceInterface = service.getInterfaceContract()
+ .getInterface();
+ Remote rmiProxy = createRmiService(serviceInterface);
+ try {
+ rmiHost.registerService(binding.getURI(), rmiProxy);
+ } catch (RMIHostException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public void stop() {
+ rmiHost.unregisterService(binding.getURI());
+ }
+
+ protected Remote createRmiService(final Interface serviceInterface) {
+ Enhancer enhancer = new Enhancer();
+ enhancer.setSuperclass(UnicastRemoteObject.class);
+ enhancer.setCallback(new RMIMethodInterceptor(wire, serviceInterface));
+ Class<?> targetJavaInterface = getTargetJavaClass(serviceInterface);
+ List<Class<?>> interfaces = new ArrayList<Class<?>>();
+ RMIServiceClassLoader classloader = new RMIServiceClassLoader(
+ targetJavaInterface.getClassLoader());
+ if (!Remote.class.isAssignableFrom(targetJavaInterface)) {
+ final byte[] byteCode = generateRemoteInterface(targetJavaInterface);
+ targetJavaInterface = classloader.defineClass(targetJavaInterface
+ .getName(), byteCode);
+ }
+ interfaces.add(targetJavaInterface);
+ if (serviceInterface.isConversational()) {
+ Class<?> conversationalInterface = ConversationalServiceInterfaceFactory
+ .create(targetJavaInterface);
+ final byte[] byteCode = generateRemoteInterface(conversationalInterface);
+ conversationalInterface = classloader.defineClass(
+ conversationalInterface.getName(), byteCode);
+ interfaces.add(conversationalInterface);
+ }
+ enhancer.setClassLoader(classloader);
+ enhancer.setInterfaces(interfaces.toArray(new Class[] {}));
+ return (Remote) enhancer.create();
+ }
+
+ /**
+ * if the interface of the component whose serviceBindings must be exposed
+ * as RMI Service, does not implement java.rmi.Remote, then generate such an
+ * interface. This method will stop with just generating the bytecode.
+ * Defining the class from the byte code must be the responsibility of the
+ * caller of this method, since it requires a ClassLoader to be created to
+ * define and load this interface.
+ */
+ private byte[] generateRemoteInterface(Class serviceInterface) {
+ String interfazeName = serviceInterface.getName();
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+
+ cw.visit(Constants.V1_5, Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT
+ + Constants.ACC_INTERFACE, interfazeName.replace('.', '/'),
+ null, "java/lang/Object", new String[] { "java/rmi/Remote" });
+ StringBuffer argsAndReturn = null;
+ Method[] methods = serviceInterface.getMethods();
+ for (Method method : methods) {
+ argsAndReturn = new StringBuffer("(");
+ Class<?>[] paramTypes = method.getParameterTypes();
+ Class<?> returnType = method.getReturnType();
+
+ for (Class<?> paramType : paramTypes) {
+ argsAndReturn.append(Type.getType(paramType));
+ }
+ argsAndReturn.append(")");
+ argsAndReturn.append(Type.getType(returnType));
+
+ boolean hasRemoteException = false;
+ List<String> exceptions = new ArrayList<String>();
+ Class<?>[] exceptionTypes = method.getExceptionTypes();
+ for (int i = 0, s = exceptionTypes.length; i < s; i++) {
+ if (exceptionTypes[i].equals(RemoteException.class)) {
+ hasRemoteException = true;
+ }
+ exceptions.add(exceptionTypes[i].getName().replace('.', '/'));
+ }
+ if (!hasRemoteException) {
+ exceptions.add("java/rmi/RemoteException");
+ }
+ cw.visitMethod(Constants.ACC_PUBLIC + Constants.ACC_ABSTRACT,
+ method.getName(), argsAndReturn.toString(), null,
+ exceptions.toArray(new String[] {}));
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ private Class<?> getTargetJavaClass(Interface targetInterface) {
+ // TODO: right now assume that the target is always a Java
+ // Implementation. Need to figure out
+ // how to generate Java Interface in cases where the target is not a
+ // Java Implementation
+ return ((JavaInterface) targetInterface).getJavaClass();
+ }
+
+ protected class RMIServiceClassLoader extends ClassLoader {
+ public RMIServiceClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ public Class defineClass(String name, byte[] byteArray) {
+ return defineClass(name, byteArray, 0, byteArray.length);
+ }
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ return service.getInterfaceContract();
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return false;
+ }
+
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java
index cbc860ecc6..e4af1b92ec 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java
+++ b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloException.java
@@ -24,37 +24,37 @@ package helloworld;
*/
public class HelloException extends Exception {
- /**
- *
- */
- private static final long serialVersionUID = 2570611055132507470L;
-
- /**
- *
- */
- public HelloException() {
- }
-
- /**
- * @param message
- */
- public HelloException(String message) {
- super(message);
- }
-
- /**
- * @param cause
- */
- public HelloException(Throwable cause) {
- super(cause);
- }
-
- /**
- * @param message
- * @param cause
- */
- public HelloException(String message, Throwable cause) {
- super(message, cause);
- }
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2570611055132507470L;
+
+ /**
+ *
+ */
+ public HelloException() {
+ }
+
+ /**
+ * @param message
+ */
+ public HelloException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param cause
+ */
+ public HelloException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public HelloException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java
index 0a1f4283db..64745639b1 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java
+++ b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldImpl.java
@@ -20,23 +20,23 @@ package helloworld;
import org.osoa.sca.annotations.Service;
-
/**
* This class implements the HelloWorld service.
- *
+ *
* @version $Rev$ $Date$
*/
@Service(HelloWorldService.class)
public class HelloWorldImpl implements HelloWorldService {
- public String sayHello(String name) {
- return "Hello from the RMI Service to - " + name;
- }
-
- public String sayHi(String name, String greeter) throws HelloException {
- if (name == null || greeter == null) {
- throw new HelloException("Invalid name or greeter: name=" + name + " greeter=" + greeter);
- }
- return "Hi from " + greeter + " in RMI Service to - " + name;
- }
+ public String sayHello(String name) {
+ return "Hello from the RMI Service to - " + name;
+ }
+
+ public String sayHi(String name, String greeter) throws HelloException {
+ if (name == null || greeter == null) {
+ throw new HelloException("Invalid name or greeter: name=" + name
+ + " greeter=" + greeter);
+ }
+ return "Hi from " + greeter + " in RMI Service to - " + name;
+ }
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java
index 5b20d17c83..c0c49da215 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java
+++ b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiImpl.java
@@ -19,32 +19,70 @@
package helloworld;
import org.osoa.sca.annotations.Reference;
+import org.osoa.sca.annotations.Scope;
import org.osoa.sca.annotations.Service;
/**
- * This class implements the HelloWorld service.
- *
+ * This class implements the HelloWorld service. The Scope is CONVERSATION to
+ * test the RMI Conversational Service and Conversational in interface and
+ * Scope("CONVERSATION") in Implementation keep the same instance of the
+ * references. But only references conversational are Stateful.
+ * HelloWorldService is stateless is keep stateless.
+ * HelloWorldConversationalService is stateful.
+ *
+ * When BindingTestCase take a instance of HelloWorldRmiImpl it is use the same
+ * instance of the HelloWorldRmiImpl to all method invocation, how
+ * extConversationService is conversational (stateful) too, your state is keep
+ * between call, differently of the extService that is stateless.
+ *
* @version $Rev$ $Date$
*/
@Service(HelloWorldRmiService.class)
+@Scope("CONVERSATION")
public class HelloWorldRmiImpl implements HelloWorldRmiService {
- private HelloWorldService extService;
-
- public HelloWorldService getExtService() {
- return extService;
- }
-
- @Reference
- public void setExtService(HelloWorldService extService) {
- this.extService = extService;
- }
-
- public String sayRmiHello(String name) {
- return extService.sayHello(name) + " thro the RMI Reference";
- }
-
- public String sayRmiHi(String name, String greeter) throws HelloException {
- return extService.sayHi(name, greeter) + " thro the RMI Reference";
- }
+ private HelloWorldService extService;
+ private HelloWorldConversationalService extConversationalService;
+ private static final String COMPLEMENT = " thro the RMI Reference";
+
+ public HelloWorldService getExtService() {
+ return extService;
+ }
+
+ @Reference
+ public void setExtService(HelloWorldService extService) {
+ this.extService = extService;
+ }
+
+ @Reference
+ public void setExtConversationalService(
+ HelloWorldConversationalService extConversationalService) {
+ this.extConversationalService = extConversationalService;
+ }
+
+ public String sayRmiHello(String name) {
+ return extService.sayHello(name) + COMPLEMENT;
+ }
+
+ public String sayRmiHi(String name, String greeter) throws HelloException {
+ return extService.sayHi(name, greeter) + COMPLEMENT;
+ }
+
+ public String getConversationalHello() {
+ return extConversationalService.getHello() + COMPLEMENT;
+ }
+
+ public String getConversationalHi() {
+ return extConversationalService.getHi() + COMPLEMENT;
+ }
+
+ public void sayRmiConversationalHello(String name) {
+ extConversationalService.sayHello(name);
+
+ }
+
+ public void sayRmiConversationalHi(String name, String greeter)
+ throws HelloException {
+ extConversationalService.sayHi(name, greeter);
+ }
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java
index 461c176e1e..2742ab14c0 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java
+++ b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldRmiService.java
@@ -18,14 +18,36 @@
*/
package helloworld;
+import org.osoa.sca.annotations.Conversational;
+
/**
- * This is the business interface of the HelloWorld greetings service.
- *
+ * This is the business interface of the HelloWorld greetings service. This
+ * interface is Conversational to test the RMI Conversational Service and
+ * Conversational in interface and Scope("CONVERSATION") in Implementation keep
+ * the same instance of the references. But only references conversational are
+ * Stateful. HelloWorldService is stateless is keep stateless.
+ * HelloWorldConversationalService is stateful.
+ *
+ * When BindingTestCase take a instance of HelloWorldRmiImpl it is use the same
+ * instance of the HelloWorldRmiImpl in all method invocation, how
+ * extConversationService is conversational (stateful) too, your state is keep
+ * between call, differently of the extService that is stateless.
+ *
* @version $Rev$ $Date$
*/
+@Conversational
public interface HelloWorldRmiService {
- String sayRmiHello(String name);
- String sayRmiHi(String name, String greeter) throws HelloException;
+ String sayRmiHello(String name);
+
+ String sayRmiHi(String name, String greeter) throws HelloException;
+
+ void sayRmiConversationalHello(String name);
+
+ void sayRmiConversationalHi(String name, String greeter)
+ throws HelloException;
+
+ String getConversationalHello();
+ String getConversationalHi();
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java
index 3b705d2c97..999dfc2052 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java
+++ b/java/sca/modules/binding-rmi-runtime/src/test/java/helloworld/HelloWorldService.java
@@ -20,12 +20,13 @@ package helloworld;
/**
* This is the business interface of the HelloWorld greetings service.
- *
+ *
* @version $Rev$ $Date$
*/
public interface HelloWorldService {
- String sayHello(String name);
- String sayHi(String name, String greeter) throws HelloException;
+ String sayHello(String name);
+
+ String sayHi(String name, String greeter) throws HelloException;
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java b/java/sca/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java
index c62e3a6b8b..a59507c144 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java
+++ b/java/sca/modules/binding-rmi-runtime/src/test/java/org/apache/tuscany/sca/binding/rmi/BindingTestCase.java
@@ -39,8 +39,26 @@ public class BindingTestCase {
private static HelloWorldRmiService helloWorldRmiService;
private static Node node;
+ @BeforeClass
+ public static void init() throws Exception {
+ try {
+ String contribution = ContributionLocationHelper.getContributionLocation(BindingTestCase.class);
+ node = NodeFactory.newInstance().createNode("RMIBindingTest.composite", new Contribution("test", contribution));
+ node.start();
+ helloWorldRmiService = node.getService(HelloWorldRmiService.class, "HelloWorldRmiServiceComponent");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ node.stop();
+ node.destroy();
+ }
+
@Test
- public void testRmiService() {
+ public void performRmiNormalService() {
String msg = helloWorldRmiService.sayRmiHello("Tuscany World!");
System.out.println(msg);
Assert.assertEquals("Hello from the RMI Service to - Tuscany World! thro the RMI Reference", msg);
@@ -60,22 +78,28 @@ public class BindingTestCase {
}
}
- @BeforeClass
- public static void init() throws Exception {
+ @Test
+ public void performRmiConversationalService() {
+ helloWorldRmiService.sayRmiConversationalHello("Tuscany World!");
+ String msg = helloWorldRmiService.getConversationalHello();
+ System.out.println(msg);
+ Assert.assertEquals("Hello from the RMI Service to - Tuscany World! thro the RMI Reference", msg);
+
try {
- String contribution = ContributionLocationHelper.getContributionLocation(BindingTestCase.class);
- node = NodeFactory.newInstance().createNode("RMIBindingTest.composite", new Contribution("test", contribution));
- node.start();
- helloWorldRmiService = node.getService(HelloWorldRmiService.class, "HelloWorldRmiServiceComponent");
- } catch (Exception e) {
- e.printStackTrace();
+ helloWorldRmiService.sayRmiConversationalHi("Tuscany World!", "Apache World");
+ msg = helloWorldRmiService.getConversationalHi();
+ System.out.println(msg);
+ Assert.assertEquals("Hi from Apache World in RMI Service to - Tuscany World! thro the RMI Reference", msg);
+ } catch (HelloException e) {
+ Assert.fail(e.getMessage());
+ }
+ try {
+ helloWorldRmiService.sayRmiConversationalHi(null, "Apache World");
+ Assert.fail("HelloException should have been thrown");
+ } catch (HelloException e) {
+ System.out.println("Expected exception :" + e.getClass().getName());
}
}
- @AfterClass
- public static void destroy() throws Exception {
- node.stop();
- node.destroy();
- }
}
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType b/java/sca/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType
index a83e7e6d1d..6857c03802 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType
+++ b/java/sca/modules/binding-rmi-runtime/src/test/resources/HelloWorldRmiImpl.componentType
@@ -24,4 +24,7 @@
<reference name="extService">
<interface.java interface="helloworld.HelloWorldService"/>
</reference>
+ <reference name="extConversationalService">
+ <interface.java interface="helloworld.HelloWorldConversationalService"/>
+ </reference>
</componentType>
diff --git a/java/sca/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite b/java/sca/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite
index 2a0bcf0f76..8d19d92036 100644
--- a/java/sca/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite
+++ b/java/sca/modules/binding-rmi-runtime/src/test/resources/RMIBindingTest.composite
@@ -20,24 +20,37 @@
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
name="HelloWorldRmiComposite">
-
+
+ <!-- PROVIDER -->
<service name="HelloWorldRmiService" promote="HelloWorldServiceComponent">
<interface.java interface="helloworld.HelloWorldService"/>
<tuscany:binding.rmi uri="rmi://localhost:8099/HelloWorldRemoteService" />
</service>
-
<component name="HelloWorldServiceComponent">
<implementation.java class="helloworld.HelloWorldImpl"/>
</component>
+ <service name="HelloWorldRmiConversationalService" promote="HelloWorldConversationalServiceComponent">
+ <interface.java interface="helloworld.HelloWorldConversationalService"/>
+ <tuscany:binding.rmi uri="rmi://localhost:8099/HelloWorldRemoteConversationalService"/>
+ </service>
+ <component name="HelloWorldConversationalServiceComponent">
+ <implementation.java class="helloworld.HelloWorldConversationalImpl"/>
+ </component>
+
+ <!-- CONSUMER -->
<component name="HelloWorldRmiServiceComponent">
<implementation.java class="helloworld.HelloWorldRmiImpl"/>
<reference name="extService"></reference>
+ <reference name="extConversationalService"></reference>
</component>
<reference name="HelloWorldRmiReference" promote="HelloWorldRmiServiceComponent/extService">
<interface.java interface="helloworld.HelloWorldService"/>
<tuscany:binding.rmi uri="rmi://localhost:8099/HelloWorldRemoteService" />
</reference>
-
+ <reference name="HelloWorldRmiConversationalReference" promote="HelloWorldRmiServiceComponent/extConversationalService">
+ <interface.java interface="helloworld.HelloWorldConversationalService"/>
+ <tuscany:binding.rmi uri="rmi://localhost:8099/HelloWorldRemoteConversationalService" />
+ </reference>
</composite>