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.bam; 018 019 import java.util.ArrayList; 020 import java.util.List; 021 022 import org.apache.camel.Endpoint; 023 import org.apache.camel.Processor; 024 import org.apache.camel.Route; 025 import org.apache.camel.bam.model.ActivityDefinition; 026 import org.apache.camel.bam.model.ProcessDefinition; 027 import org.apache.camel.bam.model.ProcessInstance; 028 import org.apache.camel.bam.processor.ActivityMonitorEngine; 029 import org.apache.camel.bam.processor.JpaBamProcessor; 030 import org.apache.camel.bam.rules.ProcessRules; 031 import org.apache.camel.builder.RouteBuilder; 032 033 import org.springframework.orm.jpa.JpaTemplate; 034 import org.springframework.transaction.TransactionStatus; 035 import org.springframework.transaction.support.TransactionCallbackWithoutResult; 036 import org.springframework.transaction.support.TransactionTemplate; 037 038 import static org.apache.camel.util.ObjectHelper.notNull; 039 040 /** 041 * A builder of a process definition 042 * 043 * @version $Revision: $ 044 */ 045 public abstract class ProcessBuilder extends RouteBuilder { 046 private static int processCounter; 047 private JpaTemplate jpaTemplate; 048 private final TransactionTemplate transactionTemplate; 049 private final String processName; 050 private List<ActivityBuilder> activityBuilders = new ArrayList<ActivityBuilder>(); 051 private Class entityType = ProcessInstance.class; 052 private ProcessRules processRules = new ProcessRules(); 053 private ProcessDefinition processDefinition; 054 055 protected ProcessBuilder(JpaTemplate jpaTemplate, TransactionTemplate transactionTemplate) { 056 this(jpaTemplate, transactionTemplate, createProcessName()); 057 } 058 059 protected ProcessBuilder(JpaTemplate jpaTemplate, TransactionTemplate transactionTemplate, String processName) { 060 this.jpaTemplate = jpaTemplate; 061 this.transactionTemplate = transactionTemplate; 062 this.processName = processName; 063 } 064 065 protected static synchronized String createProcessName() { 066 return "Process-" + (++processCounter); 067 } 068 069 public ActivityBuilder activity(String endpointUri) { 070 return activity(endpoint(endpointUri)); 071 } 072 073 public ActivityBuilder activity(Endpoint endpoint) { 074 ActivityBuilder answer = new ActivityBuilder(this, endpoint); 075 activityBuilders.add(answer); 076 return answer; 077 } 078 079 /** 080 * Sets the process entity type used to perform state management 081 */ 082 public ProcessBuilder entityType(Class entityType) { 083 this.entityType = entityType; 084 return this; 085 } 086 087 public Processor createActivityProcessor(ActivityBuilder activityBuilder) { 088 notNull(jpaTemplate, "jpaTemplate"); 089 transactionTemplate.execute(new TransactionCallbackWithoutResult() { 090 protected void doInTransactionWithoutResult(TransactionStatus status) { 091 processRules.setProcessDefinition(getProcessDefinition()); 092 } 093 }); 094 return new JpaBamProcessor(getTransactionTemplate(), getJpaTemplate(), activityBuilder.getCorrelationExpression(), activityBuilder.getActivityRules(), getEntityType()); 095 } 096 097 // Properties 098 // ----------------------------------------------------------------------- 099 public List<ActivityBuilder> getActivityBuilders() { 100 return activityBuilders; 101 } 102 103 public Class getEntityType() { 104 return entityType; 105 } 106 107 public JpaTemplate getJpaTemplate() { 108 return jpaTemplate; 109 } 110 111 public void setJpaTemplate(JpaTemplate jpaTemplate) { 112 this.jpaTemplate = jpaTemplate; 113 } 114 115 public TransactionTemplate getTransactionTemplate() { 116 return transactionTemplate; 117 } 118 119 public ProcessRules getProcessRules() { 120 return processRules; 121 } 122 123 public String getProcessName() { 124 return processName; 125 } 126 127 public ProcessDefinition getProcessDefinition() { 128 if (processDefinition == null) { 129 processDefinition = findOrCreateProcessDefinition(); 130 } 131 return processDefinition; 132 } 133 134 public void setProcessDefinition(ProcessDefinition processDefinition) { 135 this.processDefinition = processDefinition; 136 } 137 138 // Implementation methods 139 // ------------------------------------------------------------------------- 140 protected void populateRoutes(List<Route> routes) throws Exception { 141 boolean first = true; 142 for (ActivityBuilder builder : activityBuilders) { 143 Route route = builder.createRoute(); 144 if (first) { 145 route.getServices().add(new ActivityMonitorEngine(getJpaTemplate(), getTransactionTemplate(), getProcessRules())); 146 first = false; 147 } 148 routes.add(route); 149 } 150 } 151 152 // Implementation methods 153 // ------------------------------------------------------------------------- 154 public ActivityDefinition findOrCreateActivityDefinition(String activityName) { 155 ProcessDefinition definition = getProcessDefinition(); 156 List<ActivityDefinition> list = jpaTemplate.find("select x from " + ActivityDefinition.class.getName() + " x where x.processDefinition = ?1 and x.name = ?2", definition, activityName); 157 if (!list.isEmpty()) { 158 return list.get(0); 159 } else { 160 ActivityDefinition answer = new ActivityDefinition(); 161 answer.setName(activityName); 162 answer.setProcessDefinition(ProcessDefinition.getRefreshedProcessDefinition(jpaTemplate, definition)); 163 jpaTemplate.persist(answer); 164 return answer; 165 } 166 } 167 168 protected ProcessDefinition findOrCreateProcessDefinition() { 169 List<ProcessDefinition> list = jpaTemplate.find("select x from " + ProcessDefinition.class.getName() + " x where x.name = ?1", processName); 170 if (!list.isEmpty()) { 171 return list.get(0); 172 } else { 173 ProcessDefinition answer = new ProcessDefinition(); 174 answer.setName(processName); 175 jpaTemplate.persist(answer); 176 return answer; 177 } 178 } 179 }