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; 020import org.apache.camel.AsyncCallback; 021import org.apache.camel.AsyncProcessor; 022import org.apache.camel.Exchange; 023import org.apache.camel.spi.UnitOfWork; 024import org.slf4j.Logger; 025import org.slf4j.LoggerFactory; 026 027/** 028 * Helper methods for {@link AsyncProcessor} objects. 029 */ 030public final class AsyncProcessorHelper { 031 032 private static final Logger LOG = LoggerFactory.getLogger(AsyncProcessorHelper.class); 033 034 private AsyncProcessorHelper() { 035 // utility class 036 } 037 038 /** 039 * Calls the async version of the processor's process method. 040 * <p/> 041 * This implementation supports transacted {@link Exchange}s which ensure those are run in a synchronous fashion. 042 * See more details at {@link org.apache.camel.AsyncProcessor}. 043 * 044 * @param processor the processor 045 * @param exchange the exchange 046 * @param callback the callback 047 * @return <tt>true</tt> to continue execute synchronously, <tt>false</tt> to continue being executed asynchronously 048 * @deprecated should no longer be needed, instead invoke the process method on the {@link AsyncProcessor} directly, 049 * instead of using this method. 050 */ 051 @Deprecated 052 public static boolean process(final AsyncProcessor processor, final Exchange exchange, final AsyncCallback callback) { 053 boolean sync; 054 055 if (exchange.isTransacted()) { 056 // must be synchronized for transacted exchanges 057 LOG.trace("Transacted Exchange must be routed synchronously for exchangeId: {} -> {}", exchange.getExchangeId(), exchange); 058 try { 059 process(processor, exchange); 060 } catch (Throwable e) { 061 exchange.setException(e); 062 } 063 callback.done(true); 064 sync = true; 065 } else { 066 final UnitOfWork uow = exchange.getUnitOfWork(); 067 068 // allow unit of work to wrap callback in case it need to do some special work 069 // for example the MDCUnitOfWork 070 AsyncCallback async = callback; 071 if (uow != null) { 072 async = uow.beforeProcess(processor, exchange, callback); 073 } 074 075 // we support asynchronous routing so invoke it 076 sync = processor.process(exchange, async); 077 078 // execute any after processor work (in current thread, not in the callback) 079 if (uow != null) { 080 uow.afterProcess(processor, exchange, callback, sync); 081 } 082 } 083 084 if (LOG.isTraceEnabled()) { 085 LOG.trace("Exchange processed and is continued routed {} for exchangeId: {} -> {}", 086 new Object[]{sync ? "synchronously" : "asynchronously", exchange.getExchangeId(), exchange}); 087 } 088 return sync; 089 } 090 091 /** 092 * Calls the async version of the processor's process method and waits 093 * for it to complete before returning. This can be used by {@link AsyncProcessor} 094 * objects to implement their sync version of the process method. 095 * <p/> 096 * <b>Important:</b> This method is discouraged to be used, as its better to invoke the asynchronous 097 * {@link AsyncProcessor#process(org.apache.camel.Exchange, org.apache.camel.AsyncCallback)} method, whenever possible. 098 * 099 * @param processor the processor 100 * @param exchange the exchange 101 * @throws Exception can be thrown if waiting is interrupted 102 */ 103 public static void process(final AsyncProcessor processor, final Exchange exchange) throws Exception { 104 final CountDownLatch latch = new CountDownLatch(1); 105 boolean sync = processor.process(exchange, new AsyncCallback() { 106 public void done(boolean doneSync) { 107 if (!doneSync) { 108 LOG.trace("Asynchronous callback received for exchangeId: {}", exchange.getExchangeId()); 109 latch.countDown(); 110 } 111 } 112 113 @Override 114 public String toString() { 115 return "Done " + processor; 116 } 117 }); 118 if (!sync) { 119 LOG.trace("Waiting for asynchronous callback before continuing for exchangeId: {} -> {}", 120 exchange.getExchangeId(), exchange); 121 latch.await(); 122 LOG.trace("Asynchronous callback received, will continue routing exchangeId: {} -> {}", 123 exchange.getExchangeId(), exchange); 124 } 125 } 126 127}