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

org.apache.camel.processor.PollEnricher 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.processor;

import org.apache.camel.AsyncCallback;
import org.apache.camel.AsyncProcessor;
import org.apache.camel.CamelExchangeException;
import org.apache.camel.Exchange;
import org.apache.camel.PollingConsumer;
import org.apache.camel.processor.aggregate.AggregationStrategy;
import org.apache.camel.support.ServiceSupport;
import org.apache.camel.util.AsyncProcessorHelper;
import org.apache.camel.util.ExchangeHelper;
import org.apache.camel.util.ServiceHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.camel.util.ExchangeHelper.copyResultsPreservePattern;

/**
 * A content enricher that enriches input data by first obtaining additional
 * data from a resource represented by an endpoint producer
 * and second by aggregating input data and additional data. Aggregation of
 * input data and additional data is delegated to an {@link org.apache.camel.processor.aggregate.AggregationStrategy}
 * object.
 * 

* Uses a {@link org.apache.camel.PollingConsumer} to obtain the additional data as opposed to {@link Enricher} * that uses a {@link org.apache.camel.Producer}. * * @see Enricher */ public class PollEnricher extends ServiceSupport implements AsyncProcessor { private static final Logger LOG = LoggerFactory.getLogger(PollEnricher.class); private AggregationStrategy aggregationStrategy; private PollingConsumer consumer; private long timeout; private boolean aggregateOnException; /** * Creates a new {@link PollEnricher}. The default aggregation strategy is to * copy the additional data obtained from the enricher's resource over the * input data. When using the copy aggregation strategy the enricher * degenerates to a normal transformer. * * @param consumer consumer to resource endpoint. */ public PollEnricher(PollingConsumer consumer) { this(defaultAggregationStrategy(), consumer, 0); } /** * Creates a new {@link PollEnricher}. * * @param aggregationStrategy aggregation strategy to aggregate input data and additional data. * @param consumer consumer to resource endpoint. * @param timeout timeout in millis */ public PollEnricher(AggregationStrategy aggregationStrategy, PollingConsumer consumer, long timeout) { this.aggregationStrategy = aggregationStrategy; this.consumer = consumer; this.timeout = timeout; } public AggregationStrategy getAggregationStrategy() { return aggregationStrategy; } /** * Sets the aggregation strategy for this poll enricher. * * @param aggregationStrategy the aggregationStrategy to set */ public void setAggregationStrategy(AggregationStrategy aggregationStrategy) { this.aggregationStrategy = aggregationStrategy; } public long getTimeout() { return timeout; } /** * Sets the timeout to use when polling. *

* Use 0 to use receiveNoWait, * Use -1 to use receive with no timeout (which will block until data is available). * * @param timeout timeout in millis. */ public void setTimeout(long timeout) { this.timeout = timeout; } public boolean isAggregateOnException() { return aggregateOnException; } public void setAggregateOnException(boolean aggregateOnException) { this.aggregateOnException = aggregateOnException; } /** * Sets the default aggregation strategy for this poll enricher. */ public void setDefaultAggregationStrategy() { this.aggregationStrategy = defaultAggregationStrategy(); } public void process(Exchange exchange) throws Exception { AsyncProcessorHelper.process(this, exchange); } /** * Enriches the input data (exchange) by first obtaining * additional data from an endpoint represented by an endpoint * producer and second by aggregating input data and additional * data. Aggregation of input data and additional data is delegated to an * {@link org.apache.camel.processor.aggregate.AggregationStrategy} object set at construction time. If the * message exchange with the resource endpoint fails then no aggregation * will be done and the failed exchange content is copied over to the * original message exchange. * * @param exchange input data. */ @Override public boolean process(Exchange exchange, AsyncCallback callback) { try { preCheckPoll(exchange); } catch (Exception e) { exchange.setException(new CamelExchangeException("Error during pre poll check", exchange, e)); callback.done(true); return true; } Exchange resourceExchange; try { if (timeout < 0) { LOG.debug("Consumer receive: {}", consumer); resourceExchange = consumer.receive(); } else if (timeout == 0) { LOG.debug("Consumer receiveNoWait: {}", consumer); resourceExchange = consumer.receiveNoWait(); } else { LOG.debug("Consumer receive with timeout: {} ms. {}", timeout, consumer); resourceExchange = consumer.receive(timeout); } if (resourceExchange == null) { LOG.debug("Consumer received no exchange"); } else { LOG.debug("Consumer received: {}", resourceExchange); } } catch (Exception e) { exchange.setException(new CamelExchangeException("Error during poll", exchange, e)); callback.done(true); return true; } try { if (!isAggregateOnException() && (resourceExchange != null && resourceExchange.isFailed())) { // copy resource exchange onto original exchange (preserving pattern) copyResultsPreservePattern(exchange, resourceExchange); } else { prepareResult(exchange); // prepare the exchanges for aggregation ExchangeHelper.prepareAggregation(exchange, resourceExchange); // must catch any exception from aggregation Exchange aggregatedExchange = aggregationStrategy.aggregate(exchange, resourceExchange); if (aggregatedExchange != null) { // copy aggregation result onto original exchange (preserving pattern) copyResultsPreservePattern(exchange, aggregatedExchange); // handover any synchronization if (resourceExchange != null) { resourceExchange.handoverCompletions(exchange); } } } // set header with the uri of the endpoint enriched so we can use that for tracing etc if (exchange.hasOut()) { exchange.getOut().setHeader(Exchange.TO_ENDPOINT, consumer.getEndpoint().getEndpointUri()); } else { exchange.getIn().setHeader(Exchange.TO_ENDPOINT, consumer.getEndpoint().getEndpointUri()); } } catch (Throwable e) { exchange.setException(new CamelExchangeException("Error occurred during aggregation", exchange, e)); callback.done(true); return true; } callback.done(true); return true; } /** * Strategy to pre check polling. *

* Is currently used to prevent doing poll enrich from a file based endpoint when the current route also * started from a file based endpoint as that is not currently supported. * * @param exchange the current exchange */ protected void preCheckPoll(Exchange exchange) throws Exception { // noop } private static void prepareResult(Exchange exchange) { if (exchange.getPattern().isOutCapable()) { exchange.getOut().copyFrom(exchange.getIn()); } } private static AggregationStrategy defaultAggregationStrategy() { return new CopyAggregationStrategy(); } @Override public String toString() { return "PollEnrich[" + consumer + "]"; } protected void doStart() throws Exception { ServiceHelper.startServices(aggregationStrategy, consumer); } protected void doStop() throws Exception { ServiceHelper.stopServices(consumer, aggregationStrategy); } private static class CopyAggregationStrategy implements AggregationStrategy { public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { if (newExchange != null) { copyResultsPreservePattern(oldExchange, newExchange); } else { // if no newExchange then there was no message from the external resource // and therefore we should set an empty body to indicate this fact // but keep headers/attachments as we want to propagate those oldExchange.getIn().setBody(null); oldExchange.setOut(null); } return oldExchange; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy