Class Adapter
- All Implemented Interfaces:
Closeable,AutoCloseable,FrankElement,HasApplicationContext,HasName,IConfigurable,IScopeProvider,ManagableLifecycle,NameAware,ConfigurableLifecycle,org.springframework.beans.factory.Aware,org.springframework.beans.factory.BeanFactory,org.springframework.beans.factory.HierarchicalBeanFactory,org.springframework.beans.factory.InitializingBean,org.springframework.beans.factory.ListableBeanFactory,org.springframework.beans.factory.NamedBean,org.springframework.beans.factory.support.BeanDefinitionRegistry,org.springframework.context.ApplicationContext,org.springframework.context.ApplicationContextAware,org.springframework.context.ApplicationEventPublisher,org.springframework.context.ConfigurableApplicationContext,org.springframework.context.Lifecycle,org.springframework.context.MessageSource,org.springframework.context.Phased,org.springframework.context.SmartLifecycle,org.springframework.core.AliasRegistry,org.springframework.core.env.EnvironmentCapable,org.springframework.core.io.ResourceLoader,org.springframework.core.io.support.ResourcePatternResolver
Receivers as well as the PipeLine and statistics.
The Adapter is the class that is responsible for configuring, initializing and
accessing/activating Receivers, Pipelines, statistics etc.
An Adapter receives a specific type of messages and processes them. It has Receivers
that receive the messages and a PipeLine that transforms the incoming messages. Each adapter is part of a Configuration.
If an adapter can receive its messages through multiple channels (e.g. RESTful HTTP requests, incoming files, etc),
each channel appears as a separate Receiver nested in the adapter. Each Receiver is also responsible
for dealing with
the result of its received messages; the result is the output of the PipeLine. The result
consists of the transformed message and a state. The Frank!Framework distinguishes between exit states
SUCCESS and ERROR. There is also a state REJECTED for messages that are not accepted by the Frank!Framework
and that are not processed by the PipeLine. If the exit state is ERROR, the result message may
not be usable by the calling system. This can be fixed by adding an
errorMessageFormatter that formats the result message if the state is ERROR.
Adapters gather statistics about the messages they process.
Adapters can process messages in parallel. They are thread-safe.
Error Handling in Adapters
When an exception occurs in the execution of the Adapter pipeline, you can configure the listener to return
a formatter error message using an ErrorMessageFormatter or to throw an exception (see RequestReplyListener.setOnException(RequestReplyListener.ExceptionHandlingMethod),
RequestReplyListener.setOnException(RequestReplyListener.ExceptionHandlingMethod), RequestReplyListener.setOnException(RequestReplyListener.ExceptionHandlingMethod)).
Listeners that do not return a reply will roll back the transaction (if any) and after a maximum number of retries, move the message to an error storage.
When one adapter calls another adapter using a FrankSender or
IbisLocalSender, and the adapter returns a formatted error message,
the SenderPipe can either use the exception forward or pick a forward based on the pipeline exitCode.
The default exitCode in case of an error is 500, but you can set a different exitCode
in the PipeLineSession, for instance by passing it as a NumberParameter to an
ExceptionPipe. The exitCode has to be a numerical value.
Error Handling Example 1 - Call Sub-Adapter Direct
This example uses aFrankSender to call another adapter without the overhead of
a listener. The callee sets an exitCode on error, so the caller can choose a different path.
Calling Adapter:
<Adapter name="ErrorHandling-Example-1">
<Receiver>
<!-- Listener omitted, not relevant for the example -->
</Receiver>
<Pipeline>
<Exits>
<Exit name="done" state="SUCCESS"/>
<Exit name="error" state="ERROR"/>
</Exits>
<SenderPipe name="Call Subadapter To Test">
<FrankSender scope="ADAPTER" target="Validate-Message"/>
<Forward name="42" path="error"/>
</SenderPipe>
<DataSonnetPipe name="Extract Name" styleSheetName="stylesheets/buildResponse.jsonnet"/>
</Pipeline>
</Adapter>
Sub Adapter:
<Adapter name="Validate-Message">
<DataSonnetErrorMessageFormatter styleSheetName="stylesheets/BuildErrorMessage.jsonnet"/>
<Pipeline>
<Exits>
<Exit name="done" state="SUCCESS"/>
<Exit name="error" state="ERROR"/>
</Exits>
<!-- For simplicity of the example we assume the input message is valid if it contains a single item in an array 'results' -->
<SwitchPipe name="Check Success" jsonPathExpression='concat("result-count=", $.results.length())' notFoundForwardName="result-count-too-many"/>
<!-- For simplicity we return the input unmodified in case of success. A realistic adapter might fetch a message remotely and return that after validations -->
<EchoPipe name="result-count=1" getInputFromSessionKey="originalMessage">
<Forward name="success" path="done"/>
</EchoPipe>
<!-- No results: use this ExceptionPipe to pass parameters to the error message formatter and set an exitCode -->
<ExceptionPipe name="result-count=0">
<!-- When we do not set exitCode it will default to 500 when an adapter ends with an exception -->
<NumberParam name="exitCode" value="42"/>
<NumberParam name="errorCode" value="-1"/>
<Param name="errorMessage" value="No results found"/>
</ExceptionPipe>
<!-- Too many results: use this ExceptionPipe to pass different parameters to the error message formatter and set an exitCode -->
<ExceptionPipe name="result-count-too-many">
<NumberParam name="exitCode" value="42"/>
<NumberParam name="errorCode" value="2"/>
<Param name="errorMessage" value="Too many results found, expected only single result"/>
</ExceptionPipe>
</Pipeline>
</Adapter>
Error Handling Example 2 - Call Sub-Adapter via a Listener
This example uses aFrankSender to call another adapter via a FrankListener.
Instead of a FrankSender / FrankListener, an IbisLocalSender / JavaListener
pair can also be used to the same effect.
In this example we use the exception forward on the SenderPipe to take the error-path after
an error result, but we could also use the exitCode instead as in the previous example. When
a sub-adapter ends with a state ERROR, and the calling SenderPipe does not have a forward
for the exitCode returned from the sub-adapter, but does have an exception forward, then
the exception forward is chosen.
Calling Adapter:
<Adapter name="ErrorHandling-Example-2">
<Receiver>
<!-- Listener omitted, not relevant for the example -->
</Receiver>
<Pipeline>
<Exits>
<Exit name="done" state="SUCCESS"/>
<Exit name="error" state="ERROR"/>
</Exits>
<SenderPipe name="Call Subadapter To Test">
<FrankSender scope="LISTENER" target="Validate-Message"/>
<Forward name="exception" path="error"/>
</SenderPipe>
<DataSonnetPipe name="Extract Name" styleSheetName="stylesheets/buildResponse.jsonnet"/>
</Pipeline>
</Adapter>
Sub Adapter:
<Adapter name="Validate-Message">
<Receiver>
<!-- We need to set onException="format_and_return" to make sure error message is returned instead of an exception thrown -->
<FrankListener name="Validate-Message" onException="format_and_return"/>
</Receiver>
<DataSonnetErrorMessageFormatter styleSheetName="stylesheets/BuildErrorMessage.jsonnet"/>
<Pipeline>
<Exits>
<Exit name="done" state="SUCCESS"/>
<Exit name="error" state="ERROR"/>
</Exits>
<!-- For simplicity of the example we assume the input message is valid if it contains a single item in an array 'results' -->
<SwitchPipe name="Check Success" jsonPathExpression='concat("result-count=", $.results.length())' notFoundForwardName="result-count-too-many"/>
<!-- For simplicity we return the input unmodified in case of success. A realistic adapter might fetch a message remotely and return that after validations -->
<EchoPipe name="result-count=1" getInputFromSessionKey="originalMessage">
<Forward name="success" path="done"/>
</EchoPipe>
<!-- No results: use this ExceptionPipe to pass parameters to the error message formatter -->
<ExceptionPipe name="result-count=0">
<NumberParam name="errorCode" value="-1"/>
<Param name="errorMessage" value="No results found"/>
</ExceptionPipe>
<!-- Too many results: use this ExceptionPipe to pass different parameters to the error message formatter -->
<ExceptionPipe name="result-count-too-many">
<NumberParam name="errorCode" value="2"/>
<Param name="errorMessage" value="Too many results found, expected only single result"/>
</ExceptionPipe>
</Pipeline>
</Adapter>
- Author:
- Niels Meijer
-
Nested Class Summary
Nested ClassesNested classes/interfaces inherited from class org.springframework.core.io.DefaultResourceLoader
org.springframework.core.io.DefaultResourceLoader.ClassPathContextResource -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected org.apache.logging.log4j.Loggerstatic final Stringstatic final StringFields inherited from class org.springframework.context.support.AbstractApplicationContext
APPLICATION_EVENT_MULTICASTER_BEAN_NAME, LIFECYCLE_PROCESSOR_BEAN_NAME, logger, MESSAGE_SOURCE_BEAN_NAMEFields inherited from interface org.springframework.beans.factory.BeanFactory
FACTORY_BEAN_PREFIX, FACTORY_BEAN_PREFIX_CHARFields inherited from interface org.springframework.context.ConfigurableApplicationContext
APPLICATION_STARTUP_BEAN_NAME, BOOTSTRAP_EXECUTOR_BEAN_NAME, CONFIG_LOCATION_DELIMITERS, CONVERSION_SERVICE_BEAN_NAME, ENVIRONMENT_BEAN_NAME, LOAD_TIME_WEAVER_BEAN_NAME, SHUTDOWN_HOOK_THREAD_NAME, SYSTEM_ENVIRONMENT_BEAN_NAME, SYSTEM_PROPERTIES_BEAN_NAMEFields inherited from interface org.springframework.core.io.ResourceLoader
CLASSPATH_URL_PREFIXFields inherited from interface org.springframework.core.io.support.ResourcePatternResolver
CLASSPATH_ALL_URL_PREFIXFields inherited from interface org.springframework.context.SmartLifecycle
DEFAULT_PHASE -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidsend an error to the log and to the messagekeeper of the adaptervoidaddReceiver(Receiver<?> receiver) Receives incoming messages.voidprotected final StringvoidInstruct the adapter to configure itself.voidconfigureReceiver(Receiver<?> receiver) formatErrorMessage(String errorMessage, Throwable t, Message originalMessage, PipeLineSession session, HasName objectInError) org.springframework.context.ApplicationContextlonggetLastExitIsTimeoutDate(String pipeName) retrieve the date and time of the last message.getName()doubleThe number of messages for which processing ended unsuccessfully.intdoubleTotal of messages processedlong[]intgetPhase()Receiver<?> getReceiverByName(String receiverName) Returns the RunState of the object.return the date and time since active Creation date: (19-02-2003 12:16:53)voidThe number of messages for which processing ended unsuccessfully.protected voidbooleanBy default these beans are not started.booleanVerifies if this object needs to be started or stopped.voidlogToMessageLogWithMessageContentsOrSize(org.apache.logging.log4j.Level level, String logMessage, String dataPrefix, Message data) processMessageDirect(String messageId, Message message, PipeLineSession pipeLineSession) Direct call to the Adapter PipeLine, foregoing any listeners and receivers.processMessageWithExceptions(String messageId, Message message, PipeLineSession pipeLineSession) This method does the real processing of messages by the adapter.voidpublishEvent(org.springframework.context.ApplicationEvent event) protected voidregisterBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory beanFactory) Enables theAutowiredannotation andConfigurationAwareobjects.voidsetApplicationContext(org.springframework.context.ApplicationContext applicationContext) voidsetAutoStart(boolean autoStart) AutoStart indicates that the adapter should be started when the configuration is started.voidsetDescription(String description) some functional description of theAdaptervoidsetErrorMessageFormatter(IErrorMessageFormatter errorMessageFormatter) Set anErrorMessageFormatterthat will be used to format an error-message when an exception occurs in this adapter.voidsetLastExitState(String pipeName, long lastExitStateDate, String lastExitState) voidsetMessageKeeperSize(int size) number of message displayed in ibisconsolevoidsetMsgLogHidden(boolean b) If set totrue, the length of the message is shown in the msg log instead of the content of the messagevoidDefines behaviour for logging messages.voidname of the adaptervoidsetPipeLine(PipeLine pipeline) ThePipeLine.voidsetReplaceNullMessage(boolean b) Iftruea null message is replaced by an empty messagevoidsetRequestReplyLogging(boolean requestReplyLogging) Deprecated.voidsetTargetDesignDocument(String targetDesignDocument) An optional field for documentation-purposes where you can add a reference to the design-document used for the design of this adapter.voidstart()Start the adapter.voidstop()This method should ideally not be called directly.voidStop theAdapterand close all elements like receivers, Pipeline, pipes etc.toString()voidprotected voidsend a warning to the log and to the messagekeeper of the adapterMethods inherited from class org.springframework.context.support.GenericApplicationContext
cancelRefresh, closeBeanFactory, getAutowireCapableBeanFactory, getBeanDefinition, getBeanFactory, getClassLoader, getDefaultListableBeanFactory, getResource, getResources, isAlias, isBeanDefinitionOverridable, isBeanNameInUse, refreshBeanFactory, refreshForAotProcessing, registerAlias, registerBean, registerBean, registerBean, registerBean, registerBean, registerBean, registerBeanDefinition, removeAlias, removeBeanDefinition, setAllowBeanDefinitionOverriding, setAllowCircularReferences, setApplicationStartup, setClassLoader, setParent, setResourceLoaderMethods inherited from class org.springframework.context.support.AbstractApplicationContext
addApplicationListener, addBeanFactoryPostProcessor, assertBeanFactoryActive, clearResourceCaches, close, containsBean, containsBeanDefinition, containsLocalBean, createEnvironment, destroyBeans, doClose, findAllAnnotationsOnBean, findAnnotationOnBean, findAnnotationOnBean, finishBeanFactoryInitialization, finishRefresh, getAliases, getApplicationListeners, getApplicationName, getApplicationStartup, getBean, getBean, getBean, getBean, getBean, getBeanDefinitionCount, getBeanDefinitionNames, getBeanFactoryPostProcessors, getBeanNamesForAnnotation, getBeanNamesForType, getBeanNamesForType, getBeanNamesForType, getBeanNamesForType, getBeanProvider, getBeanProvider, getBeanProvider, getBeanProvider, getBeansOfType, getBeansOfType, getBeansWithAnnotation, getDisplayName, getEnvironment, getId, getInternalParentBeanFactory, getInternalParentMessageSource, getMessage, getMessage, getMessage, getParent, getParentBeanFactory, getResourcePatternResolver, getStartupDate, getType, getType, initApplicationEventMulticaster, initMessageSource, initPropertySources, invokeBeanFactoryPostProcessors, isActive, isClosed, isPrototype, isSingleton, isTypeMatch, isTypeMatch, obtainFreshBeanFactory, onClose, onRefresh, postProcessBeanFactory, prepareBeanFactory, prepareRefresh, publishEvent, publishEvent, refresh, registerListeners, registerShutdownHook, removeApplicationListener, resetCommonCaches, setDisplayName, setEnvironment, setIdMethods inherited from class org.springframework.core.io.DefaultResourceLoader
addProtocolResolver, getProtocolResolvers, getResourceByPath, getResourceCacheMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface org.springframework.core.AliasRegistry
getAliasesMethods inherited from interface org.springframework.beans.factory.support.BeanDefinitionRegistry
containsBeanDefinition, getBeanDefinitionCount, getBeanDefinitionNamesMethods inherited from interface org.springframework.context.ConfigurableApplicationContext
addProtocolResolverMethods inherited from interface org.frankframework.core.FrankElement
addConfigWarningMethods inherited from interface org.frankframework.core.HasApplicationContext
getConfigurationClassLoaderMethods inherited from interface org.frankframework.core.ManagableLifecycle
isConfigured
-
Field Details
-
msgLog
protected org.apache.logging.log4j.Logger msgLog -
PROCESS_STATE_OK
- See Also:
-
PROCESS_STATE_ERROR
- See Also:
-
-
Constructor Details
-
Adapter
public Adapter()
-
-
Method Details
-
initLifecycleProcessor
protected void initLifecycleProcessor()- Overrides:
initLifecycleProcessorin classorg.springframework.context.support.AbstractApplicationContext
-
setApplicationContext
public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext) - Specified by:
setApplicationContextin interfaceorg.springframework.context.ApplicationContextAware
-
getApplicationContext
public org.springframework.context.ApplicationContext getApplicationContext()- Specified by:
getApplicationContextin interfaceHasApplicationContext
-
afterPropertiesSet
- Specified by:
afterPropertiesSetin interfaceorg.springframework.beans.factory.InitializingBean- Throws:
Exception
-
registerBeanPostProcessors
protected void registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory beanFactory) Enables theAutowiredannotation andConfigurationAwareobjects.- Overrides:
registerBeanPostProcessorsin classorg.springframework.context.support.AbstractApplicationContext
-
configure
Instruct the adapter to configure itself. The adapter will call the pipeline to configure itself, the pipeline will call the individual pipes to configure themselves.- Specified by:
configurein interfaceIConfigurable- Throws:
ConfigurationException- in case it was not able to configure the component.- See Also:
-
computeCombinedHideRegex
-
configureReceiver
- Throws:
ConfigurationException
-
warn
send a warning to the log and to the messagekeeper of the adapter -
addErrorMessageToMessageKeeper
send an error to the log and to the messagekeeper of the adapter -
publishEvent
public void publishEvent(org.springframework.context.ApplicationEvent event) - Specified by:
publishEventin interfaceorg.springframework.context.ApplicationEventPublisher- Overrides:
publishEventin classorg.springframework.context.support.AbstractApplicationContext
-
incNumOfMessagesInError
public void incNumOfMessagesInError()The number of messages for which processing ended unsuccessfully. -
setLastExitState
-
getLastExitIsTimeoutDate
-
formatErrorMessage
-
getLastMessageDateDate
retrieve the date and time of the last message. -
getNumOfMessagesInError
public double getNumOfMessagesInError()The number of messages for which processing ended unsuccessfully. -
getNumOfMessagesInProcess
public int getNumOfMessagesInProcess() -
getNumOfMessagesStartProcessingByHour
public long[] getNumOfMessagesStartProcessingByHour() -
getNumOfMessagesProcessed
public double getNumOfMessagesProcessed()Total of messages processed- Returns:
- long total messages processed
-
getReceiverByName
-
getReceivers
-
getRunState
Description copied from interface:ManagableLifecycleReturns the RunState of the object.- Specified by:
getRunStatein interfaceManagableLifecycle
-
getStatsUpSinceDate
return the date and time since active Creation date: (19-02-2003 12:16:53)- Returns:
- String Date
-
logToMessageLogWithMessageContentsOrSize
-
processMessageDirect
public PipeLineResult processMessageDirect(String messageId, Message message, PipeLineSession pipeLineSession) Direct call to the Adapter PipeLine, foregoing any listeners and receivers. This method does an amount of setup which is otherwise done by theReceiver.
This method does not throw any exceptions, and will always return aPipeLineResult. If an error occurred, the error information is in thePipeLineResult.- Parameters:
messageId- ID of the messagemessage-Messageto be processedpipeLineSession-PipeLineSessionsession in which message is to be processed- Returns:
- The
PipeLineResultfrom processing the message, or indicating what error occurred.
-
processMessageWithExceptions
public PipeLineResult processMessageWithExceptions(String messageId, Message message, PipeLineSession pipeLineSession) throws ListenerException This method does the real processing of messages by the adapter. This method is to be called either from theReceiver, or fromprocessMessageDirect(String, Message, PipeLineSession).
NB: This method expects most setup to already have been done by the caller! LoggingContext and masking of sensitive information is among things that should be set up by the caller.
This method will return aPipeLineResultwith results of the processing. This might indicate an error if the message could not be processed successfully. If there was an exception from thePipeLine, aListenerExceptionmight be thrown.- Parameters:
messageId- ID of the messagemessage-Messageto be processedpipeLineSession-PipeLineSessionin which the message is to be processed- Returns:
PipeLineResultwith result from processing the message in thePipeLine.- Throws:
ListenerException- If there was an exception, throws aListenerException.
-
addReceiver
Receives incoming messages. If an adapter can receive messages through multiple channels, then add a receiver for each channel. -
setErrorMessageFormatter
Set anErrorMessageFormatterthat will be used to format an error-message when an exception occurs in this adapter. If not set, then, when an exception occurs, the adapter will first check theConfiguration.setErrorMessageFormatter(IErrorMessageFormatter)to see if a configuration-wide default error message formatter is set and otherwise create a new instance ofErrorMessageFormatteras default.- See Also:
-
setPipeLine
ThePipeLine. -
getPipeLine
-
start
public void start()Start the adapter. The thread-name will be set to the adapter's name. The run method, called by t.start(), will call the startRunning method of the IReceiver. The Adapter will be a new thread, as this interface extends theRunnableinterface. The actual starting is done in therunmethod.- Specified by:
startin interfaceConfigurableLifecycle- Specified by:
startin interfaceorg.springframework.context.Lifecycle- Overrides:
startin classorg.springframework.context.support.AbstractApplicationContext- See Also:
-
getPhase
public int getPhase()- Specified by:
getPhasein interfaceConfigurableLifecycle- Specified by:
getPhasein interfaceorg.springframework.context.Phased- Specified by:
getPhasein interfaceorg.springframework.context.SmartLifecycle
-
isRunning
public boolean isRunning()Description copied from interface:ManagableLifecycleVerifies if this object needs to be started or stopped.- Specified by:
isRunningin interfaceorg.springframework.context.Lifecycle- Specified by:
isRunningin interfaceManagableLifecycle- Overrides:
isRunningin classorg.springframework.context.support.AbstractApplicationContext
-
stop
Stop theAdapterand close all elements like receivers, Pipeline, pipes etc. The adapter will call theIReceivertostopListeningAlso the
PipeLine.stop()method will be called, closing all registered pipes.- Specified by:
stopin interfaceorg.springframework.context.SmartLifecycle- See Also:
-
stop
public void stop()This method should ideally not be called directly. Since this is aSmartLifecyclethestop(Runnable)must be called instead. Delegates tostop(Runnable)which calls `super.stop()`.- Specified by:
stopin interfaceorg.springframework.context.Lifecycle- Overrides:
stopin classorg.springframework.context.support.AbstractApplicationContext
-
toString
- Overrides:
toStringin classorg.springframework.context.support.AbstractApplicationContext
-
waitForNoMessagesInProcess
- Throws:
InterruptedException
-
getBeanName
- Specified by:
getBeanNamein interfaceorg.springframework.beans.factory.NamedBean
-
setName
name of the adapter -
getName
-
setDescription
some functional description of theAdapter -
setAutoStart
public void setAutoStart(boolean autoStart) AutoStart indicates that the adapter should be started when the configuration is started.- Default value
true
-
isAutoStartup
public boolean isAutoStartup()Description copied from interface:ConfigurableLifecycleBy default these beans are not started. TheConfigurationmay do so in theConfiguration.configure()method.- Specified by:
isAutoStartupin interfaceConfigurableLifecycle- Specified by:
isAutoStartupin interfaceorg.springframework.context.SmartLifecycle
-
setReplaceNullMessage
public void setReplaceNullMessage(boolean b) Iftruea null message is replaced by an empty message- Default value
false
-
setMessageKeeperSize
public void setMessageKeeperSize(int size) number of message displayed in ibisconsole- Default value
- 10
-
setMsgLogLevel
Defines behaviour for logging messages. Configuration is done in the MSG appender in log4j4ibis.properties.- Default value
INFO, unless overridden by propertymsg.log.level.default
-
setRequestReplyLogging
Deprecated. -
setMsgLogHidden
public void setMsgLogHidden(boolean b) If set totrue, the length of the message is shown in the msg log instead of the content of the message- Default value
false
-
setTargetDesignDocument
An optional field for documentation-purposes where you can add a reference to the design-document used for the design of this adapter.
Setting this field has no impact on the behaviour of the Adapter.
-