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.model;
018
019import java.util.function.Supplier;
020
021import javax.xml.bind.annotation.XmlAccessType;
022import javax.xml.bind.annotation.XmlAccessorType;
023import javax.xml.bind.annotation.XmlAttribute;
024import javax.xml.bind.annotation.XmlRootElement;
025import javax.xml.bind.annotation.XmlTransient;
026
027import org.apache.camel.AggregationStrategy;
028import org.apache.camel.model.language.ExpressionDefinition;
029import org.apache.camel.spi.Metadata;
030
031/**
032 * Enriches messages with data polled from a secondary resource
033 *
034 * @see org.apache.camel.processor.Enricher
035 */
036@Metadata(label = "eip,transformation")
037@XmlRootElement(name = "pollEnrich")
038@XmlAccessorType(XmlAccessType.FIELD)
039public class PollEnrichDefinition extends ExpressionNode {
040    @XmlAttribute
041    @Metadata(javaType = "java.time.Duration", defaultValue = "-1")
042    private String timeout;
043    @XmlAttribute(name = "strategyRef")
044    private String aggregationStrategyRef;
045    @XmlAttribute(name = "strategyMethodName")
046    private String aggregationStrategyMethodName;
047    @XmlAttribute(name = "strategyMethodAllowNull")
048    @Metadata(javaType = "java.lang.Boolean")
049    private String aggregationStrategyMethodAllowNull;
050    @XmlAttribute
051    @Metadata(javaType = "java.lang.Boolean")
052    private String aggregateOnException;
053    @XmlTransient
054    private AggregationStrategy aggregationStrategy;
055    @XmlAttribute
056    @Metadata(javaType = "java.lang.Integer")
057    private String cacheSize;
058    @XmlAttribute
059    @Metadata(javaType = "java.lang.Integer")
060    private String ignoreInvalidEndpoint;
061
062    public PollEnrichDefinition() {
063    }
064
065    public PollEnrichDefinition(AggregationStrategy aggregationStrategy, long timeout) {
066        this.aggregationStrategy = aggregationStrategy;
067        this.timeout = Long.toString(timeout);
068    }
069
070    @Override
071    public String toString() {
072        return "PollEnrich[" + getExpression() + "]";
073    }
074
075    @Override
076    public String getShortName() {
077        return "pollEnrich";
078    }
079
080    @Override
081    public String getLabel() {
082        return "pollEnrich[" + getExpression() + "]";
083    }
084
085    // Fluent API
086    // -------------------------------------------------------------------------
087
088    /**
089     * Timeout in millis when polling from the external service.
090     * <p/>
091     * The timeout has influence about the poll enrich behavior. It basically
092     * operations in three different modes:
093     * <ul>
094     * <li>negative value - Waits until a message is available and then returns
095     * it. Warning that this method could block indefinitely if no messages are
096     * available.</li>
097     * <li>0 - Attempts to receive a message exchange immediately without
098     * waiting and returning <tt>null</tt> if a message exchange is not
099     * available yet.</li>
100     * <li>positive value - Attempts to receive a message exchange, waiting up
101     * to the given timeout to expire if a message is not yet available. Returns
102     * <tt>null</tt> if timed out</li>
103     * </ul>
104     * The default value is -1 and therefore the method could block
105     * indefinitely, and therefore its recommended to use a timeout value
106     */
107    public PollEnrichDefinition timeout(long timeout) {
108        setTimeout(Long.toString(timeout));
109        return this;
110    }
111
112    /**
113     * Sets the AggregationStrategy to be used to merge the reply from the
114     * external service, into a single outgoing message. By default Camel will
115     * use the reply from the external service as outgoing message.
116     */
117    public PollEnrichDefinition aggregationStrategy(AggregationStrategy aggregationStrategy) {
118        setAggregationStrategy(aggregationStrategy);
119        return this;
120    }
121
122    /**
123     * Sets the AggregationStrategy to be used to merge the reply from the
124     * external service, into a single outgoing message. By default Camel will
125     * use the reply from the external service as outgoing message.
126     */
127    public PollEnrichDefinition aggregationStrategy(Supplier<AggregationStrategy> aggregationStrategy) {
128        setAggregationStrategy(aggregationStrategy.get());
129        return this;
130    }
131
132    /**
133     * Refers to an AggregationStrategy to be used to merge the reply from the
134     * external service, into a single outgoing message. By default Camel will
135     * use the reply from the external service as outgoing message.
136     */
137    public PollEnrichDefinition aggregationStrategyRef(String aggregationStrategyRef) {
138        setAggregationStrategyRef(aggregationStrategyRef);
139        return this;
140    }
141
142    /**
143     * This option can be used to explicit declare the method name to use, when
144     * using POJOs as the AggregationStrategy.
145     */
146    public PollEnrichDefinition aggregationStrategyMethodName(String aggregationStrategyMethodName) {
147        setAggregationStrategyMethodName(aggregationStrategyMethodName);
148        return this;
149    }
150
151    /**
152     * If this option is false then the aggregate method is not used if there
153     * was no data to enrich. If this option is true then null values is used as
154     * the oldExchange (when no data to enrich), when using POJOs as the
155     * AggregationStrategy.
156     */
157    public PollEnrichDefinition aggregationStrategyMethodAllowNull(boolean aggregationStrategyMethodAllowNull) {
158        setAggregationStrategyMethodAllowNull(Boolean.toString(aggregationStrategyMethodAllowNull));
159        return this;
160    }
161
162    /**
163     * If this option is false then the aggregate method is not used if there
164     * was an exception thrown while trying to retrieve the data to enrich from
165     * the resource. Setting this option to true allows end users to control
166     * what to do if there was an exception in the aggregate method. For example
167     * to suppress the exception or set a custom message body etc.
168     */
169    public PollEnrichDefinition aggregateOnException(boolean aggregateOnException) {
170        setAggregateOnException(Boolean.toString(aggregateOnException));
171        return this;
172    }
173
174    /**
175     * Sets the maximum size used by the
176     * {@link org.apache.camel.spi.ConsumerCache} which is used to cache and
177     * reuse consumers when uris are reused.
178     *
179     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
180     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
181     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
182     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
183     * are stored in memory in the caches.
184     *
185     * However if there are a high degree of dynamic endpoints that have been used before, then it can
186     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
187     * can be set accordingly or rely on the default size (1000).
188     *
189     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
190     * can help reduce memory usage to avoid storing too many non frequent used producers.
191     *
192     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
193     *            or <tt>-1</tt> to turn cache off.
194     * @return the builder
195     */
196    public PollEnrichDefinition cacheSize(int cacheSize) {
197        setCacheSize(Integer.toString(cacheSize));
198        return this;
199    }
200
201    /**
202     * Sets the maximum size used by the
203     * {@link org.apache.camel.spi.ConsumerCache} which is used to cache and
204     * reuse consumers when uris are reused.
205     *
206     * Beware that when using dynamic endpoints then it affects how well the cache can be utilized.
207     * If each dynamic endpoint is unique then its best to turn of caching by setting this to -1, which
208     * allows Camel to not cache both the producers and endpoints; they are regarded as prototype scoped
209     * and will be stopped and discarded after use. This reduces memory usage as otherwise producers/endpoints
210     * are stored in memory in the caches.
211     *
212     * However if there are a high degree of dynamic endpoints that have been used before, then it can
213     * benefit to use the cache to reuse both producers and endpoints and therefore the cache size
214     * can be set accordingly or rely on the default size (1000).
215     *
216     * If there is a mix of unique and used before dynamic endpoints, then setting a reasonable cache size
217     * can help reduce memory usage to avoid storing too many non frequent used producers.
218     *
219     * @param cacheSize the cache size, use <tt>0</tt> for default cache size,
220     *            or <tt>-1</tt> to turn cache off.
221     * @return the builder
222     */
223    public PollEnrichDefinition cacheSize(String cacheSize) {
224        setCacheSize(cacheSize);
225        return this;
226    }
227
228    /**
229     * Ignore the invalidate endpoint exception when try to create a producer
230     * with that endpoint
231     *
232     * @return the builder
233     */
234    public PollEnrichDefinition ignoreInvalidEndpoint() {
235        setIgnoreInvalidEndpoint(Boolean.toString(true));
236        return this;
237    }
238
239    // Properties
240    // -------------------------------------------------------------------------
241
242    /**
243     * Expression that computes the endpoint uri to use as the resource endpoint
244     * to enrich from
245     */
246    @Override
247    public void setExpression(ExpressionDefinition expression) {
248        // override to include javadoc what the expression is used for
249        super.setExpression(expression);
250    }
251
252    public String getTimeout() {
253        return timeout;
254    }
255
256    public void setTimeout(String timeout) {
257        this.timeout = timeout;
258    }
259
260    public String getAggregationStrategyRef() {
261        return aggregationStrategyRef;
262    }
263
264    public void setAggregationStrategyRef(String aggregationStrategyRef) {
265        this.aggregationStrategyRef = aggregationStrategyRef;
266    }
267
268    public String getAggregationStrategyMethodName() {
269        return aggregationStrategyMethodName;
270    }
271
272    public void setAggregationStrategyMethodName(String aggregationStrategyMethodName) {
273        this.aggregationStrategyMethodName = aggregationStrategyMethodName;
274    }
275
276    public String getAggregationStrategyMethodAllowNull() {
277        return aggregationStrategyMethodAllowNull;
278    }
279
280    public void setAggregationStrategyMethodAllowNull(String aggregationStrategyMethodAllowNull) {
281        this.aggregationStrategyMethodAllowNull = aggregationStrategyMethodAllowNull;
282    }
283
284    public AggregationStrategy getAggregationStrategy() {
285        return aggregationStrategy;
286    }
287
288    public void setAggregationStrategy(AggregationStrategy aggregationStrategy) {
289        this.aggregationStrategy = aggregationStrategy;
290    }
291
292    public String getAggregateOnException() {
293        return aggregateOnException;
294    }
295
296    public void setAggregateOnException(String aggregateOnException) {
297        this.aggregateOnException = aggregateOnException;
298    }
299
300    public String getCacheSize() {
301        return cacheSize;
302    }
303
304    public void setCacheSize(String cacheSize) {
305        this.cacheSize = cacheSize;
306    }
307
308    public String getIgnoreInvalidEndpoint() {
309        return ignoreInvalidEndpoint;
310    }
311
312    public void setIgnoreInvalidEndpoint(String ignoreInvalidEndpoint) {
313        this.ignoreInvalidEndpoint = ignoreInvalidEndpoint;
314    }
315}