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