/**
* Copyright 2015 Otto (GmbH & Co KG)
*
* 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 com.ottogroup.bi.spqr.pipeline;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import com.ottogroup.bi.spqr.exception.ComponentInitializationFailedException;
import com.ottogroup.bi.spqr.exception.QueueInitializationFailedException;
import com.ottogroup.bi.spqr.exception.RequiredInputMissingException;
import com.ottogroup.bi.spqr.metrics.MetricsHandler;
import com.ottogroup.bi.spqr.metrics.MetricsReporterFactory;
import com.ottogroup.bi.spqr.pipeline.component.MicroPipelineComponent;
import com.ottogroup.bi.spqr.pipeline.component.MicroPipelineComponentConfiguration;
import com.ottogroup.bi.spqr.pipeline.component.MicroPipelineComponentType;
import com.ottogroup.bi.spqr.pipeline.component.emitter.Emitter;
import com.ottogroup.bi.spqr.pipeline.component.emitter.EmitterRuntimeEnvironment;
import com.ottogroup.bi.spqr.pipeline.component.operator.DelayedResponseOperator;
import com.ottogroup.bi.spqr.pipeline.component.operator.DelayedResponseOperatorRuntimeEnvironment;
import com.ottogroup.bi.spqr.pipeline.component.operator.DelayedResponseOperatorWaitStrategy;
import com.ottogroup.bi.spqr.pipeline.component.operator.DirectResponseOperator;
import com.ottogroup.bi.spqr.pipeline.component.operator.DirectResponseOperatorRuntimeEnvironment;
import com.ottogroup.bi.spqr.pipeline.component.operator.MessageCountResponseWaitStrategy;
import com.ottogroup.bi.spqr.pipeline.component.operator.OperatorTriggeredWaitStrategy;
import com.ottogroup.bi.spqr.pipeline.component.operator.TimerBasedResponseWaitStrategy;
import com.ottogroup.bi.spqr.pipeline.component.source.Source;
import com.ottogroup.bi.spqr.pipeline.component.source.SourceRuntimeEnvironment;
import com.ottogroup.bi.spqr.pipeline.exception.UnknownWaitStrategyException;
import com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueue;
import com.ottogroup.bi.spqr.pipeline.queue.StreamingMessageQueueConfiguration;
import com.ottogroup.bi.spqr.pipeline.queue.chronicle.DefaultStreamingMessageQueue;
import com.ottogroup.bi.spqr.pipeline.queue.memory.InMemoryStreamingMessageQueue;
import com.ottogroup.bi.spqr.repository.ComponentRepository;
/**
* Manages the instantiation of {@link MicroPipeline micro pipelines}
* @author mnxfst
* @since Mar 6, 2015
*/
public class MicroPipelineFactory {
/** our faithful logging service ... ;-) */
private static final Logger logger = Logger.getLogger(MicroPipelineFactory.class);
/** reference towards component repository */
private final ComponentRepository componentRepository;
/** identifier of processing node this factory lives on */
private final String processingNodeId;
/**
* Initializes the factory using the provided input
* @param processingNodeId
* @param componentRepository
*/
public MicroPipelineFactory(final String processingNodeId, final ComponentRepository componentRepository) {
this.processingNodeId = processingNodeId;
this.componentRepository = componentRepository;
}
/**
* Instantiates the {@link MicroPipeline} according to the provided {@link MicroPipelineComponentConfiguration}
* @param cfg
* @param executorService
* @return
* @throws RequiredInputMissingException
* TODO validate micro pipeline for path from source to emitter
*/
public MicroPipeline instantiatePipeline(final MicroPipelineConfiguration cfg, final ExecutorService executorService) throws RequiredInputMissingException, QueueInitializationFailedException, ComponentInitializationFailedException {
///////////////////////////////////////////////////////////////////////////////////
// validate input
if(cfg == null)
throw new RequiredInputMissingException("Missing required configuration");
if(StringUtils.isBlank(cfg.getId()))
throw new RequiredInputMissingException("Missing required micro pipeline id");
if(cfg.getComponents() == null || cfg.getComponents().isEmpty())
throw new RequiredInputMissingException("Missing required component configurations");
if(cfg.getQueues() == null || cfg.getQueues().isEmpty())
throw new RequiredInputMissingException("Missing required queue configurations");
//
///////////////////////////////////////////////////////////////////////////////////
MetricRegistry.name(StringUtils.lowerCase(StringUtils.trim(this.processingNodeId)),
StringUtils.lowerCase(StringUtils.trim(cfg.getId())),
"queue",
"messages");
final MetricsHandler metricsHandler = new MetricsHandler();
MetricsReporterFactory.attachReporters(metricsHandler, cfg.getMetricsReporter());
///////////////////////////////////////////////////////////////////////////////////
// (1) initialize queues
// keep track of all ready created queue instances and create a new one for each configuration
// entry. if creation fails for any reason, all previously created queues are shut down and
// a queue initialization exception is thrown
MicroPipeline microPipeline = new MicroPipeline(StringUtils.lowerCase(StringUtils.trim(cfg.getId())), cfg);
for(final StreamingMessageQueueConfiguration queueConfig : cfg.getQueues()) {
String id = StringUtils.lowerCase(StringUtils.trim(queueConfig.getId()));
// a queue for that identifier already exists: kill the pipeline and tell the caller about it
if(microPipeline.hasQueue(id)) {
logger.error("queue initialization failed [id="+id+"]. Forcing shutdown of all queues.");
microPipeline.shutdown();
throw new QueueInitializationFailedException("Non-unique queue identifier found [id="+id+"]");
}
// try to instantiate the queue, if it fails .... shutdown queues initialized so far and throw an exception
try {
StreamingMessageQueue queueInstance = initializeQueue(queueConfig);
/////////////////////////////////////////////////////////////////////
// add queue message insertion and retrieval counters
if(queueConfig.isAttachInsertionCounter()) {
final Counter queueInsertionCounter = metricsHandler.counter(
MetricRegistry.name(
StringUtils.lowerCase(StringUtils.trim(this.processingNodeId)),
StringUtils.lowerCase(StringUtils.trim(cfg.getId())),
"queue",
id,
"messages",
"in"
), true
);
queueInstance.setMessageInsertionCounter(queueInsertionCounter);
if(logger.isDebugEnabled())
logger.debug("queue[id="+id+"]: message insertion counter attached");
}
if(queueConfig.isAttachRetrievalCounter()) {
final Counter queueRetrievalCounter = metricsHandler.counter(
MetricRegistry.name(
StringUtils.lowerCase(StringUtils.trim(this.processingNodeId)),
StringUtils.lowerCase(StringUtils.trim(cfg.getId())),
"queue",
id,
"messages",
"out"
), true
);
queueInstance.setMessageRetrievalCounter(queueRetrievalCounter);
if(logger.isDebugEnabled())
logger.debug("queue[id="+id+"]: message retrieval counter attached");
}
/////////////////////////////////////////////////////////////////////
microPipeline.addQueue(id, queueInstance);
logger.info("queue initialized[id="+id+"]");
} catch(Exception e) {
logger.error("queue initialization failed [id="+id+"]. Forcing shutdown of all queues.");
microPipeline.shutdown();
throw new QueueInitializationFailedException("Failed to initialize queue [id="+id+"]. Reason: " + e.getMessage(), e);
}
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// (2) initialize components
final Map<String, MicroPipelineComponent> components = new HashMap<>();
boolean sourceComponentFound = false;
boolean emitterComponentFound = false;
for(final MicroPipelineComponentConfiguration componentCfg : cfg.getComponents()) {
String id = StringUtils.lowerCase(StringUtils.trim(componentCfg.getId()));
// a component for that identifier already exists: kill the pipeline and tell the caller about it
if(microPipeline.hasComponent(id)) {
logger.error("component initialization failed [id="+id+", class="+componentCfg.getName()+", version="+componentCfg.getVersion()+"]. Forcing shutdown of all queues and components.");
microPipeline.shutdown();
throw new ComponentInitializationFailedException("Non-unique component identifier found [id="+id+"]");
}
// try to instantiate component, if it fails .... shutdown queues and components initialized so far and throw an exception
try {
MicroPipelineComponent component = initializeComponent(componentCfg, microPipeline.getQueues());
if(component.getType() == null) {
logger.error("component initialization failed [id="+id+", class="+componentCfg.getName()+", version="+componentCfg.getVersion()+"]. Type missing. Forcing shutdown of all queues and components.");
microPipeline.shutdown();
throw new ComponentInitializationFailedException("Failed to initialize component [id="+id+", class="+componentCfg.getName()+", version="+componentCfg.getVersion()+"]. Reason: type missing");
}
final StreamingMessageQueue fromQueue = microPipeline.getQueue(StringUtils.lowerCase(StringUtils.trim(componentCfg.getFromQueue())));
final StreamingMessageQueue toQueue = microPipeline.getQueue(StringUtils.lowerCase(StringUtils.trim(componentCfg.getToQueue())));
Counter messageCounter = null;
if(componentCfg.isAttachMessageCounter()) {
messageCounter = metricsHandler.counter(
MetricRegistry.name(
StringUtils.lowerCase(StringUtils.trim(this.processingNodeId)),
StringUtils.lowerCase(StringUtils.trim(cfg.getId())),
"component",
id,
"messages",
"count"
), true
);
}
switch(component.getType()) {
case SOURCE: {
SourceRuntimeEnvironment srcEnv = new SourceRuntimeEnvironment(this.processingNodeId, cfg.getId(), (Source)component, toQueue.getProducer());
///////////////////////////////////////////////
// attach monitoring components
if(messageCounter != null)
srcEnv.setMessageCounter(messageCounter);
///////////////////////////////////////////////
microPipeline.addSource(id, srcEnv);
sourceComponentFound = true;
break;
}
case DIRECT_RESPONSE_OPERATOR: {
DirectResponseOperatorRuntimeEnvironment directResponseEnv = new DirectResponseOperatorRuntimeEnvironment(this.processingNodeId, cfg.getId(), (DirectResponseOperator)component,
fromQueue.getConsumer(), toQueue.getProducer());
///////////////////////////////////////////////
// attach monitoring components
if(componentCfg.isAttachProcessingTimer()) {
final Timer messageProcessingTimer = metricsHandler.timer(
MetricRegistry.name(
StringUtils.lowerCase(StringUtils.trim(this.processingNodeId)),
StringUtils.lowerCase(StringUtils.trim(cfg.getId())),
"component",
id,
"messages",
"timer"
)
);
directResponseEnv.setMessageProcessingTimer(messageProcessingTimer);
}
if(messageCounter != null)
directResponseEnv.setMessageCounter(messageCounter);
///////////////////////////////////////////////
microPipeline.addOperator(id, directResponseEnv);
break;
}
case DELAYED_RESPONSE_OPERATOR: {
DelayedResponseOperatorRuntimeEnvironment delayedResponseEnv = new DelayedResponseOperatorRuntimeEnvironment(this.processingNodeId, cfg.getId(), (DelayedResponseOperator)component, getResponseWaitStrategy(componentCfg),
fromQueue.getConsumer(), toQueue.getProducer(), executorService);
///////////////////////////////////////////////
// attach monitoring components
if(messageCounter != null)
delayedResponseEnv.setMessageCounter(messageCounter);
///////////////////////////////////////////////
microPipeline.addOperator(id, delayedResponseEnv);
break;
}
case EMITTER: {
EmitterRuntimeEnvironment emitterEnv = new EmitterRuntimeEnvironment(this.processingNodeId, cfg.getId(), (Emitter)component, fromQueue.getConsumer());
///////////////////////////////////////////////
// attach monitoring components
if(componentCfg.isAttachProcessingTimer()) {
final Timer messageEmitDurationTimer = metricsHandler.timer(
MetricRegistry.name(
StringUtils.lowerCase(StringUtils.trim(this.processingNodeId)),
StringUtils.lowerCase(StringUtils.trim(cfg.getId())),
"component",
id,
"messages",
"emit",
"duration"
)
);
emitterEnv.setMessageEmitDurationTimer(messageEmitDurationTimer);
}
if(messageCounter != null)
emitterEnv.setMessageCounter(messageCounter);
///////////////////////////////////////////////
microPipeline.addEmitter(id, emitterEnv);
emitterComponentFound = true;
break;
}
}
components.put(id, component);
} catch(Exception e) {
logger.error("component initialization failed [id="+id+", class="+componentCfg.getName()+", version="+componentCfg.getVersion()+"]. Forcing shutdown of all queues and components. Reason: " + e.getMessage(), e);
microPipeline.shutdown();
throw new ComponentInitializationFailedException("Failed to initialize component [id="+id+", class="+componentCfg.getName()+", version="+componentCfg.getVersion()+"]. Reason: " + e.getMessage(), e);
}
}
if(!sourceComponentFound) {
microPipeline.shutdown();
throw new RequiredInputMissingException("Missing required source component");
}
if(!emitterComponentFound) {
microPipeline.shutdown();
throw new RequiredInputMissingException("Missing required emitter component");
}
///////////////////////////////////////////////////////////////////////////////////
microPipeline.attachComponentMetricsHandler(metricsHandler);
///////////////////////////////////////////////////////////////////////////////////
// (3) start components --> ramp up their runtime environments
for(String sourceId : microPipeline.getSources().keySet()) {
executorService.submit(microPipeline.getSources().get(sourceId));
if(logger.isDebugEnabled())
logger.debug("Started runtime environment for source [id="+sourceId+"]");
}
for(String directResponseOperatorId : microPipeline.getDirectResponseOperators().keySet()) {
executorService.submit(microPipeline.getDirectResponseOperators().get(directResponseOperatorId));
if(logger.isDebugEnabled())
logger.debug("Started runtime environment for direct response operator [id="+directResponseOperatorId+"]");
}
for(String delayedResponseOperatorId : microPipeline.getDelayedResponseOperators().keySet()) {
executorService.submit(microPipeline.getDelayedResponseOperators().get(delayedResponseOperatorId));
if(logger.isDebugEnabled())
logger.debug("Started runtime environment for delayed response operator [id="+delayedResponseOperatorId+"]");
}
for(String emitterId : microPipeline.getEmitters().keySet()) {
executorService.submit(microPipeline.getEmitters().get(emitterId));
if(logger.isDebugEnabled())
logger.debug("Started runtime environment for emitter [id="+emitterId+"]");
}
if(logger.isDebugEnabled())
logger.debug("Started stats collector");
//
///////////////////////////////////////////////////////////////////////////////////
return microPipeline;
}
/**
* Initializes a {@link StreamingMessageQueue} instance according to provided information.
* @param queueConfiguration+
* @return
* @throws RequiredInputMissingException
* @throws QueueInitializationFailedException
*/
protected StreamingMessageQueue initializeQueue(final StreamingMessageQueueConfiguration queueConfiguration) throws RequiredInputMissingException, QueueInitializationFailedException {
///////////////////////////////////////////////////////////////////////////////////
// validate input
if(queueConfiguration == null)
throw new RequiredInputMissingException("Missing required queue configuration");
if(StringUtils.isBlank(queueConfiguration.getId()))
throw new RequiredInputMissingException("Missing required queue identifier");
//
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// check properties for optional settings
boolean inMemoryQueue = false;
if(queueConfiguration.getProperties() != null && !queueConfiguration.getProperties().isEmpty()) {
String queueType = StringUtils.lowerCase(StringUtils.trim(queueConfiguration.getProperties().getProperty(StreamingMessageQueue.CFG_QUEUE_TYPE)));
inMemoryQueue = StringUtils.equalsIgnoreCase(queueType, InMemoryStreamingMessageQueue.CFG_QUEUE_TYPE);
}
///////////////////////////////////////////////////////////////////////////////////
if(inMemoryQueue) {
try {
StreamingMessageQueue queue = new InMemoryStreamingMessageQueue();
queue.setId(StringUtils.lowerCase(StringUtils.trim(queueConfiguration.getId())));
queue.initialize((queueConfiguration.getProperties() != null ? queueConfiguration.getProperties() : new Properties()));
return queue;
} catch(Exception e) {
throw new QueueInitializationFailedException("Failed to initialize streaming message queue '"+queueConfiguration.getId()+"'. Error: " + e.getMessage());
}
}
try {
StreamingMessageQueue queue = new DefaultStreamingMessageQueue();
queue.setId(StringUtils.lowerCase(StringUtils.trim(queueConfiguration.getId())));
queue.initialize((queueConfiguration.getProperties() != null ? queueConfiguration.getProperties() : new Properties()));
return queue;
} catch(Exception e) {
throw new QueueInitializationFailedException("Failed to initialize streaming message queue '"+queueConfiguration.getId()+"'. Error: " + e.getMessage());
}
}
/**
* Initializes a {@link MicroPipelineComponent} instance according to provided information
* @param componentConfiguration
* @return
* @throws RequiredInputMissingException
* @throws ComponentInitializationFailedException
* TODO test for settings that must be provided for type SOURCE
* TODO test for settings that must be provided for type EMITTER
* TODO test for settings that must be provided for type OPERATOR
* TODO test queue references in toQueues and fromQueues
* TODO test component instantiation
*/
protected MicroPipelineComponent initializeComponent(final MicroPipelineComponentConfiguration componentConfiguration, final Map<String, StreamingMessageQueue> queues) throws RequiredInputMissingException, ComponentInitializationFailedException {
///////////////////////////////////////////////////////////////////////////////////
// validate input
if(componentConfiguration == null)
throw new RequiredInputMissingException("Missing required component configuration");
if(StringUtils.isBlank(componentConfiguration.getId()))
throw new RequiredInputMissingException("Missing required component identifier");
if(componentConfiguration.getType() == null)
throw new RequiredInputMissingException("Missing required component type");
if(StringUtils.isBlank(componentConfiguration.getName()))
throw new RequiredInputMissingException("Missing required component name");
if(StringUtils.isBlank(componentConfiguration.getVersion()))
throw new RequiredInputMissingException("Missing required component version");
if(componentConfiguration.getSettings() == null)
throw new RequiredInputMissingException("Missing required component settings");
//
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// validate settings for components of type: SOURCE
if(componentConfiguration.getType() == MicroPipelineComponentType.SOURCE) {
if(StringUtils.isBlank(componentConfiguration.getToQueue()))
throw new RequiredInputMissingException("Missing required queues to write content to");
if(!queues.containsKey(StringUtils.lowerCase(StringUtils.trim(componentConfiguration.getToQueue()))))
throw new RequiredInputMissingException("Unknown destination queue '"+componentConfiguration.getToQueue()+"'");
////////////////////////////////////////////////////////////////////////////////////
// validate settings for components of type: DIRECT_RESPONSE_OPERATOR
} else if(componentConfiguration.getType() == MicroPipelineComponentType.DIRECT_RESPONSE_OPERATOR) {
if(StringUtils.isBlank(componentConfiguration.getToQueue()))
throw new RequiredInputMissingException("Missing required queues to write content to");
if(!queues.containsKey(StringUtils.lowerCase(StringUtils.trim(componentConfiguration.getToQueue()))))
throw new RequiredInputMissingException("Unknown destination queue '"+componentConfiguration.getToQueue()+"'");
if(StringUtils.isBlank(componentConfiguration.getFromQueue()))
throw new RequiredInputMissingException("Missing required queues to retrieve content from");
if(!queues.containsKey(StringUtils.lowerCase(StringUtils.trim(componentConfiguration.getFromQueue()))))
throw new RequiredInputMissingException("Unknown source queue '"+componentConfiguration.getFromQueue()+"'");
////////////////////////////////////////////////////////////////////////////////////
// validate settings for components of type: DELAYED_RESPONSE_OPERATOR
} else if(componentConfiguration.getType() == MicroPipelineComponentType.DELAYED_RESPONSE_OPERATOR) {
if(StringUtils.isBlank(componentConfiguration.getToQueue()))
throw new RequiredInputMissingException("Missing required queues to write content to");
if(!queues.containsKey(StringUtils.lowerCase(StringUtils.trim(componentConfiguration.getToQueue()))))
throw new RequiredInputMissingException("Unknown destination queue '"+componentConfiguration.getToQueue()+"'");
if(StringUtils.isBlank(componentConfiguration.getFromQueue()))
throw new RequiredInputMissingException("Missing required queues to retrieve content from");
if(!queues.containsKey(StringUtils.lowerCase(StringUtils.trim(componentConfiguration.getFromQueue()))))
throw new RequiredInputMissingException("Unknown source queue '"+componentConfiguration.getFromQueue()+"'");
if(StringUtils.isBlank(componentConfiguration.getSettings().getProperty(DelayedResponseOperator.CFG_WAIT_STRATEGY_NAME)))
throw new RequiredInputMissingException("Missing required settings for wait strategy applied to delayed response operator");
////////////////////////////////////////////////////////////////////////////////////
// validate settings for components of type: EMITTER
} else if(componentConfiguration.getType() == MicroPipelineComponentType.EMITTER) {
if(StringUtils.isBlank(componentConfiguration.getFromQueue()))
throw new RequiredInputMissingException("Missing required queues to retrieve content from");
if(!queues.containsKey(StringUtils.lowerCase(StringUtils.trim(componentConfiguration.getFromQueue()))))
throw new RequiredInputMissingException("Unknown source queue '"+componentConfiguration.getFromQueue()+"'");
}
//
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
// instantiate component class
try {
return this.componentRepository.newInstance(componentConfiguration.getId(), componentConfiguration.getName(), componentConfiguration.getVersion(), componentConfiguration.getSettings());
} catch(Exception e) {
throw new ComponentInitializationFailedException("Failed to initialize component '"+componentConfiguration.getId()+"'. Error: " + e.getMessage(), e);
}
//
////////////////////////////////////////////////////////////////////////////////////
}
/**
* Instantiates, initializes and returns the {@link DelayedResponseOperatorWaitStrategy} configured for the {@link DelayedResponseOperator}
* whose {@link MicroPipelineComponentConfiguration configuration} is provided when calling this method.
* @param delayedResponseOperatorCfg
* @return
*/
protected DelayedResponseOperatorWaitStrategy getResponseWaitStrategy(final MicroPipelineComponentConfiguration delayedResponseOperatorCfg) throws RequiredInputMissingException, UnknownWaitStrategyException {
/////////////////////////////////////////////////////////////////////////////////////
// validate input
if(delayedResponseOperatorCfg == null)
throw new RequiredInputMissingException("Missing required delayed response operator configuration");
if(delayedResponseOperatorCfg.getSettings() == null)
throw new RequiredInputMissingException("Missing required delayed response operator settings");
String strategyName = StringUtils.lowerCase(StringUtils.trim(delayedResponseOperatorCfg.getSettings().getProperty(DelayedResponseOperator.CFG_WAIT_STRATEGY_NAME)));
if(StringUtils.isBlank(strategyName))
throw new RequiredInputMissingException("Missing required strategy name expected as part of operator settings ('"+DelayedResponseOperator.CFG_WAIT_STRATEGY_NAME+"')");
//
/////////////////////////////////////////////////////////////////////////////////////
if(logger.isDebugEnabled())
logger.debug("Settings provided for strategy '"+strategyName+"'");
Properties strategyProperties = new Properties();
for(Enumeration<Object> keyEnumerator = delayedResponseOperatorCfg.getSettings().keys(); keyEnumerator.hasMoreElements();) {
String key = (String)keyEnumerator.nextElement();
if(StringUtils.startsWith(key, DelayedResponseOperator.CFG_WAIT_STRATEGY_SETTINGS_PREFIX)) {
String waitStrategyCfgKey = StringUtils.substring(key, StringUtils.lastIndexOf(key, ".") + 1);
if(StringUtils.isNoneBlank(waitStrategyCfgKey)) {
String waitStrategyCfgValue = delayedResponseOperatorCfg.getSettings().getProperty(key);
strategyProperties.put(waitStrategyCfgKey, waitStrategyCfgValue);
if(logger.isDebugEnabled())
logger.debug("\t" + waitStrategyCfgKey + ": " + waitStrategyCfgValue);
}
}
}
if(StringUtils.equalsIgnoreCase(strategyName, MessageCountResponseWaitStrategy.WAIT_STRATEGY_NAME)) {
MessageCountResponseWaitStrategy strategy = new MessageCountResponseWaitStrategy();
strategy.initialize(strategyProperties);
return strategy;
} else if(StringUtils.equalsIgnoreCase(strategyName, TimerBasedResponseWaitStrategy.WAIT_STRATEGY_NAME)) {
TimerBasedResponseWaitStrategy strategy = new TimerBasedResponseWaitStrategy();
strategy.initialize(strategyProperties);
return strategy;
} else if(StringUtils.equalsIgnoreCase(strategyName, OperatorTriggeredWaitStrategy.WAIT_STRATEGY_NAME)) {
OperatorTriggeredWaitStrategy strategy = new OperatorTriggeredWaitStrategy();
strategy.initialize(strategyProperties);
return strategy;
}
throw new UnknownWaitStrategyException("Unknown wait strategy '"+strategyName+"'");
}
}