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.component.saga;
018
019import org.apache.camel.AsyncCallback;
020import org.apache.camel.Exchange;
021import org.apache.camel.impl.DefaultAsyncProducer;
022import org.apache.camel.saga.CamelSagaService;
023import org.apache.camel.util.CamelContextHelper;
024
025/**
026 * A producer that finalizes the current saga.
027 */
028public class SagaProducer extends DefaultAsyncProducer {
029
030    private final boolean success;
031
032    private CamelSagaService camelSagaService;
033
034    public SagaProducer(SagaEndpoint endpoint, boolean success) {
035        super(endpoint);
036        this.success = success;
037
038        CamelSagaService sagaService = endpoint.getCamelContext().hasService(CamelSagaService.class);
039        if (sagaService == null) {
040            sagaService = CamelContextHelper.findByType(endpoint.getCamelContext(), CamelSagaService.class);
041        }
042        if (sagaService == null) {
043            throw new IllegalStateException("Cannot find saga service: saga producers can only be used within a saga");
044        }
045        this.camelSagaService = sagaService;
046    }
047
048    @Override
049    public boolean process(Exchange exchange, AsyncCallback callback) {
050        String currentSaga = exchange.getIn().getHeader(Exchange.SAGA_LONG_RUNNING_ACTION, String.class);
051        if (currentSaga == null) {
052            exchange.setException(new IllegalStateException("Current exchange is not bound to a saga context: cannot complete"));
053            callback.done(true);
054            return true;
055        }
056
057
058        camelSagaService.getSaga(currentSaga).thenApply(coordinator -> {
059            if (coordinator == null) {
060                throw new IllegalStateException("No coordinator found for saga id " + currentSaga);
061            }
062            return coordinator;
063        }).thenCompose(coordinator -> {
064            if (success) {
065                return coordinator.complete();
066            } else {
067                return coordinator.compensate();
068            }
069        }).whenComplete((res, ex) -> {
070            if (ex != null) {
071                exchange.setException(ex);
072            }
073            callback.done(false);
074        });
075        return false;
076    }
077
078}