Permalink
Browse files

EJBCLIENT-28 Added a testcase for checking the various states on the …

…Future object returned for an async invocation on a bean
  • Loading branch information...
1 parent 1131985 commit 94a43e8b9f12e3f2b6e1231cd0eb323d12c8da64 @jaikiran jaikiran committed with stuartwdouglas Apr 9, 2012
@@ -33,11 +33,9 @@
import org.jboss.marshalling.Marshalling;
import org.jboss.marshalling.MarshallingConfiguration;
import org.jboss.marshalling.Unmarshaller;
-import org.jboss.remoting3.Channel;
import java.io.DataInput;
import java.io.DataOutput;
-import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -65,6 +63,7 @@
private static final byte HEADER_MODULE_UNAVAILABLE = 0x09;
private static final byte HEADER_NO_SUCH_EJB_FAILURE = 0x0A;
private static final byte HEADER_INVOCATION_EXCEPTION = 0x06;
+ private static final byte HEADER_ASYNC_METHOD_NOTIFICATION = 0x0E;
public DummyProtocolHandler(final String marshallerType) {
this.marshallerFactory = Marshalling.getProvidedMarshallerFactory(marshallerType);
@@ -199,6 +198,13 @@ public void writeSessionId(final DataOutput output, final short invocationId, fi
marshaller.finish();
}
+ public void writeAsyncMethodNotification(final DataOutput output, final short invocationId) throws IOException {
+ // write the header
+ output.write(HEADER_ASYNC_METHOD_NOTIFICATION);
+ // write the invocation id
+ output.writeShort(invocationId);
+ }
+
private Map<String, Object> readAttachments(final ObjectInput input) throws IOException, ClassNotFoundException {
final int numAttachments = input.readByte();
if (numAttachments == 0) {
@@ -0,0 +1,41 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.ejb.client.test.async;
+
+import javax.ejb.AsyncResult;
+import java.util.concurrent.Future;
+
+/**
+ * @author Jaikiran Pai
+ */
+public class AsyncBean implements SlowEcho {
+ @Override
+ public Future<String> twoSecondEcho(String message) {
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return new AsyncResult<String>(message);
+ }
+}
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.ejb.client.test.async;
+
+import org.jboss.ejb.client.ContextSelector;
+import org.jboss.ejb.client.EJBClient;
+import org.jboss.ejb.client.EJBClientConfiguration;
+import org.jboss.ejb.client.EJBClientContext;
+import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
+import org.jboss.ejb.client.StatelessEJBLocator;
+import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;
+import org.jboss.ejb.client.test.common.DummyServer;
+import org.jboss.logging.Logger;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.concurrent.Future;
+
+/**
+ * @author Jaikiran Pai
+ */
+public class AsyncInvocationTestCase {
+
+ private static final Logger logger = Logger.getLogger(AsyncInvocationTestCase.class);
+
+ private static final String APP_NAME = "my-foo-app";
+ private static final String MODULE_NAME = "my-bar-module";
+ private static final String DISTINCT_NAME = "";
+
+ private DummyServer server;
+ private ContextSelector<EJBClientContext> previousSelector;
+
+ @Before
+ public void beforeTest() throws IOException {
+ server = new DummyServer("localhost", 6999, "async-invocation-test-server");
+ server.start();
+
+ final SlowEcho asyncBean = new AsyncBean();
+
+ // deploy on server
+ server.register(APP_NAME, MODULE_NAME, DISTINCT_NAME, AsyncBean.class.getSimpleName(), asyncBean);
+
+ // setup EJB client context
+ final String clientPropsName = "async-invocation-jboss-ejb-client.properties";
+ final InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(clientPropsName);
+ if (inputStream == null) {
+ throw new RuntimeException("Could not find EJB client configuration properties at " + clientPropsName + " using classloader " + this.getClass().getClassLoader());
+ }
+ final Properties clientProps = new Properties();
+ clientProps.load(inputStream);
+ final EJBClientConfiguration clientConfiguration = new PropertiesBasedEJBClientConfiguration(clientProps);
+ final ConfigBasedEJBClientContextSelector selector = new ConfigBasedEJBClientContextSelector(clientConfiguration);
+ this.previousSelector = EJBClientContext.setSelector(selector);
+ }
+
+ @After
+ public void afterTest() throws IOException {
+ try {
+ this.server.stop();
+ } catch (Exception e) {
+ logger.info("Could not stop server", e);
+ }
+ if (this.previousSelector != null) {
+ EJBClientContext.setSelector(previousSelector);
+ }
+ }
+
+ /**
+ * Tests that the invocation on async methods of a bean return the correct states when the
+ * returned {@link Future} is used on the client side
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testAsyncInvocation() throws Exception {
+ // create a proxy for invocation
+ final StatelessEJBLocator<SlowEcho> statelessEJBLocator = new StatelessEJBLocator<SlowEcho>(SlowEcho.class, APP_NAME, MODULE_NAME, AsyncBean.class.getSimpleName(), "");
+ final SlowEcho asyncBean = EJBClient.createProxy(statelessEJBLocator);
+ Assert.assertNotNull("Received a null proxy", asyncBean);
+
+ // invoke
+ final String message = "Hola!";
+ final Future<String> futureResult = asyncBean.twoSecondEcho(message);
+ Assert.assertFalse("Unexpected return for isDone()", futureResult.isDone());
+ Assert.assertFalse("Unexpected return for isCancelled()", futureResult.isCancelled());
+ // cancel the invocation
+ final boolean wasCancelled = futureResult.cancel(true);
+ // subsequent invocations to isDone() will *always* return true after a call to cancel()
+ Assert.assertTrue("Unexpected return for isDone() after a call to cancel", futureResult.isDone());
+ // subsequent invocations to isCancelled() will return true *if* cancel() returned true
+ if (wasCancelled) {
+ Assert.assertTrue("Unexpected return for isCancelled() after a call to cancel() returned true", futureResult.isCancelled());
+ }
+
+ }
+}
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2012, Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.ejb.client.test.async;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Jaikiran Pai
+ */
+public interface SlowEcho {
+
+ Future<String> twoSecondEcho(String message);
+}
@@ -62,6 +62,7 @@
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.Future;
/**
* @author <a href="mailto:cdewolf@redhat.com">Carlo de Wolf</a>
@@ -188,7 +189,7 @@ public void handleMessage(Channel channel, MessageInputStream messageInputStream
final MethodInvocationRequest methodInvocationRequest = this.dummyProtocolHandler.readMethodInvocationRequest(inputStream, this.getClass().getClassLoader());
Object methodInvocationResult = null;
try {
- methodInvocationResult = DummyServer.this.handleMethodInvocationRequest(methodInvocationRequest);
+ methodInvocationResult = DummyServer.this.handleMethodInvocationRequest(channel, methodInvocationRequest, dummyProtocolHandler);
} catch (NoSuchEJBException nsee) {
final DataOutputStream outputStream = new DataOutputStream(channel.writeMessage());
try {
@@ -395,7 +396,7 @@ private void writeModuleReport(final DataOutput output, final EJBModuleIdentifie
}
}
- private Object handleMethodInvocationRequest(final MethodInvocationRequest methodInvocationRequest) throws InvocationTargetException, IllegalAccessException {
+ private Object handleMethodInvocationRequest(final Channel channel, final MethodInvocationRequest methodInvocationRequest, final DummyProtocolHandler dummyProtocolHandler) throws InvocationTargetException, IllegalAccessException, IOException {
final EJBModuleIdentifier ejbModuleIdentifier = new EJBModuleIdentifier(methodInvocationRequest.getAppName(), methodInvocationRequest.getModuleName(), methodInvocationRequest.getDistinctName());
final Map<String, Object> ejbs = this.registeredEJBs.get(ejbModuleIdentifier);
final Object beanInstance = ejbs.get(methodInvocationRequest.getBeanName());
@@ -408,6 +409,17 @@ private Object handleMethodInvocationRequest(final MethodInvocationRequest metho
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
+ // check if this is an async method
+ if (this.isAsyncMethod(method)) {
+ final DataOutputStream output = new DataOutputStream(channel.writeMessage());
+ try {
+ // send a notification to the client that this is an async method
+ dummyProtocolHandler.writeAsyncMethodNotification(output, methodInvocationRequest.getInvocationId());
+ } finally {
+ output.close();
+ }
+ }
+ // invoke on the method
return method.invoke(beanInstance, methodInvocationRequest.getParams());
}
@@ -423,6 +435,11 @@ private Method getRequiredMethod(final Class<?> klass, final String methodName,
return klass.getMethod(methodName, types);
}
+ private boolean isAsyncMethod(final Method method) {
+ // just check for return type and assume it to be async if it returns Future
+ return method.getReturnType().equals(Future.class);
+ }
+
class VersionReceiver implements Channel.Receiver {
@Override
public void handleError(Channel channel, IOException error) {
@@ -0,0 +1,30 @@
+#
+# JBoss, Home of Professional Open Source.
+# Copyright 2012, Red Hat, Inc., and individual contributors
+# as indicated by the @author tags. See the copyright.txt file in the
+# distribution for a full listing of individual contributors.
+#
+# This is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this software; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+#
+
+remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
+
+remote.connections=one
+
+remote.connection.one.host=localhost
+remote.connection.one.port=6999
+remote.connection.one.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
+

0 comments on commit 94a43e8

Please sign in to comment.