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