/* * JBoss, Home of Professional Open Source * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual * contributors by the @authors tag. See the copyright.txt in the * distribution for a full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.as.quickstarts.ejb.asynchronous.client; import java.util.Collection; import java.util.Date; import java.util.Hashtable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import org.jboss.as.quickstarts.ejb.asynchronous.AsynchronousAccess; import org.jboss.as.quickstarts.ejb.asynchronous.ParallelAccess; /** * A client to call the SingletonService via EJB remoting to demonstrate the behaviour of asynchronous invocations. * * @author <a href="mailto:wfink@redhat.com">Wolf-Dieter Fink</a> */ public class AsynchronousClient { private static final Logger LOGGER = Logger.getLogger(AsynchronousClient.class.getName()); /** * Proxy of the SLSB with asynchronous methods */ private final AsynchronousAccess accessBean; /** * Proxy of the SLSB that uses asynchronous bean calls inside to parallelize internal actions. */ private final ParallelAccess parallelBean; /** * Constructor to prepare the client-context.<br/> * There must be a jboss-ejb-client.properties file in the classpath to specify the server connection(s). * * @throws NamingException */ private AsynchronousClient() throws NamingException { final Hashtable<String, String> jndiProperties = new Hashtable<>(); jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming"); final Context context = new InitialContext(jndiProperties); String lookupName = "ejb:/ejb-asynchronous-ejb/AsynchronousAccessBean!" + AsynchronousAccess.class.getName(); LOGGER.info("Lookup Bean >" + lookupName); accessBean = (AsynchronousAccess) context.lookup(lookupName); lookupName = "ejb:/ejb-asynchronous-ejb/ParallelAccessBean!" + ParallelAccess.class.getName(); LOGGER.info("Lookup Bean >" + lookupName); parallelBean = (ParallelAccess) context.lookup(lookupName); } /** * Demonstrate a fire-and-forget call to an asynchronous bean. * * @throws InterruptedException */ private void fireAndForget() throws InterruptedException { long sleepMillis = 15000; accessBean.fireAndForget(sleepMillis); LOGGER.info(String.format("The server log should contain a message at (about) %s, indicating that the call to the asynchronous bean completed.", new Date(new Date().getTime() + sleepMillis))); } /** * Demonstrate how to call an asynchronous EJB, and then perform another task whilst waiting for the result. * If the result is not present after the timeout of get(<timeout>) the result will be ignored. * * @throws TimeoutException Will be thrown if you change the timing */ private void getResultAsync() throws InterruptedException, ExecutionException, TimeoutException { Future<String> myResult = accessBean.longerRunning(200); // Start a call with a short duration // simulate something // wait below 200ms will force a timeout during get Thread.sleep(400); // If you handle the TimeoutException you are able to ignore the result // WARNING: there might be an ERROR at server side that the result is not delivered LOGGER.info("Got the async result as expected => " + myResult.get(1, TimeUnit.MILLISECONDS)); } /** * Demonstrate how to call an asynchronous EJB and continue local work meanwhile. After finishing local work * wait for the result of the server call.<br/> * Remember that the call of Future.get() will have a remote roundtrip to the server. */ private void waitForAsyncResult() throws InterruptedException, ExecutionException, TimeoutException { Future<String> myResult = accessBean.longerRunning(1500); // Start a call with a short duration // you might do something here // get() without a timeout will wait until the remote result is present. LOGGER.info("Got the async result as expected after wait => " + myResult.get()); } /** * Invoke a remote synchronous EJB method. The remote method uses asynchronous calls internally, to parallelize it's workload. */ private void callAnEJBwithAsyncAccess() { Collection<String> results = parallelBean.invokeAsyncParallel(); LOGGER.info("Results of the parallel (server) processing : " + results); } /** * Demonstrate how a EJB can call different annotated asynchronous methods within the same application. */ private void waitForAnotherAsyncResult2() throws InterruptedException, ExecutionException, TimeoutException { parallelBean.callInterfaceAnnotatedMethod(); } /** * Demonstrate how to handle an Exception from an asynchronous call. */ private void callAsyncWithFailure() throws InterruptedException { Future<String> x; try { x = accessBean.failure(); // this method will return successfully, because the invocation will be successful! } catch (IllegalAccessException e) { throw new RuntimeException("Unexpected failure during start asynchronous execution!", e); } try { x.get(); // this will not return successfully } catch (ExecutionException e) { // the IllegalAccessException is thrown by the bean method if (e.getCause() instanceof IllegalAccessException) { // This is the expected behavior LOGGER.info("Catch the expected Exception of the asynchronous execution!"); } else if (e.getCause().getCause() instanceof IllegalAccessException) { LOGGER.info("Catch the covered Exception of the asynchronous execution, you may be using an older release of JBoss EAP!"); } else { throw new RuntimeException("Unexpected ExecutionException during asynchronous call!", e); } } } /** * Call all the different asynchronous methods. * * @param args no arguments needed */ public static void main(String[] args) throws Exception { AsynchronousClient client = new AsynchronousClient(); client.fireAndForget(); client.getResultAsync(); client.waitForAsyncResult(); client.callAsyncWithFailure(); client.callAnEJBwithAsyncAccess(); client.waitForAnotherAsyncResult2(); } }