All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.camel.model.AggregateDefinition Maven / Gradle / Ivy

There is a newer version: 4.6.0
Show newest version
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.model;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;

import org.apache.camel.CamelContextAware;
import org.apache.camel.Expression;
import org.apache.camel.Predicate;
import org.apache.camel.Processor;
import org.apache.camel.builder.AggregationStrategyClause;
import org.apache.camel.builder.ExpressionClause;
import org.apache.camel.builder.PredicateClause;
import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.processor.CamelInternalProcessor;
import org.apache.camel.processor.aggregate.AggregateController;
import org.apache.camel.processor.aggregate.AggregateProcessor;
import org.apache.camel.processor.aggregate.AggregationStrategy;
import org.apache.camel.processor.aggregate.AggregationStrategyBeanAdapter;
import org.apache.camel.processor.aggregate.ClosedCorrelationKeyException;
import org.apache.camel.processor.aggregate.GroupedExchangeAggregationStrategy;
import org.apache.camel.processor.aggregate.OptimisticLockRetryPolicy;
import org.apache.camel.spi.AggregationRepository;
import org.apache.camel.spi.AsPredicate;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.RouteContext;
import org.apache.camel.util.concurrent.SynchronousExecutorService;

/**
 * Aggregates many messages into a single message
 *
 * @version 
 */
@Metadata(label = "eip,routing")
@XmlRootElement(name = "aggregate")
@XmlAccessorType(XmlAccessType.FIELD)
public class AggregateDefinition extends ProcessorDefinition implements ExecutorServiceAwareDefinition {
    @XmlElement(name = "correlationExpression", required = true)
    private ExpressionSubElementDefinition correlationExpression;
    @XmlElement(name = "completionPredicate") @AsPredicate
    private ExpressionSubElementDefinition completionPredicate;
    @XmlElement(name = "completionTimeout")
    private ExpressionSubElementDefinition completionTimeoutExpression;
    @XmlElement(name = "completionSize")
    private ExpressionSubElementDefinition completionSizeExpression;
    @XmlElement(name = "optimisticLockRetryPolicy")
    private OptimisticLockRetryPolicyDefinition optimisticLockRetryPolicyDefinition;
    @XmlTransient
    private ExpressionDefinition expression;
    @XmlTransient
    private AggregationStrategy aggregationStrategy;
    @XmlTransient
    private ExecutorService executorService;
    @XmlTransient
    private ScheduledExecutorService timeoutCheckerExecutorService;
    @XmlTransient
    private AggregationRepository aggregationRepository;
    @XmlTransient
    private OptimisticLockRetryPolicy optimisticLockRetryPolicy;
    @XmlAttribute
    private Boolean parallelProcessing;
    @XmlAttribute
    private Boolean optimisticLocking;
    @XmlAttribute
    private String executorServiceRef;
    @XmlAttribute
    private String timeoutCheckerExecutorServiceRef;
    @XmlAttribute
    private String aggregationRepositoryRef;
    @XmlAttribute
    private String strategyRef;
    @XmlAttribute
    private String strategyMethodName;
    @XmlAttribute
    private Boolean strategyMethodAllowNull;
    @XmlAttribute
    private Integer completionSize;
    @XmlAttribute
    private Long completionInterval;
    @XmlAttribute
    private Long completionTimeout;
    @XmlAttribute
    private Boolean completionFromBatchConsumer;
    @XmlAttribute
    @Deprecated
    private Boolean groupExchanges;
    @XmlAttribute
    private Boolean eagerCheckCompletion;
    @XmlAttribute
    private Boolean ignoreInvalidCorrelationKeys;
    @XmlAttribute
    private Integer closeCorrelationKeyOnCompletion;
    @XmlAttribute
    private Boolean discardOnCompletionTimeout;
    @XmlAttribute
    private Boolean forceCompletionOnStop;
    @XmlAttribute
    private Boolean completeAllOnStop;
    @XmlTransient
    private AggregateController aggregateController;
    @XmlAttribute
    private String aggregateControllerRef;
    @XmlElementRef
    private List> outputs = new ArrayList>();

    public AggregateDefinition() {
    }

    public AggregateDefinition(@AsPredicate Predicate predicate) {
        this(ExpressionNodeHelper.toExpressionDefinition(predicate));
    }
    
    public AggregateDefinition(Expression expression) {
        this(ExpressionNodeHelper.toExpressionDefinition(expression));
    }

    public AggregateDefinition(ExpressionDefinition correlationExpression) {
        setExpression(correlationExpression);

        ExpressionSubElementDefinition cor = new ExpressionSubElementDefinition();
        cor.setExpressionType(correlationExpression);
        setCorrelationExpression(cor);
    }

    public AggregateDefinition(Expression correlationExpression, AggregationStrategy aggregationStrategy) {
        this(correlationExpression);
        this.aggregationStrategy = aggregationStrategy;
    }

    @Override
    public String toString() {
        return "Aggregate[" + description() + " -> " + getOutputs() + "]";
    }
    
    protected String description() {
        return getExpression() != null ? getExpression().getLabel() : "";
    }

    @Override
    public String getLabel() {
        return "aggregate[" + description() + "]";
    }

    @Override
    public Processor createProcessor(RouteContext routeContext) throws Exception {
        return createAggregator(routeContext);
    }

    protected AggregateProcessor createAggregator(RouteContext routeContext) throws Exception {
        Processor childProcessor = this.createChildProcessor(routeContext, true);

        // wrap the aggregate route in a unit of work processor
        CamelInternalProcessor internal = new CamelInternalProcessor(childProcessor);
        internal.addAdvice(new CamelInternalProcessor.UnitOfWorkProcessorAdvice(routeContext));

        Expression correlation = getExpression().createExpression(routeContext);
        AggregationStrategy strategy = createAggregationStrategy(routeContext);

        boolean parallel = getParallelProcessing() != null && getParallelProcessing();
        boolean shutdownThreadPool = ProcessorDefinitionHelper.willCreateNewThreadPool(routeContext, this, parallel);
        ExecutorService threadPool = ProcessorDefinitionHelper.getConfiguredExecutorService(routeContext, "Aggregator", this, parallel);
        if (threadPool == null && !parallel) {
            // executor service is mandatory for the Aggregator
            // we do not run in parallel mode, but use a synchronous executor, so we run in current thread
            threadPool = new SynchronousExecutorService();
            shutdownThreadPool = true;
        }

        AggregateProcessor answer = new AggregateProcessor(routeContext.getCamelContext(), internal,
                correlation, strategy, threadPool, shutdownThreadPool);

        AggregationRepository repository = createAggregationRepository(routeContext);
        if (repository != null) {
            answer.setAggregationRepository(repository);
        }

        if (getAggregateController() == null && getAggregateControllerRef() != null) {
            setAggregateController(routeContext.mandatoryLookup(getAggregateControllerRef(), AggregateController.class));
        }

        // this EIP supports using a shared timeout checker thread pool or fallback to create a new thread pool
        boolean shutdownTimeoutThreadPool = false;
        ScheduledExecutorService timeoutThreadPool = timeoutCheckerExecutorService;
        if (timeoutThreadPool == null && timeoutCheckerExecutorServiceRef != null) {
            // lookup existing thread pool
            timeoutThreadPool = routeContext.getCamelContext().getRegistry().lookupByNameAndType(timeoutCheckerExecutorServiceRef, ScheduledExecutorService.class);
            if (timeoutThreadPool == null) {
                // then create a thread pool assuming the ref is a thread pool profile id
                timeoutThreadPool = routeContext.getCamelContext().getExecutorServiceManager().newScheduledThreadPool(this,
                        AggregateProcessor.AGGREGATE_TIMEOUT_CHECKER, timeoutCheckerExecutorServiceRef);
                if (timeoutThreadPool == null) {
                    throw new IllegalArgumentException("ExecutorServiceRef " + timeoutCheckerExecutorServiceRef 
                            + " not found in registry (as an ScheduledExecutorService instance) or as a thread pool profile.");
                }
                shutdownTimeoutThreadPool = true;
            }
        }
        answer.setTimeoutCheckerExecutorService(timeoutThreadPool);
        answer.setShutdownTimeoutCheckerExecutorService(shutdownTimeoutThreadPool);

        // set other options
        answer.setParallelProcessing(parallel);
        if (getOptimisticLocking() != null) {
            answer.setOptimisticLocking(getOptimisticLocking());
        }
        if (getCompletionPredicate() != null) {
            Predicate predicate = getCompletionPredicate().createPredicate(routeContext);
            answer.setCompletionPredicate(predicate);
        } else if (strategy instanceof Predicate) {
            // if aggregation strategy implements predicate and was not configured then use as fallback
            log.debug("Using AggregationStrategy as completion predicate: {}", strategy);
            answer.setCompletionPredicate((Predicate) strategy);
        }
        if (getCompletionTimeoutExpression() != null) {
            Expression expression = getCompletionTimeoutExpression().createExpression(routeContext);
            answer.setCompletionTimeoutExpression(expression);
        }
        if (getCompletionTimeout() != null) {
            answer.setCompletionTimeout(getCompletionTimeout());
        }
        if (getCompletionInterval() != null) {
            answer.setCompletionInterval(getCompletionInterval());
        }
        if (getCompletionSizeExpression() != null) {
            Expression expression = getCompletionSizeExpression().createExpression(routeContext);
            answer.setCompletionSizeExpression(expression);
        }
        if (getCompletionSize() != null) {
            answer.setCompletionSize(getCompletionSize());
        }
        if (getCompletionFromBatchConsumer() != null) {
            answer.setCompletionFromBatchConsumer(getCompletionFromBatchConsumer());
        }
        if (getEagerCheckCompletion() != null) {
            answer.setEagerCheckCompletion(getEagerCheckCompletion());
        }
        if (getIgnoreInvalidCorrelationKeys() != null) {
            answer.setIgnoreInvalidCorrelationKeys(getIgnoreInvalidCorrelationKeys());
        }
        if (getCloseCorrelationKeyOnCompletion() != null) {
            answer.setCloseCorrelationKeyOnCompletion(getCloseCorrelationKeyOnCompletion());
        }
        if (getDiscardOnCompletionTimeout() != null) {
            answer.setDiscardOnCompletionTimeout(getDiscardOnCompletionTimeout());
        }
        if (getForceCompletionOnStop() != null) {
            answer.setForceCompletionOnStop(getForceCompletionOnStop());
        }
        if (getCompleteAllOnStop() != null) {
            answer.setCompleteAllOnStop(getCompleteAllOnStop());
        }
        if (optimisticLockRetryPolicy == null) {
            if (getOptimisticLockRetryPolicyDefinition() != null) {
                answer.setOptimisticLockRetryPolicy(getOptimisticLockRetryPolicyDefinition().createOptimisticLockRetryPolicy());
            }
        } else {
            answer.setOptimisticLockRetryPolicy(optimisticLockRetryPolicy);
        }
        if (getAggregateController() != null) {
            answer.setAggregateController(getAggregateController());
        }
        return answer;
    }

