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.spi; 018 019import java.util.function.Predicate; 020 021import org.apache.camel.AsyncCallback; 022import org.apache.camel.Exchange; 023import org.apache.camel.Message; 024import org.apache.camel.Processor; 025import org.apache.camel.Route; 026import org.apache.camel.Service; 027 028/** 029 * An object representing the unit of work processing an {@link Exchange} 030 * which allows the use of {@link Synchronization} hooks. This object might map one-to-one with 031 * a transaction in JPA or Spring; or might not. 032 */ 033public interface UnitOfWork extends Service { 034 035 String MDC_BREADCRUMB_ID = "camel.breadcrumbId"; 036 String MDC_EXCHANGE_ID = "camel.exchangeId"; 037 String MDC_MESSAGE_ID = "camel.messageId"; 038 String MDC_CORRELATION_ID = "camel.correlationId"; 039 String MDC_ROUTE_ID = "camel.routeId"; 040 String MDC_STEP_ID = "camel.stepId"; 041 String MDC_CAMEL_CONTEXT_ID = "camel.contextId"; 042 String MDC_TRANSACTION_KEY = "camel.transactionKey"; 043 044 /** 045 * Adds a synchronization hook 046 * 047 * @param synchronization the hook 048 */ 049 void addSynchronization(Synchronization synchronization); 050 051 /** 052 * Removes a synchronization hook 053 * 054 * @param synchronization the hook 055 */ 056 void removeSynchronization(Synchronization synchronization); 057 058 /** 059 * Checks if the passed synchronization hook is already part of this unit of work. 060 * 061 * @param synchronization the hook 062 * @return <tt>true</tt>, if the passed synchronization is part of this unit of work, else <tt>false</tt> 063 */ 064 boolean containsSynchronization(Synchronization synchronization); 065 066 /** 067 * Handover all the registered synchronizations to the target {@link org.apache.camel.Exchange}. 068 * <p/> 069 * This is used when a route turns into asynchronous and the {@link org.apache.camel.Exchange} that 070 * is continued and routed in the async thread should do the on completion callbacks instead of the 071 * original synchronous thread. 072 * 073 * @param target the target exchange 074 */ 075 void handoverSynchronization(Exchange target); 076 077 /** 078 * Handover all the registered synchronizations to the target {@link org.apache.camel.Exchange}. 079 * <p/> 080 * This is used when a route turns into asynchronous and the {@link org.apache.camel.Exchange} that 081 * is continued and routed in the async thread should do the on completion callbacks instead of the 082 * original synchronous thread. 083 * 084 * @param target the target exchange 085 * @param filter optional filter to only handover if filter returns <tt>true</tt> 086 */ 087 void handoverSynchronization(Exchange target, Predicate<Synchronization> filter); 088 089 /** 090 * Invoked when this unit of work has been completed, whether it has failed or completed 091 * 092 * @param exchange the current exchange 093 */ 094 void done(Exchange exchange); 095 096 /** 097 * Invoked when this unit of work is about to be routed by the given route. 098 * 099 * @param exchange the current exchange 100 * @param route the route 101 */ 102 void beforeRoute(Exchange exchange, Route route); 103 104 /** 105 * Invoked when this unit of work is done being routed by the given route. 106 * 107 * @param exchange the current exchange 108 * @param route the route 109 */ 110 void afterRoute(Exchange exchange, Route route); 111 112 /** 113 * Returns the unique ID of this unit of work, lazily creating one if it does not yet have one 114 * 115 * @return the unique ID 116 */ 117 String getId(); 118 119 /** 120 * Gets the original IN {@link Message} this Unit of Work was started with. 121 * <p/> 122 * The original message is only returned if the option {@link org.apache.camel.RuntimeConfiguration#isAllowUseOriginalMessage()} 123 * is enabled. If its disabled an <tt>IllegalStateException</tt> is thrown. 124 * 125 * @return the original IN {@link Message}, or <tt>null</tt> if using original message is disabled. 126 */ 127 Message getOriginalInMessage(); 128 129 /** 130 * Are we transacted? 131 * 132 * @return <tt>true</tt> if transacted, <tt>false</tt> otherwise 133 */ 134 boolean isTransacted(); 135 136 /** 137 * Are we already transacted by the given transaction key? 138 * 139 * @param key the transaction key 140 * @return <tt>true</tt> if already, <tt>false</tt> otherwise 141 */ 142 boolean isTransactedBy(Object key); 143 144 /** 145 * Mark this UnitOfWork as being transacted by the given transaction key. 146 * <p/> 147 * When the transaction is completed then invoke the {@link #endTransactedBy(Object)} method using the same key. 148 * 149 * @param key the transaction key 150 */ 151 void beginTransactedBy(Object key); 152 153 /** 154 * Mark this UnitOfWork as not transacted anymore by the given transaction definition. 155 * 156 * @param key the transaction key 157 */ 158 void endTransactedBy(Object key); 159 160 /** 161 * Gets the {@link RouteContext} that this {@link UnitOfWork} currently is being routed through. 162 * <p/> 163 * Notice that an {@link Exchange} can be routed through multiple routes and thus the 164 * {@link org.apache.camel.spi.RouteContext} can change over time. 165 * 166 * @return the route context 167 * @see #pushRouteContext(RouteContext) 168 * @see #popRouteContext() 169 */ 170 RouteContext getRouteContext(); 171 172 /** 173 * Pushes the {@link RouteContext} that this {@link UnitOfWork} currently is being routed through. 174 * <p/> 175 * Notice that an {@link Exchange} can be routed through multiple routes and thus the 176 * {@link org.apache.camel.spi.RouteContext} can change over time. 177 * 178 * @param routeContext the route context 179 */ 180 void pushRouteContext(RouteContext routeContext); 181 182 /** 183 * When finished being routed under the current {@link org.apache.camel.spi.RouteContext} 184 * it should be removed. 185 * 186 * @return the route context or <tt>null</tt> if none existed 187 */ 188 RouteContext popRouteContext(); 189 190 /** 191 * Strategy for optional work to be execute before processing 192 * <p/> 193 * For example the {@link org.apache.camel.impl.MDCUnitOfWork} leverages this 194 * to ensure MDC is handled correctly during routing exchanges using the 195 * asynchronous routing engine. 196 * 197 * @param processor the processor to be executed 198 * @param exchange the current exchange 199 * @param callback the callback 200 * @return the callback to be used (can return a wrapped callback) 201 */ 202 AsyncCallback beforeProcess(Processor processor, Exchange exchange, AsyncCallback callback); 203 204 /** 205 * Strategy for optional work to be executed after the processing 206 * 207 * @param processor the processor executed 208 * @param exchange the current exchange 209 * @param callback the callback used 210 * @param doneSync whether the process was done synchronously or asynchronously 211 */ 212 void afterProcess(Processor processor, Exchange exchange, AsyncCallback callback, boolean doneSync); 213 214 /** 215 * Create a child unit of work, which is associated to this unit of work as its parent. 216 * <p/> 217 * This is often used when EIPs need to support {@link SubUnitOfWork}s. For example a splitter, 218 * where the sub messages of the splitter all participate in the same sub unit of work. 219 * That sub unit of work then decides whether the Splitter (in general) is failed or a 220 * processed successfully. 221 * 222 * @param childExchange the child exchange 223 * @return the created child unit of work 224 * @see SubUnitOfWork 225 * @see SubUnitOfWorkCallback 226 */ 227 UnitOfWork createChildUnitOfWork(Exchange childExchange); 228 229 /** 230 * Sets the parent unit of work. 231 * 232 * @param parentUnitOfWork the parent 233 */ 234 void setParentUnitOfWork(UnitOfWork parentUnitOfWork); 235 236 /** 237 * Gets the {@link SubUnitOfWorkCallback} if this unit of work participates in a sub unit of work. 238 * 239 * @return the callback, or <tt>null</tt> if this unit of work is not part of a sub unit of work. 240 * @see #beginSubUnitOfWork(org.apache.camel.Exchange) 241 */ 242 SubUnitOfWorkCallback getSubUnitOfWorkCallback(); 243 244 /** 245 * Begins a {@link SubUnitOfWork}, where sub (child) unit of works participate in a parent unit of work. 246 * The {@link SubUnitOfWork} will callback to the parent unit of work using {@link SubUnitOfWorkCallback}s. 247 * 248 * @param exchange the exchange 249 */ 250 void beginSubUnitOfWork(Exchange exchange); 251 252 /** 253 * Ends a {@link SubUnitOfWork}. 254 * <p/> 255 * The {@link #beginSubUnitOfWork(org.apache.camel.Exchange)} must have been invoked 256 * prior to this operation. 257 * 258 * @param exchange the exchange 259 */ 260 void endSubUnitOfWork(Exchange exchange); 261 262}