001/** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.util; 018 019import java.util.concurrent.CountDownLatch; 020 021import org.apache.camel.AsyncCallback; 022import org.apache.camel.AsyncProcessor; 023import org.apache.camel.Exchange; 024import org.apache.camel.spi.AsyncProcessorAwaitManager; 025import org.apache.camel.spi.UnitOfWork; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029/** 030 * Helper methods for {@link AsyncProcessor} objects. 031 */ 032public final class AsyncProcessorHelper { 033 034 private static final Logger LOG = LoggerFactory.getLogger(AsyncProcessorHelper.class); 035 036 private AsyncProcessorHelper() { 037 // utility class 038 } 039 040 /** 041 * Calls the async version of the processor's process method. 042 * <p/> 043 * This implementation supports transacted {@link Exchange}s which ensure those are run in a synchronous fashion. 044 * See more details at {@link org.apache.camel.AsyncProcessor}. 045 * 046 * @param processor the processor 047 * @param exchange the exchange 048 * @param callback the callback 049 * @return <tt>true</tt> to continue execute synchronously, <tt>false</tt> to continue being executed asynchronously 050 * @deprecated should no longer be needed, instead invoke the process method on the {@link AsyncProcessor} directly, 051 * instead of using this method. 052 */ 053 @Deprecated 054 public static boolean process(final AsyncProcessor processor, final Exchange exchange, final AsyncCallback callback) { 055 boolean sync; 056 057 if (exchange.isTransacted()) { 058 // must be synchronized for transacted exchanges 059 LOG.trace("Transacted Exchange must be routed synchronously for exchangeId: {} -> {}", exchange.getExchangeId(), exchange); 060 try { 061 process(processor, exchange); 062 } catch (Throwable e) { 063 exchange.setException(e); 064 } 065 callback.done(true); 066 sync = true; 067 } else { 068 final UnitOfWork uow = exchange.getUnitOfWork(); 069 070 // allow unit of work to wrap callback in case it need to do some special work 071 // for example the MDCUnitOfWork 072 AsyncCallback async = callback; 073 if (uow != null) { 074 async = uow.beforeProcess(processor, exchange, callback); 075 } 076 077 // we support asynchronous routing so invoke it 078 sync = processor.process(exchange, async); 079 080 // execute any after processor work (in current thread, not in the callback) 081 if (uow != null) { 082 uow.afterProcess(processor, exchange, callback, sync); 083 } 084 } 085 086 if (LOG.isTraceEnabled()) { 087 LOG.trace("Exchange processed and is continued routed {} for exchangeId: {} -> {}", 088 new Object[]{sync ? "synchronously" : "asynchronously", exchange.getExchangeId(), exchange}); 089 } 090 return sync; 091 } 092 093 /** 094 * Calls the async version of the processor's process method and waits 095 * for it to complete before returning. This can be used by {@link AsyncProcessor} 096 * objects to implement their sync version of the process method. 097 * <p/> 098 * <b>Important:</b> This method is discouraged to be used, as its better to invoke the asynchronous 099 * {@link AsyncProcessor#process(org.apache.camel.Exchange, org.apache.camel.AsyncCallback)} method, whenever possible. 100 * 101 * @param processor the processor 102 * @param exchange the exchange 103 * @throws Exception can be thrown if waiting is interrupted 104 */ 105 public static void process(final AsyncProcessor processor, final Exchange exchange) throws Exception { 106 final AsyncProcessorAwaitManager awaitManager = exchange.getContext().getAsyncProcessorAwaitManager(); 107 108 final CountDownLatch latch = new CountDownLatch(1); 109 boolean sync = processor.process(exchange, new AsyncCallback() { 110 public void done(boolean doneSync) { 111 if (!doneSync) { 112 awaitManager.countDown(exchange, latch); 113 } 114 } 115 116 @Override 117 public String toString() { 118 return "Done " + processor; 119 } 120 }); 121 if (!sync) { 122 awaitManager.await(exchange, latch); 123 } 124 } 125 126}