    @Override
    public void configureChild(ProcessorDefinition output) {
        if (expression != null && expression instanceof ExpressionClause) {
            ExpressionClause clause = (ExpressionClause) expression;
            if (clause.getExpressionType() != null) {
                // if using the Java DSL then the expression may have been set using the
                // ExpressionClause which is a fancy builder to define expressions and predicates
                // using fluent builders in the DSL. However we need afterwards a callback to
                // reset the expression to the expression type the ExpressionClause did build for us
                expression = clause.getExpressionType();
                // set the correlation expression from the expression type, as the model definition
                // would then be accurate
                correlationExpression = new ExpressionSubElementDefinition();
                correlationExpression.setExpressionType(clause.getExpressionType());
            }
        }
    }

    private AggregationStrategy createAggregationStrategy(RouteContext routeContext) {
        AggregationStrategy strategy = getAggregationStrategy();
        if (strategy == null && strategyRef != null) {
            Object aggStrategy = routeContext.lookup(strategyRef, Object.class);
            if (aggStrategy instanceof AggregationStrategy) {
                strategy = (AggregationStrategy) aggStrategy;
            } else if (aggStrategy != null) {
                AggregationStrategyBeanAdapter adapter = new AggregationStrategyBeanAdapter(aggStrategy, getAggregationStrategyMethodName());
                if (getStrategyMethodAllowNull() != null) {
                    adapter.setAllowNullNewExchange(getStrategyMethodAllowNull());
                    adapter.setAllowNullOldExchange(getStrategyMethodAllowNull());
                }
                strategy = adapter;
            } else {
                throw new IllegalArgumentException("Cannot find AggregationStrategy in Registry with name: " + strategyRef);
            }
        }

        if (groupExchanges != null && groupExchanges) {
            if (strategy != null || strategyRef != null) {
                throw new IllegalArgumentException("Options groupExchanges and AggregationStrategy cannot be enabled at the same time");
            }
            if (eagerCheckCompletion != null && !eagerCheckCompletion) {
                throw new IllegalArgumentException("Option eagerCheckCompletion cannot be false when groupExchanges has been enabled");
            }
            // set eager check to enabled by default when using grouped exchanges
            setEagerCheckCompletion(true);
            // if grouped exchange is enabled then use special strategy for that
            strategy = new GroupedExchangeAggregationStrategy();
        }

        if (strategy == null) {
            throw new IllegalArgumentException("AggregationStrategy or AggregationStrategyRef must be set on " + this);
        }

        if (strategy instanceof CamelContextAware) {
            ((CamelContextAware) strategy).setCamelContext(routeContext.getCamelContext());
        }

        return strategy;
    }

