Package org.activiti.camel

Source Code of org.activiti.camel.CamelBehavior

/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.activiti.camel;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.pvm.PvmProcessDefinition;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.impl.DefaultExchange;
import org.apache.commons.lang3.StringUtils;

/**
* This abstract class takes the place of the now-deprecated CamelBehaviour class (which can still be used for legacy compatibility)
* and significantly improves on its flexibility. Additional implementations can be created that change the way in which Activiti
* interacts with Camel per your specific needs.
*
* Three out-of-the-box implementations of CamelBehavior are provided:
*   (1) CamelBehaviorDefaultImpl: Works just like CamelBehaviour does; copies variables into and out of Camel as or from properties.
*   (2) CamelBehaviorBodyAsMapImpl: Works by copying variables into and out of Camel using a Map<String,Object> object in the body.
*   (3) CamelBehaviorCamelBodyImpl: Works by copying a single variable value into Camel as a String body and copying the Camel
*      body into that same Activiti variable. The variable in Activiti must be named "camelBody".
*
* The chosen implementation should be set within your ProcessEngineConfiguration. To specify the implementation using Spring, include
* the following line in your configuration file as part of the properties for "org.activiti.spring.SpringProcessEngineConfiguration":
*
*   <property name="camelBehaviorClass" value="org.activiti.camel.impl.CamelBehaviorCamelBodyImpl"/>
*
* Note also that the manner in which variables are copied to Activiti from Camel has changed. It will always copy Camel
* properties to the Activiti variable set; they can safely be ignored, of course, if not required. It will conditionally
* copy the Camel body to the "camelBody" variable if it is of type java.lang.String, OR it will copy the Camel body to
* individual variables within Activiti if it is of type Map<String,Object>.
*
* @author Ryan Johnston (@rjfsu), Tijs Rademakers, Saeid Mirzaei
* @version 5.12
*/
public abstract class CamelBehavior extends AbstractBpmnActivityBehavior implements ActivityBehavior {

  private static final long serialVersionUID = 1L;
  protected Expression camelContext;
  protected CamelContext camelContextObj;
  protected SpringProcessEngineConfiguration springConfiguration;
 
  protected abstract void setPropertTargetVariable(ActivitiEndpoint endpoint);
 
  public enum TargetType {
        BODY_AS_MAP, BODY, PROPERTIES
     

  protected TargetType toTargetType=null;
 
  protected void updateTargetVariables(ActivitiEndpoint endpoint) {
    toTargetType = null;
    if (endpoint.isCopyVariablesToBodyAsMap())
      toTargetType = TargetType.BODY_AS_MAP;
    else if (endpoint.isCopyCamelBodyToBody())
      toTargetType = TargetType.BODY;
    else if (endpoint.isCopyVariablesToProperties())
      toTargetType = TargetType.PROPERTIES;

    if (toTargetType == null)
      setPropertTargetVariable(endpoint);
  }
 
  protected void copyVariables(Map<String, Object> variables, Exchange exchange, ActivitiEndpoint endpoint) {
    switch (toTargetType) {
    case BODY_AS_MAP:
      copyVariablesToBodyAsMap(variables, exchange);
      break;

    case BODY:
      copyVariablesToBody(variables, exchange);
      break;

    case PROPERTIES:
      copyVariablesToProperties(variables, exchange);
    }
  }
 
  public void execute(ActivityExecution execution) throws Exception {
    setAppropriateCamelContext(execution);
   
    final ActivitiEndpoint endpoint = createEndpoint(execution);
    final Exchange exchange = createExchange(execution, endpoint);
   
    if (isASync(execution)) {

      FutureTask<Void> future = new FutureTask<Void>(new Callable<Void>() {
          public Void call() {
            try {
              endpoint.process(exchange);
            } catch (Exception e) { 
              throw new RuntimeException("Unable to process camel endpint asynchronously.");
            }
            return null;
          }
      });
      ExecutorService executor = Executors.newSingleThreadExecutor();
      executor.submit(future);
      handleCamelException(exchange);

    } else {
      endpoint.process(exchange);
      handleCamelException(exchange);
      execution.setVariables(ExchangeUtils.prepareVariables(exchange, endpoint));
    }
 
    leave(execution);
  }

