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;
018
019import java.util.concurrent.Future;
020import java.util.function.Supplier;
021
022/**
023 * Template for working with Camel and sending {@link Message} instances in an
024 * {@link Exchange} to an {@link Endpoint} using a <i>fluent</i> build style.
025 * <br/>
026 * <p/><b>Important:</b> Read the javadoc of each method carefully to ensure the behavior of the method is understood.
027 * Some methods is for <tt>InOnly</tt>, others for <tt>InOut</tt> MEP. And some methods throws
028 * {@link org.apache.camel.CamelExecutionException} while others stores any thrown exception on the returned
029 * {@link Exchange}.
030 * <br/>
031 * <p/>The {@link FluentProducerTemplate} is <b>thread safe</b>.
032 * <br/>
033 * <p/>All the methods which sends a message may throw {@link FailedToCreateProducerException} in
034 * case the {@link Producer} could not be created. Or a {@link NoSuchEndpointException} if the endpoint could
035 * not be resolved. There may be other related exceptions being thrown which occurs <i>before</i> the {@link Producer}
036 * has started sending the message.
037 * <br/>
038 * <p/>All the send or request methods will return the content according to this strategy:
039 * <ul>
040 *   <li>throws {@link org.apache.camel.CamelExecutionException} if processing failed <i>during</i> routing
041 *       with the caused exception wrapped</li>
042 *   <li>The <tt>fault.body</tt> if there is a fault message set and its not <tt>null</tt></li>
043 *   <li>Either <tt>IN</tt> or <tt>OUT</tt> body according to the message exchange pattern. If the pattern is
044 *   Out capable then the <tt>OUT</tt> body is returned, otherwise <tt>IN</tt>.
045 * </ul>
046 * <br/>
047 * <p/>Before using the template it must be started.
048 * And when you are done using the template, make sure to {@link #stop()} the template.
049 * <br/>
050 * <p/><b>Important note on usage:</b> See this
051 * <a href="http://camel.apache.org/why-does-camel-use-too-many-threads-with-producertemplate.html">FAQ entry</a>
052 * before using.
053 *
054 * @see ProducerTemplate
055 * @see ConsumerTemplate
056 */
057public interface FluentProducerTemplate extends Service {
058
059    /**
060     * Get the {@link CamelContext}
061     *
062     * @return camelContext the Camel context
063     */
064    CamelContext getCamelContext();
065
066    // Configuration methods
067    // -----------------------------------------------------------------------
068
069    /**
070     * Gets the maximum cache size used in the backing cache pools.
071     *
072     * @return the maximum cache size
073     */
074    int getMaximumCacheSize();
075
076    /**
077     * Sets a custom maximum cache size to use in the backing cache pools.
078     *
079     * @param maximumCacheSize the custom maximum cache size
080     */
081    void setMaximumCacheSize(int maximumCacheSize);
082
083    /**
084     * Gets an approximated size of the current cached resources in the backing cache pools.
085     *
086     * @return the size of current cached resources
087     */
088    int getCurrentCacheSize();
089
090    /**
091     * Get the default endpoint to use if none is specified
092     *
093     * @return the default endpoint instance
094     */
095    Endpoint getDefaultEndpoint();
096
097    /**
098     * Sets the default endpoint to use if none is specified
099     *
100     * @param defaultEndpoint the default endpoint instance
101     */
102    void setDefaultEndpoint(Endpoint defaultEndpoint);
103
104    /**
105     * Sets the default endpoint uri to use if none is specified
106     *
107     *  @param endpointUri the default endpoint uri
108     */
109    void setDefaultEndpointUri(String endpointUri);
110
111    /**
112     * Sets whether the {@link org.apache.camel.spi.EventNotifier} should be
113     * used by this {@link ProducerTemplate} to send events about the {@link Exchange}
114     * being sent.
115     * <p/>
116     * By default this is enabled.
117     *
118     * @param enabled <tt>true</tt> to enable, <tt>false</tt> to disable.
119     */
120    void setEventNotifierEnabled(boolean enabled);
121
122    /**
123     * Whether the {@link org.apache.camel.spi.EventNotifier} should be
124     * used by this {@link ProducerTemplate} to send events about the {@link Exchange}
125     * being sent.
126     *
127     * @return <tt>true</tt> if enabled, <tt>false</tt> otherwise
128     */
129    boolean isEventNotifierEnabled();
130
131    /**
132     * Cleanup the cache (purging stale entries)
133     */
134    void cleanUp();
135
136    // Fluent methods
137    // -----------------------------------------------------------------------
138
139    /**
140     * Remove the body and headers.
141     */
142    FluentProducerTemplate clearAll();
143
144    /**
145     * Set the header
146     *
147     * @param key the key of the header
148     * @param value the value of the header
149     */
150    FluentProducerTemplate withHeader(String key, Object value);
151
152    /**
153     * Remove the headers.
154     */
155    FluentProducerTemplate clearHeaders();
156
157    /**
158     * Set the message body
159     *
160     * @param body the body
161     */
162    FluentProducerTemplate withBody(Object body);
163
164    /**
165     * Set the message body after converting it to the given type
166     *
167     * @param body the body
168     * @param type the type which the body should be converted to
169     */
170    FluentProducerTemplate withBodyAs(Object body, Class<?> type);
171
172    /**
173     * Remove the body.
174     */
175    FluentProducerTemplate clearBody();
176
177    /**
178     * To customize the producer template for advanced usage like to set the
179     * executor service to use.
180     *
181     * <pre>
182     * {@code
183     * FluentProducerTemplate.on(context)
184     *     .withTemplateCustomizer(
185     *         template -> {
186     *             template.setExecutorService(myExecutor);
187     *             template.setMaximumCacheSize(10);
188     *         }
189     *      )
190     *     .withBody("the body")
191     *     .to("direct:start")
192     *     .request()}
193     * </pre>
194     *
195     * Note that it is invoked only once.
196     *
197     * @param templateCustomizer the customizer
198     */
199    FluentProducerTemplate withTemplateCustomizer(java.util.function.Consumer<ProducerTemplate> templateCustomizer);
200
201    /**
202     * Set the exchange to use for send.
203     *
204     * When using withExchange then you must use the send method (request is not supported).
205     *
206     * @param exchange the exchange
207     */
208    FluentProducerTemplate withExchange(Exchange exchange);
209
210    /**
211     * Set the exchangeSupplier which will be invoke to get the exchange to be
212     * used for send.
213     *
214     * When using withExchange then you must use the send method (request is not supported).
215     *
216     * @param exchangeSupplier the supplier
217     */
218    FluentProducerTemplate withExchange(Supplier<Exchange> exchangeSupplier);
219
220    /**
221     * Set the processor to use for send/request.
222     *
223     * <pre>
224     * {@code
225     * FluentProducerTemplate.on(context)
226     *     .withProcessor(
227     *         exchange -> {
228     *             exchange.getIn().setHeader("Key1", "Val1");
229     *             exchange.getIn().setHeader("Key2", "Val2");
230     *             exchange.getIn().setBody("the body");
231     *         }
232     *      )
233     *     .to("direct:start")
234     *     .request()}
235     * </pre>
236     *
237     * @param processor 
238     */
239    FluentProducerTemplate withProcessor(Processor processor);
240
241    /**
242     * Set the processorSupplier which will be invoke to get the processor to be
243     * used for send/request.
244     *
245     * @param processorSupplier the supplier
246     */
247    FluentProducerTemplate withProcessor(Supplier<Processor> processorSupplier);
248
249    /**
250     * Endpoint to send to
251     *
252     * @param endpointUri the endpoint URI to send to
253     */
254    FluentProducerTemplate to(String endpointUri);
255
256    /**
257     * Endpoint to send to
258     *
259     * @param endpoint the endpoint to send to
260     */
261    FluentProducerTemplate to(Endpoint endpoint);
262
263    /**
264     * Send to an endpoint (InOut) returning any result output body.
265     *
266     * @return the result
267     * @throws CamelExecutionException is thrown if error occurred
268     */
269    Object request() throws CamelExecutionException;
270
271    /**
272     * Send to an endpoint (InOut).
273     *
274     * @param type the expected response type
275     * @return the result
276     * @throws CamelExecutionException is thrown if error occurred
277     */
278    <T> T request(Class<T> type) throws CamelExecutionException;
279
280    /**
281     * Sends asynchronously to the given endpoint (InOut).
282     *
283     * @return a handle to be used to get the response in the future
284     */
285    Future<Object> asyncRequest();
286
287    /**
288     * Sends asynchronously to the given endpoint (InOut).
289     *
290     * @param type the expected response type
291     * @return a handle to be used to get the response in the future
292     */
293    <T> Future<T> asyncRequest(Class<T> type);
294
295    /**
296     * Send to an endpoint (InOnly)
297     *
298     * @throws CamelExecutionException is thrown if error occurred
299     */
300    Exchange send() throws CamelExecutionException;
301
302    /**
303     * Sends asynchronously to the given endpoint (InOnly).
304     *
305     * @return a handle to be used to get the response in the future
306     */
307    Future<Exchange> asyncSend();
308}