    private AggregationRepository createAggregationRepository(RouteContext routeContext) {
        AggregationRepository repository = getAggregationRepository();
        if (repository == null && aggregationRepositoryRef != null) {
            repository = routeContext.mandatoryLookup(aggregationRepositoryRef, AggregationRepository.class);
        }
        return repository;
    }

    public AggregationStrategy getAggregationStrategy() {
        return aggregationStrategy;
    }

    /**
     * The AggregationStrategy to use.
     * 

* Configuring an AggregationStrategy is required, and is used to merge the incoming Exchange with the existing already merged exchanges. * At first call the oldExchange parameter is null. * On subsequent invocations the oldExchange contains the merged exchanges and newExchange is of course the new incoming Exchange. */ public void setAggregationStrategy(AggregationStrategy aggregationStrategy) { this.aggregationStrategy = aggregationStrategy; } public String getAggregationStrategyRef() { return strategyRef; } /** * A reference to lookup the AggregationStrategy in the Registry. *

* Configuring an AggregationStrategy is required, and is used to merge the incoming Exchange with the existing already merged exchanges. * At first call the oldExchange parameter is null. * On subsequent invocations the oldExchange contains the merged exchanges and newExchange is of course the new incoming Exchange. */ public void setAggregationStrategyRef(String aggregationStrategyRef) { this.strategyRef = aggregationStrategyRef; } public String getStrategyRef() { return strategyRef; } /** * A reference to lookup the AggregationStrategy in the Registry. *

* Configuring an AggregationStrategy is required, and is used to merge the incoming Exchange with the existing already merged exchanges. * At first call the oldExchange parameter is null. * On subsequent invocations the oldExchange contains the merged exchanges and newExchange is of course the new incoming Exchange. */ public void setStrategyRef(String strategyRef) { this.strategyRef = strategyRef; } public String getAggregationStrategyMethodName() { return strategyMethodName; } /** * This option can be used to explicit declare the method name to use, when using POJOs as the AggregationStrategy. */ public void setAggregationStrategyMethodName(String strategyMethodName) { this.strategyMethodName = strategyMethodName; } public Boolean getStrategyMethodAllowNull() { return strategyMethodAllowNull; } public String getStrategyMethodName() { return strategyMethodName; } /** * This option can be used to explicit declare the method name to use, when using POJOs as the AggregationStrategy. */ public void setStrategyMethodName(String strategyMethodName) { this.strategyMethodName = strategyMethodName; } /** * If this option is false then the aggregate method is not used for the very first aggregation. * If this option is true then null values is used as the oldExchange (at the very first aggregation), * when using POJOs as the AggregationStrategy. */ public void setStrategyMethodAllowNull(Boolean strategyMethodAllowNull) { this.strategyMethodAllowNull = strategyMethodAllowNull; } /** * The expression used to calculate the correlation key to use for aggregation. * The Exchange which has the same correlation key is aggregated together. * If the correlation key could not be evaluated an Exception is thrown. * You can disable this by using the ignoreBadCorrelationKeys option. */ public void setCorrelationExpression(ExpressionSubElementDefinition correlationExpression) { this.correlationExpression = correlationExpression; } public ExpressionSubElementDefinition getCorrelationExpression() { return correlationExpression; } public Integer getCompletionSize() { return completionSize; } public void setCompletionSize(Integer completionSize) { this.completionSize = completionSize; } public OptimisticLockRetryPolicyDefinition getOptimisticLockRetryPolicyDefinition() { return optimisticLockRetryPolicyDefinition; } public void setOptimisticLockRetryPolicyDefinition(OptimisticLockRetryPolicyDefinition optimisticLockRetryPolicyDefinition) { this.optimisticLockRetryPolicyDefinition = optimisticLockRetryPolicyDefinition; } public OptimisticLockRetryPolicy getOptimisticLockRetryPolicy() { return optimisticLockRetryPolicy; } public void setOptimisticLockRetryPolicy(OptimisticLockRetryPolicy optimisticLockRetryPolicy) { this.optimisticLockRetryPolicy = optimisticLockRetryPolicy; } public Long getCompletionInterval() { return completionInterval; } public void setCompletionInterval(Long completionInterval) { this.completionInterval = completionInterval; } public Long getCompletionTimeout() { return completionTimeout; } public void setCompletionTimeout(Long completionTimeout) { this.completionTimeout = completionTimeout; } public ExpressionSubElementDefinition getCompletionPredicate() { return completionPredicate; } public void setCompletionPredicate(ExpressionSubElementDefinition completionPredicate) { this.completionPredicate = completionPredicate; } public ExpressionSubElementDefinition getCompletionTimeoutExpression() { return completionTimeoutExpression; } public void setCompletionTimeoutExpression(ExpressionSubElementDefinition completionTimeoutExpression) { this.completionTimeoutExpression = completionTimeoutExpression; } public ExpressionSubElementDefinition getCompletionSizeExpression() { return completionSizeExpression; } public void setCompletionSizeExpression(ExpressionSubElementDefinition completionSizeExpression) { this.completionSizeExpression = completionSizeExpression; } public Boolean getGroupExchanges() { return groupExchanges; } public void setGroupExchanges(Boolean groupExchanges) { this.groupExchanges = groupExchanges; } public Boolean getCompletionFromBatchConsumer() { return completionFromBatchConsumer; } public void setCompletionFromBatchConsumer(Boolean completionFromBatchConsumer) { this.completionFromBatchConsumer = completionFromBatchConsumer; } public ExecutorService getExecutorService() { return executorService; } public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } public Boolean getOptimisticLocking() { return optimisticLocking; } public void setOptimisticLocking(boolean optimisticLocking) { this.optimisticLocking = optimisticLocking; } public Boolean getParallelProcessing() { return parallelProcessing; } public void setParallelProcessing(boolean parallelProcessing) { this.parallelProcessing = parallelProcessing; } public String getExecutorServiceRef() { return executorServiceRef; } public void setExecutorServiceRef(String executorServiceRef) { this.executorServiceRef = executorServiceRef; } public Boolean getEagerCheckCompletion() { return eagerCheckCompletion; } public void setEagerCheckCompletion(Boolean eagerCheckCompletion) { this.eagerCheckCompletion = eagerCheckCompletion; } public Boolean getIgnoreInvalidCorrelationKeys() { return ignoreInvalidCorrelationKeys; } public void setIgnoreInvalidCorrelationKeys(Boolean ignoreInvalidCorrelationKeys) { this.ignoreInvalidCorrelationKeys = ignoreInvalidCorrelationKeys; } public Integer getCloseCorrelationKeyOnCompletion() { return closeCorrelationKeyOnCompletion; } public void setCloseCorrelationKeyOnCompletion(Integer closeCorrelationKeyOnCompletion) { this.closeCorrelationKeyOnCompletion = closeCorrelationKeyOnCompletion; } public AggregationRepository getAggregationRepository() { return aggregationRepository; } public void setAggregationRepository(AggregationRepository aggregationRepository) { this.aggregationRepository = aggregationRepository; } public String getAggregationRepositoryRef() { return aggregationRepositoryRef; } public void setAggregationRepositoryRef(String aggregationRepositoryRef) { this.aggregationRepositoryRef = aggregationRepositoryRef; } public Boolean getDiscardOnCompletionTimeout() { return discardOnCompletionTimeout; } public void setDiscardOnCompletionTimeout(Boolean discardOnCompletionTimeout) { this.discardOnCompletionTimeout = discardOnCompletionTimeout; } public void setTimeoutCheckerExecutorService(ScheduledExecutorService timeoutCheckerExecutorService) { this.timeoutCheckerExecutorService = timeoutCheckerExecutorService; } public ScheduledExecutorService getTimeoutCheckerExecutorService() { return timeoutCheckerExecutorService; } public void setTimeoutCheckerExecutorServiceRef(String timeoutCheckerExecutorServiceRef) { this.timeoutCheckerExecutorServiceRef = timeoutCheckerExecutorServiceRef; } public String getTimeoutCheckerExecutorServiceRef() { return timeoutCheckerExecutorServiceRef; } public Boolean getForceCompletionOnStop() { return forceCompletionOnStop; } public void setForceCompletionOnStop(Boolean forceCompletionOnStop) { this.forceCompletionOnStop = forceCompletionOnStop; } public Boolean getCompleteAllOnStop() { return completeAllOnStop; } public void setCompleteAllOnStop(Boolean completeAllOnStop) { this.completeAllOnStop = completeAllOnStop; } public AggregateController getAggregateController() { return aggregateController; } public void setAggregateController(AggregateController aggregateController) { this.aggregateController = aggregateController; } public String getAggregateControllerRef() { return aggregateControllerRef; } /** * To use a {@link org.apache.camel.processor.aggregate.AggregateController} to allow external sources to control * this aggregator. */ public void setAggregateControllerRef(String aggregateControllerRef) { this.aggregateControllerRef = aggregateControllerRef; } // Fluent API //------------------------------------------------------------------------- /** * Use eager completion checking which means that the {{completionPredicate}} will use the incoming Exchange. * As opposed to without eager completion checking the {{completionPredicate}} will use the aggregated Exchange. * * @return builder */ public AggregateDefinition eagerCheckCompletion() { setEagerCheckCompletion(true); return this; } /** * If a correlation key cannot be successfully evaluated it will be ignored by logging a {{DEBUG}} and then just * ignore the incoming Exchange. * * @return builder */ public AggregateDefinition ignoreInvalidCorrelationKeys() { setIgnoreInvalidCorrelationKeys(true); return this; } /** * Closes a correlation key when its complete. Any late received exchanges which has a correlation key * that has been closed, it will be defined and a {@link ClosedCorrelationKeyException} * is thrown. * * @param capacity the maximum capacity of the closed correlation key cache. * Use 0 or negative value for unbounded capacity. * @return builder */ public AggregateDefinition closeCorrelationKeyOnCompletion(int capacity) { setCloseCorrelationKeyOnCompletion(capacity); return this; } /** * Discards the aggregated message on completion timeout. *

