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.reifier; 018 019import java.util.Map; 020import java.util.Optional; 021import java.util.TreeMap; 022 023import org.apache.camel.Endpoint; 024import org.apache.camel.Expression; 025import org.apache.camel.Processor; 026import org.apache.camel.Route; 027import org.apache.camel.RuntimeCamelException; 028import org.apache.camel.model.ProcessorDefinition; 029import org.apache.camel.model.SagaActionUriDefinition; 030import org.apache.camel.model.SagaDefinition; 031import org.apache.camel.model.SagaOptionDefinition; 032import org.apache.camel.processor.saga.SagaCompletionMode; 033import org.apache.camel.processor.saga.SagaProcessorBuilder; 034import org.apache.camel.processor.saga.SagaPropagation; 035import org.apache.camel.saga.CamelSagaService; 036import org.apache.camel.saga.CamelSagaStep; 037 038public class SagaReifier extends ProcessorReifier<SagaDefinition> { 039 040 public SagaReifier(Route route, ProcessorDefinition<?> definition) { 041 super(route, (SagaDefinition)definition); 042 } 043 044 @Override 045 public Processor createProcessor() throws Exception { 046 Optional<Endpoint> compensationEndpoint = Optional.ofNullable(definition.getCompensation()) 047 .map(SagaActionUriDefinition::getUri) 048 .map(this::resolveEndpoint); 049 050 Optional<Endpoint> completionEndpoint = Optional.ofNullable(definition.getCompletion()) 051 .map(SagaActionUriDefinition::getUri) 052 .map(this::resolveEndpoint); 053 054 Map<String, Expression> optionsMap = new TreeMap<>(); 055 if (definition.getOptions() != null) { 056 for (SagaOptionDefinition optionDef : definition.getOptions()) { 057 String optionName = optionDef.getOptionName(); 058 Expression expr = optionDef.getExpression(); 059 optionsMap.put(optionName, expr); 060 } 061 } 062 063 String timeout = definition.getTimeout() != null ? definition.getTimeout() : definition.getTimeoutInMilliseconds(); 064 CamelSagaStep step = new CamelSagaStep(compensationEndpoint, completionEndpoint, optionsMap, 065 Optional.ofNullable(parseDuration(timeout))); 066 067 SagaPropagation propagation = parse(SagaPropagation.class, definition.getPropagation()); 068 if (propagation == null) { 069 // default propagation mode 070 propagation = SagaPropagation.REQUIRED; 071 } 072 073 SagaCompletionMode completionMode = parse(SagaCompletionMode.class, definition.getCompletionMode()); 074 if (completionMode == null) { 075 // default completion mode 076 completionMode = SagaCompletionMode.defaultCompletionMode(); 077 } 078 079 Processor childProcessor = this.createChildProcessor(true); 080 CamelSagaService camelSagaService = findSagaService(); 081 082 camelSagaService.registerStep(step); 083 084 return new SagaProcessorBuilder().camelContext(camelContext).childProcessor(childProcessor) 085 .sagaService(camelSagaService).step(step) 086 .propagation(propagation).completionMode(completionMode).build(); 087 } 088 089 protected CamelSagaService findSagaService() { 090 CamelSagaService sagaService = definition.getSagaService(); 091 if (sagaService != null) { 092 return sagaService; 093 } 094 095 if (definition.getSagaServiceRef() != null) { 096 return mandatoryLookup(parseString(definition.getSagaServiceRef()), CamelSagaService.class); 097 } 098 099 sagaService = camelContext.hasService(CamelSagaService.class); 100 if (sagaService != null) { 101 return sagaService; 102 } 103 104 sagaService = findSingleByType(CamelSagaService.class); 105 if (sagaService != null) { 106 return sagaService; 107 } 108 109 throw new RuntimeCamelException("Cannot find a CamelSagaService"); 110 } 111 112}