  protected ActivitiEndpoint createEndpoint(ActivityExecution execution) {
    String uri = "activiti://" + getProcessDefinitionKey(execution) + ":" + execution.getActivity().getId();
    return getEndpoint(uri);
  }

  protected ActivitiEndpoint getEndpoint(String key) {
    for (Endpoint e : camelContextObj.getEndpoints()) {
      if (e.getEndpointKey().equals(key) && (e instanceof ActivitiEndpoint)) {
        return (ActivitiEndpoint) e;
      }
    }
    throw new RuntimeException("Activiti endpoint not defined for " + key);   
  }

  protected Exchange createExchange(ActivityExecution activityExecution, ActivitiEndpoint endpoint) {
    Exchange ex = new DefaultExchange(camelContextObj);
    ex.setProperty(ActivitiProducer.PROCESS_ID_PROPERTY, activityExecution.getProcessInstanceId());
    Map<String, Object> variables = activityExecution.getVariables();
    updateTargetVariables(endpoint);
    copyVariables(variables, ex, endpoint);
    return ex;
  }
 
  protected void handleCamelException(Exchange exchange) {
    Exception camelException = exchange.getException();
    boolean notHandledByCamel = exchange.isFailed() && camelException != null;
    if (notHandledByCamel) {
      throw new ActivitiException("Unhandled exception on camel route", camelException);
    }
  }
 
  protected void copyVariablesToProperties(Map<String, Object> variables, Exchange exchange) {
    for (Map.Entry<String, Object> var : variables.entrySet()) {
      exchange.setProperty(var.getKey(), var.getValue());
    }
  }
 
  protected void copyVariablesToBodyAsMap(Map<String, Object> variables, Exchange exchange) {
    exchange.getIn().setBody(new HashMap<String,Object>(variables));
  }
 
  protected void copyVariablesToBody(Map<String, Object> variables, Exchange exchange) {
    Object camelBody = variables.get(ExchangeUtils.CAMELBODY);
    if(camelBody != null) {
      exchange.getIn().setBody(camelBody);
    }
  }

  protected String getProcessDefinitionKey(ActivityExecution execution) {
    PvmProcessDefinition processDefinition = execution.getActivity().getProcessDefinition();
    return processDefinition.getKey();
  }
 
  protected boolean isASync(ActivityExecution execution) {
     return execution.getActivity().isAsync();
  }
 
  protected void setAppropriateCamelContext(ActivityExecution execution) {
    //Check to see if the springConfiguration has been set. If not, set it.
    if (springConfiguration == null) {
      //Get the ProcessEngineConfiguration object.
      ProcessEngineConfiguration engineConfiguration = Context.getProcessEngineConfiguration();
         
      //Convert it to a SpringProcessEngineConfiguration. If this doesn't work, throw a RuntimeException.
      // (ActivitiException extends RuntimeException.)
      try {
        springConfiguration = (SpringProcessEngineConfiguration) engineConfiguration;
      } catch (Exception e) {
        throw new ActivitiException("Expecting a SpringProcessEngineConfiguration for the Activiti Camel module.", e);
      }
    }
         
    //Get the appropriate String representation of the CamelContext object from ActivityExecution (if available).
    String camelContextValue = getStringFromField(camelContext, execution);
         
    //If the String representation of the CamelContext object from ActivityExecution is empty, use the default.
    if (StringUtils.isEmpty(camelContextValue) && camelContextObj != null) {
      //No processing required. No custom CamelContext & the default is already set.
    }
    else {
      if (StringUtils.isEmpty(camelContextValue) && camelContextObj == null) {
        camelContextValue = springConfiguration.getDefaultCamelContext();
      }
     
      //Get the CamelContext object and set the super's member variable.
      Object ctx = springConfiguration.getApplicationContext().getBean(camelContextValue);
      if (ctx == null || ctx instanceof CamelContext == false) {
        throw new ActivitiException("Could not find CamelContext named " + camelContextValue + ".");
      }
      camelContextObj = (CamelContext)ctx;
    }
  }
 
  protected String getStringFromField(Expression expression, DelegateExecution execution) {
    if (expression != null) {
      Object value = expression.getValue(execution);
      if (value != null) {
        return value.toString();
      }
    }
    return null;
  }

  public void setCamelContext(Expression camelContext) {
    this.camelContext = camelContext;
  }
}
TOP

Related Classes of org.activiti.camel.CamelBehavior

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.