You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by ke...@apache.org on 2011/05/19 19:01:09 UTC
svn commit: r1124995 - in /openejb/trunk/openejb3/server:
openejb-client/src/main/java/org/apache/openejb/client/
openejb-client/src/test/java/org/apache/openejb/client/
openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/
Author: kevan
Date: Thu May 19 17:01:09 2011
New Revision: 1124995
URL: http://svn.apache.org/viewvc?rev=1124995&view=rev
Log:
OPENEJB-1165 Got Ivan's original remote patch building. Have not done any additional testing
Modified:
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Client.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBMetaDataImpl.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBObjectHandler.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBRequest.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/RequestMethodConstants.java
openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Response.java
openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/EJBRequestTest.java
openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/LoginTestUtil.java
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/ClientObjectFactory.java
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/JndiRequestHandler.java
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Client.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Client.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Client.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Client.java Thu May 19 17:01:09 2011
@@ -68,14 +68,21 @@ public class Client {
public static Response request(Request req, Response res, ServerMetaData server) throws RemoteException {
try {
- return client.processRequest(req, res, server);
+ return client.processRequest(req, res, server, null);
} finally {
failed.remove();
}
}
- protected Response processRequest(Request req, Response res, ServerMetaData server) throws RemoteException {
-// System.out.println("req = " + req);
+ public static Response request(Request req, Response res, ServerMetaData server, URI preferedServerURI) throws RemoteException {
+ try {
+ return client.processRequest(req, res, server, preferedServerURI);
+ } finally {
+ failed.remove();
+ }
+ }
+
+ protected Response processRequest(Request req, Response res, ServerMetaData server, URI preferredServerURI) throws RemoteException {
if (server == null)
throw new IllegalArgumentException("Server instance cannot be null");
@@ -87,9 +94,16 @@ public class Client {
Connection conn = null;
try {
- conn = ConnectionManager.getConnection(cluster, server, req);
+ if (preferredServerURI != null) {
+ conn = ConnectionManager.getConnection(preferredServerURI);
+ } else {
+ conn = ConnectionManager.getConnection(cluster, server, req);
+ }
+ if (res instanceof EJBResponse) {
+ ((EJBResponse) res).setResponseServerURI(conn.getURI());
+ }
} catch (IOException e) {
- throw new RemoteException("Unable to connect",e);
+ throw new RemoteException("Unable to connect", e);
}
try {
@@ -278,9 +292,11 @@ public class Client {
Set<URI> failed = getFailed();
failed.add(conn.getURI());
conn.discard();
- if (e instanceof RetryException || getRetry()){
+ //If the preferred server URI is configured, we will not try to fail over to other servers
+ //Currently, while calling Future.cancel method remotely, the initial business method invocation server URI should be used.
+ if ((e instanceof RetryException || getRetry()) && preferredServerURI == null) {
try {
- processRequest(req, res, server);
+ processRequest(req, res, server, null);
} catch (RemoteFailoverException re) {
throw re;
} catch (RemoteException re) {
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBInvocationHandler.java Thu May 19 17:01:09 2011
@@ -140,6 +140,18 @@ public abstract class EJBInvocationHandl
return response;
}
+ protected EJBResponse request(EJBRequest req, EJBResponse res) throws Exception {
+ req.setClientIdentity(getClientIdentity());
+
+ req.setServerHash(server.buildHash());
+
+ Client.request(req, res, server);
+ if (null != res.getServer()) {
+ server.merge(res.getServer());
+ }
+ return res;
+ }
+
protected Object getClientIdentity() {
if (client != null) {
Object identity = client.getClientIdentity();
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBMetaDataImpl.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBMetaDataImpl.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBMetaDataImpl.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBMetaDataImpl.java Thu May 19 17:01:09 2011
@@ -16,15 +16,18 @@
*/
package org.apache.openejb.client;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
-import java.util.List;
+import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Properties;
+import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
import javax.ejb.EJBHome;
@@ -54,6 +57,8 @@ public class EJBMetaDataImpl implements
protected transient Class mainInterface;
+ protected final transient Set<String> asynchronousMethods = new HashSet<String>();
+
protected final transient Properties properties = new Properties();
protected transient Class keyClass;
@@ -69,9 +74,9 @@ public class EJBMetaDataImpl implements
}
- public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, String typeOfBean, InterfaceType interfaceType, List<Class> businessInterfaces) {
+ public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, String typeOfBean, InterfaceType interfaceType, List<Class> businessInterfaces, Set<String> asynchronousMethodSignatures) {
this.interfaceType = interfaceType;
-
+
if ("STATEFUL".equalsIgnoreCase(typeOfBean)){
this.type = STATEFUL;
} else if ("STATELESS".equalsIgnoreCase(typeOfBean)){
@@ -88,22 +93,25 @@ public class EJBMetaDataImpl implements
if (businessInterfaces != null){
this.businessClasses.addAll(businessInterfaces);
}
+ if (asynchronousMethodSignatures != null) {
+ this.asynchronousMethods.addAll(asynchronousMethodSignatures);
+ }
}
- public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, Class primaryKeyClass, String typeOfBean, InterfaceType interfaceType, List<Class> businessInterfaces) {
- this(homeInterface, remoteInterface, typeOfBean, interfaceType, businessInterfaces);
+ public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, Class primaryKeyClass, String typeOfBean, InterfaceType interfaceType, List<Class> businessInterfaces, Set<String> asynchronousMethodSignatures) {
+ this(homeInterface, remoteInterface, typeOfBean, interfaceType, businessInterfaces, asynchronousMethodSignatures);
if (type == CMP_ENTITY || type == BMP_ENTITY) {
this.keyClass = primaryKeyClass;
}
}
- public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, Class primaryKeyClass, String typeOfBean, String deploymentID, InterfaceType interfaceType, List<Class> businessInterfaces) {
- this(homeInterface, remoteInterface, primaryKeyClass, typeOfBean, interfaceType, businessInterfaces);
+ public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, Class primaryKeyClass, String typeOfBean, String deploymentID, InterfaceType interfaceType, List<Class> businessInterfaces, Set<String> asynchronousMethodSignatures) {
+ this(homeInterface, remoteInterface, primaryKeyClass, typeOfBean, interfaceType, businessInterfaces, asynchronousMethodSignatures);
this.deploymentID = deploymentID;
}
- public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, Class primaryKeyClass, String typeOfBean, String deploymentID, int deploymentCode, InterfaceType interfaceType, List<Class> businessInterfaces, Class mainInterface) {
- this(homeInterface, remoteInterface, primaryKeyClass, typeOfBean, deploymentID, interfaceType, businessInterfaces);
+ public EJBMetaDataImpl(Class homeInterface, Class remoteInterface, Class primaryKeyClass, String typeOfBean, String deploymentID, int deploymentCode, InterfaceType interfaceType, List<Class> businessInterfaces, Set<String> asynchronousMethodSignatures) {
+ this(homeInterface, remoteInterface, primaryKeyClass, typeOfBean, deploymentID, interfaceType, businessInterfaces, asynchronousMethodSignatures);
this.deploymentCode = deploymentCode;
}
@@ -143,6 +151,17 @@ public class EJBMetaDataImpl implements
return (type == STATEFUL || type == STATELESS || type == SINGLETON);
}
+ public boolean isAsynchronousMethod(Method method) {
+ if(asynchronousMethods.size() == 0) {
+ return false;
+ }
+ return asynchronousMethods.contains(generateMethodSignature(method));
+ }
+
+ public void addAsynchronousMethod(Method method) {
+ asynchronousMethods.add(generateMethodSignature(method));
+ }
+
protected void setEJBHomeProxy(EJBHomeProxy home) {
ejbHomeProxy = home;
}
@@ -194,8 +213,14 @@ public class EJBMetaDataImpl implements
out.writeObject(primaryKey);
}
out.writeObject(mainInterface);
+
out.writeByte(interfaceType.ordinal());
+ out.writeInt(asynchronousMethods.size());
+ for (String asynchronousMethod : asynchronousMethods) {
+ out.writeObject(asynchronousMethod);
+ }
+
if (properties.size() == 0) {
out.writeBoolean(false);
} else {
@@ -235,6 +260,9 @@ public class EJBMetaDataImpl implements
byte typeIndex = in.readByte();
interfaceType = InterfaceType.values()[typeIndex];
}
+ for (int i = in.readInt(); i > 0; i--) {
+ asynchronousMethods.add((String)in.readObject());
+ }
final boolean hasProperties = in.readBoolean();
if (hasProperties) {
@@ -280,4 +308,12 @@ public class EJBMetaDataImpl implements
}
}
}
+
+ private String generateMethodSignature(Method method) {
+ StringBuilder buffer = new StringBuilder(method.getName());
+ for(Class<?> parameterType : method.getParameterTypes()) {
+ buffer.append(parameterType.getName());
+ }
+ return buffer.toString();
+ }
}
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBObjectHandler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBObjectHandler.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBObjectHandler.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBObjectHandler.java Thu May 19 17:01:09 2011
@@ -16,14 +16,28 @@
*/
package org.apache.openejb.client;
-import org.apache.openejb.client.proxy.ProxyManager;
-
-import javax.ejb.EJBException;
-import javax.ejb.EJBObject;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.ejb.EJBException;
+import javax.ejb.EJBObject;
+
+import org.apache.openejb.client.proxy.ProxyManager;
public abstract class EJBObjectHandler extends EJBInvocationHandler {
@@ -35,11 +49,16 @@ public abstract class EJBObjectHandler e
protected static final Method GETHANDLER = getMethod(EJBObjectProxy.class, "getEJBObjectHandler", null);
+ protected static final Method CANCEL = getMethod(Future.class, "cancel", boolean.class);
+
+ //TODO figure out how to configure and manage the thread pool on the client side
+ protected static final BlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>();
+ protected static final ExecutorService executorService = new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, blockingQueue);
/*
* The registryId is a logical identifier that is used as a key when placing EntityEJBObjectHandler into
* the BaseEjbProxyHanlder's liveHandleRegistry. EntityEJBObjectHandlers that represent the same
* bean identity (keyed by the registry id) will be stored together so that they can be removed together
- * when the EJBInvocationHandler.invalidateAllHandlers is invoked. The EntityEJBObjectHandler uses a
+ * when the EJBInvocationHandler.invalidateAllHandlers is invoked. The EntityEJBObjectHandler uses a
* compound key composed of the entity bean's primary key, deployment id, and
* container id. This uniquely identifies the bean identity that is proxied by this handler allowing it
* to be removed with other handlers bound to the same registry id.
@@ -209,10 +228,39 @@ public abstract class EJBObjectHandler e
protected Object businessMethod(Method method, Object[] args, Object proxy) throws Throwable {
+ if (ejb.isAsynchronousMethod(method)) {
+ try {
+ String requestId = UUID.randomUUID().toString();
+ EJBResponse response = new EJBResponse();
+ AsynchronousCall asynchronousCall = new AsynchronousCall(method, args, proxy, requestId, response);
+ return new FutureAdapter(executorService.submit(asynchronousCall), response, requestId);
+ } catch (RejectedExecutionException e) {
+ throw new EJBException("failed to allocate internal resource to execute the target task", e);
+ }
+ } else {
+ return _businessMethod(method, args, proxy, null);
+ }
+ }
+
+ private Object _businessMethod(Method method, Object[] args, Object proxy, String requestId) throws Throwable {
EJBRequest req = new EJBRequest(RequestMethodConstants.EJB_OBJECT_BUSINESS_METHOD, ejb, method, args, primaryKey);
+ //Currently, we only set the requestId while the asynchronous invocation is called
+ req.getBody().setRequestId(requestId);
EJBResponse res = request(req);
+ return _handleBusinessMethodResponse(res);
+ }
+ private Object _businessMethod(Method method, Object[] args, Object proxy, String requestId, EJBResponse response) throws Throwable {
+ EJBRequest req = new EJBRequest(RequestMethodConstants.EJB_OBJECT_BUSINESS_METHOD, ejb, method, args, primaryKey);
+
+ //Currently, we only set the request while the asynchronous invocation is called
+ req.getBody().setRequestId(requestId);
+ EJBResponse res = request(req, response);
+ return _handleBusinessMethodResponse(res);
+ }
+
+ private Object _handleBusinessMethodResponse(EJBResponse res) throws Throwable{
switch (res.getResponseCode()) {
case ResponseCodes.EJB_ERROR:
throw new SystemError((ThrowableArtifact) res.getResult());
@@ -227,4 +275,133 @@ public abstract class EJBObjectHandler e
}
}
+ private class AsynchronousCall implements Callable {
+
+ private Method method;
+
+ private Object[] args;
+
+ private Object proxy;
+
+ private String requestId;
+
+ private EJBResponse response;
+
+ public AsynchronousCall(Method method, Object[] args, Object proxy, String requestId, EJBResponse response) {
+ this.method = method;
+ this.args = args;
+ this.proxy = proxy;
+ this.requestId = requestId;
+ this.response = response;
+ }
+
+ @Override
+ public Object call() throws Exception {
+ try {
+ return _businessMethod(method, args, proxy, requestId, response);
+ } catch (Exception e) {
+ throw e;
+ } catch (Throwable error) {
+ throw new SystemException(error);
+ }
+ }
+ }
+
+ private class FutureAdapter<T> implements Future<T> {
+
+ private Future<T> target;
+
+ private String requestId;
+
+ private EJBResponse response;
+
+ private volatile boolean canceled;
+
+ private AtomicBoolean lastMayInterruptIfRunningValue = new AtomicBoolean(false);
+
+ public FutureAdapter(Future<T> target, EJBResponse response, String requestId) {
+ this.target = target;
+ this.requestId = requestId;
+ this.response = response;
+ }
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ /* In EJB 3.1 spec 3.4.8.1.1
+ * a. If a client calls cancel on its Future object, the container will attempt to cancel
+ * the associated asynchronous invocation only if that invocation has not already been dispatched.
+ * There is no guarantee that an asynchronous invocation can be cancelled, regardless of how quickly
+ * cancel is called after the client receives its Future object.
+ * If the asynchronous invocation can not be cancelled, the method must return false.
+ * If the asynchronous invocation is successfully cancelled, the method must return true.
+ *
+ * b. The meaning of parameter mayInterruptIfRunning is changed.
+ *
+ * So, we should never call cancel(true), or the underlying Future object will try to interrupt the target thread.
+ */
+
+ /**
+ * We use our own flag canceled to identify whether the task is canceled successfully.
+ */
+ if (canceled) {
+ return true;
+ }
+ if (blockingQueue.remove(target)) {
+ // We successfully remove the task from the queue
+ canceled = true;
+ return true;
+ } else {
+ // Did not find the task in the queue, the status might be ran/canceled or running
+ // Future.isDone() will return true when the task has been ran or canceled,
+ // Since we never call the Future.cancel method, the isDone method will only return true when the task has ran
+ if (!target.isDone()) {
+ //The task is in the running state
+ if (lastMayInterruptIfRunningValue.getAndSet(mayInterruptIfRunning) == mayInterruptIfRunning) {
+ return false;
+ }
+ EJBRequest req = new EJBRequest(RequestMethodConstants.FUTURE_CANCEL, ejb, CANCEL, new Object[] { Boolean.valueOf(mayInterruptIfRunning) }, primaryKey);
+ req.getBody().setRequestId(requestId);
+ try {
+ EJBResponse res = request(req);
+ if(res.getResponseCode() != ResponseCodes.EJB_OK) {
+ //TODO how do we notify the user that we fail to configure the value ?
+ }
+ } catch (Exception e) {
+ //TODO how to handle
+ return false;
+ }
+ }
+ return false;
+ }
+ }
+
+ @Override
+ public T get() throws InterruptedException, ExecutionException {
+ if (canceled) {
+ throw new CancellationException();
+ }
+ return target.get();
+ }
+
+ @Override
+ public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ if (canceled) {
+ throw new CancellationException();
+ }
+ return target.get(timeout, unit);
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return canceled;
+ }
+
+ @Override
+ public boolean isDone() {
+ if (canceled) {
+ return false;
+ }
+ return target.isDone();
+ }
+ }
}
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBRequest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBRequest.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBRequest.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBRequest.java Thu May 19 17:01:09 2011
@@ -20,13 +20,14 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Method;
-
import java.rmi.Remote;
+import java.util.UUID;
+
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
-import javax.rmi.CORBA.Tie;
import javax.rmi.CORBA.Stub;
+import javax.rmi.CORBA.Tie;
import org.omg.CORBA.ORB;
@@ -117,12 +118,13 @@ public class EJBRequest implements Clust
private transient ORB orb;
private transient Method methodInstance;
private transient Class interfaceClass;
-// private transient Class methodClass;
private transient String methodName;
private transient Class[] methodParamTypes;
private transient Object[] methodParameters;
private transient Object primaryKey;
+ private transient String requestId;
+
public Body(EJBMetaDataImpl ejb) {
this.ejb = ejb;
}
@@ -190,15 +192,25 @@ public class EJBRequest implements Clust
this.primaryKey = primaryKey;
}
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
+ }
+
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
byte version = in.readByte(); // future use
+ requestId = null;
ClassNotFoundException result = null;
primaryKey = null;
// methodClass = null;
methodName = null;
methodInstance = null;
try {
+ requestId = (String)in.readObject();
primaryKey = in.readObject();
interfaceClass = (Class) in.readObject();
// methodClass = (Class) in.readObject();
@@ -228,6 +240,8 @@ public class EJBRequest implements Clust
// write out the version of the serialized data for future use
out.writeByte(1);
+ out.writeObject(requestId);
+
out.writeObject(primaryKey);
out.writeObject(interfaceClass);
@@ -470,49 +484,51 @@ public class EJBRequest implements Clust
}
public String toString() {
- StringBuffer s = null;
+ StringBuilder s = null;
switch (requestMethod) {
case RequestMethodConstants.EJB_HOME_GET_EJB_META_DATA:
- s = new StringBuffer("EJB_HOME.GET_EJB_META_DATA");
+ s = new StringBuilder("EJB_HOME.GET_EJB_META_DATA");
break;
case RequestMethodConstants.EJB_HOME_GET_HOME_HANDLE:
- s = new StringBuffer("EJB_HOME.GET_HOME_HANDLE");
+ s = new StringBuilder("EJB_HOME.GET_HOME_HANDLE");
break;
case RequestMethodConstants.EJB_HOME_REMOVE_BY_HANDLE:
- s = new StringBuffer("EJB_HOME.REMOVE_BY_HANDLE");
+ s = new StringBuilder("EJB_HOME.REMOVE_BY_HANDLE");
break;
case RequestMethodConstants.EJB_HOME_REMOVE_BY_PKEY:
- s = new StringBuffer("EJB_HOME.REMOVE_BY_PKEY");
+ s = new StringBuilder("EJB_HOME.REMOVE_BY_PKEY");
break;
case RequestMethodConstants.EJB_HOME_FIND:
- s = new StringBuffer("EJB_HOME.FIND");
+ s = new StringBuilder("EJB_HOME.FIND");
break;
case RequestMethodConstants.EJB_HOME_CREATE:
- s = new StringBuffer("EJB_HOME.CREATE");
+ s = new StringBuilder("EJB_HOME.CREATE");
break;
case RequestMethodConstants.EJB_HOME_METHOD:
- s = new StringBuffer("EJB_HOME.HOME_METHOD");
+ s = new StringBuilder("EJB_HOME.HOME_METHOD");
break;
case RequestMethodConstants.EJB_OBJECT_GET_EJB_HOME:
- s = new StringBuffer("EJB_OBJECT.GET_EJB_HOME");
+ s = new StringBuilder("EJB_OBJECT.GET_EJB_HOME");
break;
case RequestMethodConstants.EJB_OBJECT_GET_HANDLE:
- s = new StringBuffer("EJB_OBJECT.GET_HANDLE");
+ s = new StringBuilder("EJB_OBJECT.GET_HANDLE");
break;
case RequestMethodConstants.EJB_OBJECT_GET_PRIMARY_KEY:
- s = new StringBuffer("EJB_OBJECT.GET_PRIMARY_KEY");
+ s = new StringBuilder("EJB_OBJECT.GET_PRIMARY_KEY");
break;
case RequestMethodConstants.EJB_OBJECT_IS_IDENTICAL:
- s = new StringBuffer("EJB_OBJECT.IS_IDENTICAL");
+ s = new StringBuilder("EJB_OBJECT.IS_IDENTICAL");
break;
case RequestMethodConstants.EJB_OBJECT_REMOVE:
- s = new StringBuffer("EJB_OBJECT.REMOVE");
+ s = new StringBuilder("EJB_OBJECT.REMOVE");
break;
case RequestMethodConstants.EJB_OBJECT_BUSINESS_METHOD:
- s = new StringBuffer("EJB_OBJECT.BUSINESS_METHOD");
+ s = new StringBuilder("EJB_OBJECT.BUSINESS_METHOD");
break;
+ case RequestMethodConstants.FUTURE_CANCEL:
+ s = new StringBuilder("FUTURE.CANCEL");
default:
- s = new StringBuffer("EJB_UKNOWN."+requestMethod);
+ s = new StringBuilder("EJB_UKNOWN."+requestMethod);
}
s.append(':').append(deploymentId);
if (body != null) {
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/EJBResponse.java Thu May 19 17:01:09 2011
@@ -19,6 +19,7 @@ package org.apache.openejb.client;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.net.URI;
public class EJBResponse implements ClusterableResponse {
@@ -26,6 +27,8 @@ public class EJBResponse implements Clus
private transient Object result;
private transient ServerMetaData server;
+ private transient URI responseServerURI;
+
public EJBResponse() {
}
@@ -55,7 +58,7 @@ public class EJBResponse implements Clus
public ServerMetaData getServer() {
return server;
}
-
+
public String toString() {
StringBuffer s = null;
switch (responseCode) {
@@ -94,6 +97,14 @@ public class EJBResponse implements Clus
return s.toString();
}
+ public URI getResponseServerURI() {
+ return responseServerURI;
+ }
+
+ public void setResponseServerURI(URI responseServerURI) {
+ this.responseServerURI = responseServerURI;
+ }
+
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
byte version = in.readByte(); // future use
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/RequestMethodConstants.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/RequestMethodConstants.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/RequestMethodConstants.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/RequestMethodConstants.java Thu May 19 17:01:09 2011
@@ -50,5 +50,7 @@ public class RequestMethodConstants {
public static final int JNDI_LIST = 28;
public static final int JNDI_LIST_BINDINGS = 29;
+ public static final int FUTURE_CANCEL = 35;
+
}
Modified: openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Response.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Response.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Response.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/main/java/org/apache/openejb/client/Response.java Thu May 19 17:01:09 2011
@@ -26,5 +26,6 @@ public interface Response extends Extern
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
public void writeExternal(ObjectOutput out) throws IOException;
+
}
Modified: openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/EJBRequestTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/EJBRequestTest.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/EJBRequestTest.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/EJBRequestTest.java Thu May 19 17:01:09 2011
@@ -38,7 +38,7 @@ public class EJBRequestTest extends Test
protected void setUp() throws Exception {
- ejb = new EJBMetaDataImpl(FooHome.class, FooObject.class, Integer.class, "BMP_ENTITY", "FooBeanID", InterfaceType.BUSINESS_REMOTE, null);
+ ejb = new EJBMetaDataImpl(FooHome.class, FooObject.class, Integer.class, "BMP_ENTITY", "FooBeanID", InterfaceType.BUSINESS_REMOTE, null, null);
}
public void testEJBHomeCreate() throws Exception {
Modified: openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/LoginTestUtil.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/LoginTestUtil.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/LoginTestUtil.java (original)
+++ openejb/trunk/openejb3/server/openejb-client/src/test/java/org/apache/openejb/client/LoginTestUtil.java Thu May 19 17:01:09 2011
@@ -17,9 +17,10 @@
*/
package org.apache.openejb.client;
-import java.rmi.RemoteException;
+import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
+import java.rmi.RemoteException;
public class LoginTestUtil {
public static Request serverRequest;
@@ -36,7 +37,8 @@ public class LoginTestUtil {
}
Client.setClient(new Client() {
- protected Response processRequest(Request req, Response res, ServerMetaData server) throws RemoteException {
+ @Override
+ protected Response processRequest(Request req, Response res, ServerMetaData server, URI preferredServerURI) throws RemoteException {
serverRequest = req;
return serverResponse;
}
Modified: openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/ClientObjectFactory.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/ClientObjectFactory.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/ClientObjectFactory.java (original)
+++ openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/ClientObjectFactory.java Thu May 19 17:01:09 2011
@@ -146,7 +146,7 @@ class ClientObjectFactory implements org
idCode,
convert(info.getInterfaceType()),
info.getInterfaces(),
- info.getInterface());
+ beanContext.getAsynchronousMethodSignatures());
eMetaData.loadProperties(beanContext.getProperties());
Object primKey = info.getPrimaryKey();
@@ -190,17 +190,17 @@ class ClientObjectFactory implements org
return hanlder.createEJBHomeProxy();
}
- private EJBMetaDataImpl buildEjbMetaData(ProxyInfo info, BeanContext deployment, int idCode) {
- EJBMetaDataImpl eMetaData = new EJBMetaDataImpl(deployment.getHomeInterface(),
- deployment.getRemoteInterface(),
- deployment.getPrimaryKeyClass(),
- deployment.getComponentType().toString(),
- deployment.getDeploymentID().toString(),
+ private EJBMetaDataImpl buildEjbMetaData(ProxyInfo info, BeanContext beanContext, int idCode) {
+ EJBMetaDataImpl eMetaData = new EJBMetaDataImpl(beanContext.getHomeInterface(),
+ beanContext.getRemoteInterface(),
+ beanContext.getPrimaryKeyClass(),
+ beanContext.getComponentType().toString(),
+ beanContext.getDeploymentID().toString(),
idCode,
convert(info.getInterfaceType()),
info.getInterfaces(),
- info.getInterface());
- eMetaData.loadProperties(deployment.getProperties());
+ beanContext.getAsynchronousMethodSignatures());
+ eMetaData.loadProperties(beanContext.getProperties());
return eMetaData;
}
}
\ No newline at end of file
Modified: openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java (original)
+++ openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/EjbRequestHandler.java Thu May 19 17:01:09 2011
@@ -21,6 +21,10 @@ import java.io.ObjectOutputStream;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.openejb.BeanContext;
import org.apache.openejb.ProxyInfo;
@@ -32,6 +36,7 @@ import org.apache.openejb.client.EJBResp
import org.apache.openejb.client.RequestMethodConstants;
import org.apache.openejb.client.ResponseCodes;
import org.apache.openejb.client.ThrowableArtifact;
+import org.apache.openejb.core.ThreadContext;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.spi.SecurityService;
import org.apache.openejb.util.LogCategory;
@@ -45,9 +50,11 @@ class EjbRequestHandler {
private final ClusterableRequestHandler clusterableRequestHandler;
+ private Map<String, AtomicBoolean> asynchronousInvocationCancelMap = new ConcurrentHashMap<String, AtomicBoolean>();
+
EjbRequestHandler(EjbDaemon daemon) {
this.daemon = daemon;
-
+
clusterableRequestHandler = newClusterableRequestHandler();
}
@@ -73,7 +80,6 @@ class EjbRequestHandler {
CallContext call = null;
BeanContext di = null;
- RpcContainer c = null;
try {
di = this.daemon.getDeployment(req);
@@ -190,6 +196,10 @@ class EjbRequestHandler {
case RequestMethodConstants.EJB_HOME_REMOVE_BY_PKEY:
doEjbHome_REMOVE_BY_PKEY(req, res);
break;
+
+ case RequestMethodConstants.FUTURE_CANCEL:
+ doFUTURE_CANCEL_METHOD(req, res);
+ break;
}
} catch (org.apache.openejb.InvalidateReferenceException e) {
@@ -230,18 +240,47 @@ class EjbRequestHandler {
clusterableRequestHandler.updateServer(beanContext, req, res);
}
+ protected void doFUTURE_CANCEL_METHOD(EJBRequest req, EJBResponse res) throws Exception {
+ AtomicBoolean invocationCancelTag = asynchronousInvocationCancelMap.get(req.getBody().getRequestId());
+ if (invocationCancelTag == null) {
+ //TODO ?
+ } else {
+ invocationCancelTag.set((Boolean) req.getBody().getMethodParameters()[0]);
+ res.setResponse(ResponseCodes.EJB_OK, null);
+ }
+ }
+
protected void doEjbObject_BUSINESS_METHOD(EJBRequest req, EJBResponse res) throws Exception {
CallContext call = CallContext.getCallContext();
- RpcContainer c = (RpcContainer) call.getBeanContext().getContainer();
-
- Object result = c.invoke(req.getDeploymentId(),
- req.getInterfaceClass(), req.getMethodInstance(),
- req.getMethodParameters(),
- req.getPrimaryKey()
- );
-
- res.setResponse(ResponseCodes.EJB_OK, result);
+ BeanContext beanContext = (BeanContext)call.getBeanContext();
+ boolean asynchronous = beanContext.isAsynchronous(req.getMethodInstance());
+ try {
+ if (asynchronous) {
+ AtomicBoolean invocationCancelTag = new AtomicBoolean(false);
+ ThreadContext.initAsynchronousCancelled(invocationCancelTag);
+ asynchronousInvocationCancelMap.put(req.getBody().getRequestId(), invocationCancelTag);
+ }
+ RpcContainer c = (RpcContainer) call.getBeanContext().getContainer();
+
+ Object result = c.invoke(req.getDeploymentId(),
+ req.getInterfaceClass(), req.getMethodInstance(),
+ req.getMethodParameters(),
+ req.getPrimaryKey()
+ );
+
+ //Pass the internal value to the remote client, as AsyncResult is not serializable
+ if(result != null && asynchronous) {
+ result = ((Future)result).get();
+ }
+
+ res.setResponse(ResponseCodes.EJB_OK, result);
+ } finally {
+ if (asynchronous) {
+ ThreadContext.removeAsynchronousCancelled();
+ asynchronousInvocationCancelMap.remove(req.getBody().getRequestId());
+ }
+ }
}
protected void doEjbHome_METHOD(EJBRequest req, EJBResponse res) throws Exception {
Modified: openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/JndiRequestHandler.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/JndiRequestHandler.java?rev=1124995&r1=1124994&r2=1124995&view=diff
==============================================================================
--- openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/JndiRequestHandler.java (original)
+++ openejb/trunk/openejb3/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/JndiRequestHandler.java Thu May 19 17:01:09 2011
@@ -371,7 +371,7 @@ class JndiRequestHandler {
-1,
convert(proxyInfo.getInterfaceType()),
null,
- proxyInfo.getInterface());
+ beanContext.getAsynchronousMethodSignatures());
metaData.loadProperties(beanContext.getProperties());
log(metaData);
res.setResult(metaData);
@@ -393,7 +393,7 @@ class JndiRequestHandler {
-1,
convert(proxyInfo.getInterfaceType()),
proxyInfo.getInterfaces(),
- proxyInfo.getInterface());
+ beanContext.getAsynchronousMethodSignatures());
metaData.setPrimaryKey(proxyInfo.getPrimaryKey());
metaData.loadProperties(beanContext.getProperties());