* This means on timeout the aggregated message is dropped and not sent out of the aggregator. * * @return builder */ public AggregateDefinition discardOnCompletionTimeout() { setDiscardOnCompletionTimeout(true); return this; } /** * Enables the batch completion mode where we aggregate from a {@link org.apache.camel.BatchConsumer} * and aggregate the total number of exchanges the {@link org.apache.camel.BatchConsumer} has reported * as total by checking the exchange property {@link org.apache.camel.Exchange#BATCH_COMPLETE} when its complete. * * @return builder */ public AggregateDefinition completionFromBatchConsumer() { setCompletionFromBatchConsumer(true); return this; } /** * Number of messages aggregated before the aggregation is complete. This option can be set as either * a fixed value or using an Expression which allows you to evaluate a size dynamically - will use Integer as result. * If both are set Camel will fallback to use the fixed value if the Expression result was null or 0. * * @param completionSize the completion size, must be a positive number * @return builder */ public AggregateDefinition completionSize(int completionSize) { setCompletionSize(completionSize); return this; } /** * Number of messages aggregated before the aggregation is complete. This option can be set as either * a fixed value or using an Expression which allows you to evaluate a size dynamically - will use Integer as result. * If both are set Camel will fallback to use the fixed value if the Expression result was null or 0. * * @param completionSize the completion size as an {@link org.apache.camel.Expression} which is evaluated as a {@link Integer} type * @return builder */ public AggregateDefinition completionSize(Expression completionSize) { setCompletionSizeExpression(new ExpressionSubElementDefinition(completionSize)); return this; } /** * A repeating period in millis by which the aggregator will complete all current aggregated exchanges. * Camel has a background task which is triggered every period. You cannot use this option together * with completionTimeout, only one of them can be used. * * @param completionInterval the interval in millis, must be a positive value * @return the builder */ public AggregateDefinition completionInterval(long completionInterval) { setCompletionInterval(completionInterval); return this; } /** * Time in millis that an aggregated exchange should be inactive before its complete (timeout). * This option can be set as either a fixed value or using an Expression which allows you to evaluate * a timeout dynamically - will use Long as result. * If both are set Camel will fallback to use the fixed value if the Expression result was null or 0. * You cannot use this option together with completionInterval, only one of the two can be used. * * @param completionTimeout the timeout in millis, must be a positive value * @return the builder */ public AggregateDefinition completionTimeout(long completionTimeout) { setCompletionTimeout(completionTimeout); return this; } /** * Time in millis that an aggregated exchange should be inactive before its complete (timeout). * This option can be set as either a fixed value or using an Expression which allows you to evaluate * a timeout dynamically - will use Long as result. * If both are set Camel will fallback to use the fixed value if the Expression result was null or 0. * You cannot use this option together with completionInterval, only one of the two can be used. * * @param completionTimeout the timeout as an {@link Expression} which is evaluated as a {@link Long} type * @return the builder */ public AggregateDefinition completionTimeout(Expression completionTimeout) { setCompletionTimeoutExpression(new ExpressionSubElementDefinition(completionTimeout)); return this; } /** * Sets the AggregationStrategy to use with a fluent builder. */ public AggregationStrategyClause aggregationStrategy() { AggregationStrategyClause clause = new AggregationStrategyClause<>(this); setAggregationStrategy(clause); return clause; } /** * Sets the AggregationStrategy to use with a fluent builder. */ public AggregationStrategyClause strategy() { return aggregationStrategy(); } /** * Sets the aggregate strategy to use * * @param aggregationStrategy the aggregate strategy to use * @return the builder */ public AggregateDefinition strategy(AggregationStrategy aggregationStrategy) { return aggregationStrategy(aggregationStrategy); } /** * Sets the aggregate strategy to use * * @param aggregationStrategy the aggregate strategy to use * @return the builder */ public AggregateDefinition aggregationStrategy(AggregationStrategy aggregationStrategy) { setAggregationStrategy(aggregationStrategy); return this; } /** * Sets the aggregate strategy to use * * @param aggregationStrategyRef reference to the strategy to lookup in the registry * @return the builder */ public AggregateDefinition aggregationStrategyRef(String aggregationStrategyRef) { setAggregationStrategyRef(aggregationStrategyRef); return this; } /** * Sets the method name to use when using a POJO as {@link AggregationStrategy}. * * @param methodName the method name to call * @return the builder */ public AggregateDefinition aggregationStrategyMethodName(String methodName) { setAggregationStrategyMethodName(methodName); return this; } /** * Sets allowing null when using a POJO as {@link AggregationStrategy}. * * @return the builder */ public AggregateDefinition aggregationStrategyMethodAllowNull() { setStrategyMethodAllowNull(true); return this; } /** * Sets the custom aggregate repository to use. *

* Will by default use {@link org.apache.camel.processor.aggregate.MemoryAggregationRepository} * * @param aggregationRepository the aggregate repository to use * @return the builder */ public AggregateDefinition aggregationRepository(AggregationRepository aggregationRepository) { setAggregationRepository(aggregationRepository); return this; } /** * Sets the custom aggregate repository to use *

* Will by default use {@link org.apache.camel.processor.aggregate.MemoryAggregationRepository} * * @param aggregationRepositoryRef reference to the repository to lookup in the registry * @return the builder */ public AggregateDefinition aggregationRepositoryRef(String aggregationRepositoryRef) { setAggregationRepositoryRef(aggregationRepositoryRef); return this; } /** * Enables grouped exchanges, so the aggregator will group all aggregated exchanges into a single * combined Exchange holding all the aggregated exchanges in a {@link java.util.List}. * * @deprecated use {@link GroupedExchangeAggregationStrategy} as aggregation strategy instead. */ @Deprecated public AggregateDefinition groupExchanges() { setGroupExchanges(true); // must use eager check when using grouped exchanges setEagerCheckCompletion(true); return this; } /** * A Predicate to indicate when an aggregated exchange is complete. * If this is not specified and the AggregationStrategy object implements Predicate, * the aggregationStrategy object will be used as the completionPredicate. */ public AggregateDefinition completionPredicate(@AsPredicate Predicate predicate) { checkNoCompletedPredicate(); setCompletionPredicate(new ExpressionSubElementDefinition(predicate)); return this; } /** * A Predicate to indicate when an aggregated exchange is complete. * If this is not specified and the AggregationStrategy object implements Predicate, * the aggregationStrategy object will be used as the completionPredicate. */ @AsPredicate public PredicateClause completionPredicate() { PredicateClause clause = new PredicateClause<>(this); completionPredicate(clause); return clause; } /** * A Predicate to indicate when an aggregated exchange is complete. * If this is not specified and the AggregationStrategy object implements Predicate, * the aggregationStrategy object will be used as the completionPredicate. */ @AsPredicate public PredicateClause completion() { return completionPredicate(); } /** * A Predicate to indicate when an aggregated exchange is complete. * If this is not specified and the AggregationStrategy object implements Predicate, * the aggregationStrategy object will be used as the completionPredicate. */ public AggregateDefinition completion(@AsPredicate Predicate predicate) { return completionPredicate(predicate); } /** * Indicates to complete all current aggregated exchanges when the context is stopped */ public AggregateDefinition forceCompletionOnStop() { setForceCompletionOnStop(true); return this; } /** * Indicates to wait to complete all current and partial (pending) aggregated exchanges when the context is stopped. *

* This also means that we will wait for all pending exchanges which are stored in the aggregation repository * to complete so the repository is empty before we can stop. *

* You may want to enable this when using the memory based aggregation repository that is memory based only, * and do not store data on disk. When this option is enabled, then the aggregator is waiting to complete * all those exchanges before its stopped, when stopping CamelContext or the route using it. */ public AggregateDefinition completeAllOnStop() { setCompleteAllOnStop(true); return this; } /** * When aggregated are completed they are being send out of the aggregator. * This option indicates whether or not Camel should use a thread pool with multiple threads for concurrency. * If no custom thread pool has been specified then Camel creates a default pool with 10 concurrent threads. */ public AggregateDefinition parallelProcessing() { setParallelProcessing(true); return this; } /** * When aggregated are completed they are being send out of the aggregator. * This option indicates whether or not Camel should use a thread pool with multiple threads for concurrency. * If no custom thread pool has been specified then Camel creates a default pool with 10 concurrent threads. */ public AggregateDefinition parallelProcessing(boolean parallelProcessing) { setParallelProcessing(parallelProcessing); return this; } /** * Turns on using optimistic locking, which requires the aggregationRepository being used, * is supporting this by implementing {@link org.apache.camel.spi.OptimisticLockingAggregationRepository}. */ public AggregateDefinition optimisticLocking() { setOptimisticLocking(true); return this; } /** * Allows to configure retry settings when using optimistic locking. */ public AggregateDefinition optimisticLockRetryPolicy(OptimisticLockRetryPolicy policy) { setOptimisticLockRetryPolicy(policy); return this; } /** * If using parallelProcessing you can specify a custom thread pool to be used. * In fact also if you are not using parallelProcessing this custom thread pool is used to send out aggregated exchanges as well. */ public AggregateDefinition executorService(ExecutorService executorService) { setExecutorService(executorService); return this; } /** * If using parallelProcessing you can specify a custom thread pool to be used. * In fact also if you are not using parallelProcessing this custom thread pool is used to send out aggregated exchanges as well. */ public AggregateDefinition executorServiceRef(String executorServiceRef) { setExecutorServiceRef(executorServiceRef); return this; } /** * If using either of the completionTimeout, completionTimeoutExpression, or completionInterval options a * background thread is created to check for the completion for every aggregator. * Set this option to provide a custom thread pool to be used rather than creating a new thread for every aggregator. */ public AggregateDefinition timeoutCheckerExecutorService(ScheduledExecutorService executorService) { setTimeoutCheckerExecutorService(executorService); return this; } /** * If using either of the completionTimeout, completionTimeoutExpression, or completionInterval options a * background thread is created to check for the completion for every aggregator. * Set this option to provide a custom thread pool to be used rather than creating a new thread for every aggregator. */ public AggregateDefinition timeoutCheckerExecutorServiceRef(String executorServiceRef) { setTimeoutCheckerExecutorServiceRef(executorServiceRef); return this; } /** * To use a {@link org.apache.camel.processor.aggregate.AggregateController} to allow external sources to control * this aggregator. */ public AggregateDefinition aggregateController(AggregateController aggregateController) { setAggregateController(aggregateController); return this; } // Section - Methods from ExpressionNode // Needed to copy methods from ExpressionNode here so that I could specify the // correlation expression as optional in JAXB public ExpressionDefinition getExpression() { if (expression == null && correlationExpression != null) { expression = correlationExpression.getExpressionType(); } return expression; } public void setExpression(ExpressionDefinition expression) { this.expression = expression; } protected void checkNoCompletedPredicate() { if (getCompletionPredicate() != null) { throw new IllegalArgumentException("There is already a completionPredicate defined for this aggregator: " + this); } } @Override public List> getOutputs() { return outputs; } public boolean isOutputSupported() { return true; } public void setOutputs(List> outputs) { this.outputs = outputs; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy