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