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 */ 017 package org.apache.camel.model; 018 019 import java.util.ArrayList; 020 import java.util.Iterator; 021 import java.util.List; 022 import javax.xml.bind.annotation.XmlAccessType; 023 import javax.xml.bind.annotation.XmlAccessorType; 024 import javax.xml.bind.annotation.XmlAttribute; 025 import javax.xml.bind.annotation.XmlElement; 026 import javax.xml.bind.annotation.XmlElementRef; 027 import javax.xml.bind.annotation.XmlRootElement; 028 029 import org.apache.camel.Predicate; 030 import org.apache.camel.Processor; 031 import org.apache.camel.builder.ExpressionClause; 032 import org.apache.camel.processor.OnCompletionProcessor; 033 import org.apache.camel.processor.UnitOfWorkProcessor; 034 import org.apache.camel.spi.RouteContext; 035 036 /** 037 * Represents an XML <onCompletion/> element 038 * 039 * @version $Revision: 788766 $ 040 */ 041 @XmlRootElement(name = "onCompletion") 042 @XmlAccessorType(XmlAccessType.FIELD) 043 public class OnCompletionDefinition extends ProcessorDefinition<ProcessorDefinition> { 044 045 @XmlAttribute(required = false) 046 private Boolean onCompleteOnly = Boolean.FALSE; 047 @XmlAttribute(required = false) 048 private Boolean onFailureOnly = Boolean.FALSE; 049 @XmlElement(name = "onWhen", required = false) 050 private WhenDefinition onWhen; 051 @XmlElementRef 052 private List<ProcessorDefinition> outputs = new ArrayList<ProcessorDefinition>(); 053 054 public OnCompletionDefinition() { 055 } 056 057 @Override 058 public String toString() { 059 return "onCompletion[" + getOutputs() + "]"; 060 } 061 062 @Override 063 public String getShortName() { 064 return "onCompletion"; 065 } 066 067 @Override 068 public String getLabel() { 069 return "onCompletion"; 070 } 071 072 @Override 073 public Processor createProcessor(RouteContext routeContext) throws Exception { 074 Processor childProcessor = createOutputsProcessor(routeContext); 075 076 // wrap the on completion route in a unit of work processor 077 childProcessor = new UnitOfWorkProcessor(childProcessor); 078 079 Predicate when = null; 080 if (onWhen != null) { 081 when = onWhen.getExpression().createPredicate(routeContext); 082 } 083 084 if (onCompleteOnly && onFailureOnly) { 085 throw new IllegalArgumentException("Both onCompleteOnly and onFailureOnly cannot be true. Only one of them can be true. On node: " + this); 086 } 087 088 return new OnCompletionProcessor(childProcessor, onCompleteOnly, onFailureOnly, when); 089 } 090 091 /** 092 * Removes all existing {@link org.apache.camel.model.OnCompletionDefinition} from the defintion. 093 * <p/> 094 * This is used to let route scoped <tt>onCompletion</tt> overrule any global <tt>onCompletion</tt>. 095 * Hence we remove all existing as they are global. 096 * 097 * @param definition the parent defintion that is the route 098 */ 099 @SuppressWarnings("unchecked") 100 public void removeAllOnCompletionDefinition(ProcessorDefinition definition) { 101 for (Iterator<ProcessorDefinition> it = definition.getOutputs().iterator(); it.hasNext();) { 102 ProcessorDefinition out = it.next(); 103 if (out instanceof OnCompletionDefinition) { 104 it.remove(); 105 } 106 } 107 } 108 109 @Override 110 public ProcessorDefinition<? extends ProcessorDefinition> end() { 111 // pop parent block, as we added outself as block to parent when synchronized was defined in the route 112 getParent().popBlock(); 113 return super.end(); 114 } 115 116 /** 117 * Will only synchronize when the {@link org.apache.camel.Exchange} completed succesfully (no errors). 118 * 119 * @return the builder 120 */ 121 public OnCompletionDefinition onCompleteOnly() { 122 // must define return type as OutputDefinition and not this type to avoid end user being able 123 // to invoke onFailureOnly/onCompleteOnly more than once 124 setOnCompleteOnly(Boolean.TRUE); 125 setOnFailureOnly(Boolean.FALSE); 126 return this; 127 } 128 129 /** 130 * Will only synchronize when the {@link org.apache.camel.Exchange} ended with failure (exception or FAULT message). 131 * 132 * @return the builder 133 */ 134 public OnCompletionDefinition onFailureOnly() { 135 // must define return type as OutputDefinition and not this type to avoid end user being able 136 // to invoke onFailureOnly/onCompleteOnly more than once 137 setOnCompleteOnly(Boolean.FALSE); 138 setOnFailureOnly(Boolean.TRUE); 139 return this; 140 } 141 142 /** 143 * Sets an additional predicate that should be true before the onCompletion is triggered. 144 * <p/> 145 * To be used for fine grained controlling whether a completion callback should be invoked or not 146 * 147 * @param predicate predicate that determines true or false 148 * @return the builder 149 */ 150 public OnCompletionDefinition onWhen(Predicate predicate) { 151 setOnWhen(new WhenDefinition(predicate)); 152 return this; 153 } 154 155 /** 156 * Creates an expression to configure an additional predicate that should be true before the 157 * onCompletion is triggered. 158 * <p/> 159 * To be used for fine grained controlling whether a completion callback should be invoked or not 160 * 161 * @return the expression clause to configure 162 */ 163 public ExpressionClause<OnCompletionDefinition> onWhen() { 164 onWhen = new WhenDefinition(); 165 ExpressionClause<OnCompletionDefinition> clause = new ExpressionClause<OnCompletionDefinition>(this); 166 onWhen.setExpression(clause); 167 return clause; 168 } 169 170 171 public List<ProcessorDefinition> getOutputs() { 172 return outputs; 173 } 174 175 public void setOutputs(List<ProcessorDefinition> outputs) { 176 this.outputs = outputs; 177 } 178 179 public Boolean getOnCompleteOnly() { 180 return onCompleteOnly; 181 } 182 183 public void setOnCompleteOnly(Boolean onCompleteOnly) { 184 this.onCompleteOnly = onCompleteOnly; 185 } 186 187 public Boolean getOnFailureOnly() { 188 return onFailureOnly; 189 } 190 191 public void setOnFailureOnly(Boolean onFailureOnly) { 192 this.onFailureOnly = onFailureOnly; 193 } 194 195 public WhenDefinition getOnWhen() { 196 return onWhen; 197 } 198 199 public void setOnWhen(WhenDefinition onWhen) { 200 this.onWhen = onWhen; 201 } 202 203 }