/** * JBoss, Home of Professional Open Source * Copyright 2011, 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.seam.cron.spi.asynchronous.support; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import org.jboss.seam.cron.spi.asynchronous.Invoker; /** * <p> * Creates a #{@link Callable} whose #{@literal call} method will block until * the #{@literal executeInvocationContext()} method is called. This comes in * handy when returning Futures (eg: #{@literal new FutureTask( * new FutureInvokerSupport(invoker))}). * </p><p> * In the simplest case #{@literal executeInvocationContext()} could be called * in the same thread prior to calling #{@literal call()}. This is useful when * your method of executing in the background is also #{@link Runnable} or * #{@link Callable} and can thus be used to return a #{@link RunnableFuture}. * </p><p> * In more complex cases #{@literal executeInvocationContext()} could be called * by a separate thread at any time before or after the current thread calls * #{@literal call()}. This is useful when your method of executing in the background is * fairly arbitrary (eg a Quartz Job scheduled for the near future), and you need * to be able to return a #{@literal new FutureTask(callable)} immediately * but trigger the processing on that callable some arbitrary way (ie: inside the * Quartz Job implementation). * </p> * <p> * See the Seam Cron Asynchronous Provider projects for the Threads and Quartz providers * to see this in action (providers/scheduling/quartz and providers/asynchronous/threads). * </p> * * @author peteroyle */ public class FutureInvokerSupport implements Callable { private Invoker executor; private final BlockingQueue queue = new ArrayBlockingQueue(1); // can't add null to a BlockingQueue, so we might have to add a marker instead private static final Boolean RESULT_AS_NULL = true; public FutureInvokerSupport(final Invoker executor) { this.executor = executor; } public void executeInvocationContext() throws Exception { Object result = executor.executeInvocationContext(); if (result == null) { result = RESULT_AS_NULL; } queue.put(result); } public Object call() throws Exception { Object result = queue.take(); if (result == RESULT_AS_NULL) { result = null; } return result; } }