Spring integration Error handling - How do I access original faulty message's history? - error-handling

We have a spring-integration application where we would like to deal with the messages on the error channel.At a minimum we would like to extract the history and log it so we can visualise where exactly it failed etc
Here is a brief markup of just this bit
<int:poller id="defaultPoller" default="true" fixed-delay="5000" />
<int:channel id="MyCustomErrorChannel">
<int:queue capacity="10"/>
</int:channel>
<int:header-enricher id="errorMsg.HeaderEnricher"
input-channel="errorChannel"
output-channel="MyCustomErrorChannel">
<int:header name="history" expression="payload.failedMessage.headers" />
</int:header-enricher>
<int:service-activator input-channel="MyCustomErrorChannel" ref="errorLogger" method="logError"/>
<bean id="errorLogger" class="com.dataprep.util.ErrorLogger" />
The idea is to define our custom error channel MyCustomErrorChannel. Any error that ends up in the default errorChannel gets its header's enriched before being put out on MyCustomErrorChannel
Lastly we have a logger that reads the messages from MyCustomErrorChannel and logs the payload which is the underlying exception and also the history.
I notice that the history in my logger is always 3 steps
errorChannel,errorMsg.HeaderEnricher,pbSwiftRouterErrorChannel i.e nothing prior to this message landing on the errorChannel is obtainable in the history.
How do I get hold of the original message's history (i.e the history of the faulty message which somehow landed on the default error channel as a new Error Message)
Could you please take a look at my header enricher and let me know how to access the headers on the failed message and stuff it to the error message?
Is it doable at all ?

To replace existing headers you should use overwrite="true", because the history is built for the ErrorChannel, too.
You should override exactly with history header, not the whole headers. Therefore your expression must be like this:
<int:header name="history"
expression="payload.failedMessage.headers.history"
overwrite="true"/>

Related

MuleSoft 4 - how can i route the errors from Http:Request to my main Error handler?

i would like to route my http:request to my main ( or secondary ) error handler in Anypoint Studio 7
i does not seem to have a clear way of doing it.
And the documentation does not have guideline for this specific case.
in my case is necessary, i need to know and send a signal to another service and communicate the error response, like: connection_timeout
You can catch the errors you want using an error-handler in your flow where you are executing the http:request. if you do not catch the error, it will bubble up to the calling flow and so on. If no error-handler is configured, the default mule one will be used which just logs the message basically.
In Mule 4 you can catch all errors in your flow like so:
<flow name="retrieveMatchingOrders">
<http:request config-ref="customersConfig" path="/customer">
</http:request>
<error-handler>
<on-error-continue>
<!-- error handling logic -->
</on-error-continue>
</error-handler>
</flow>
An on-error-continue will execute and use the result of the execution, as the result of its owner (as if the owner had actually completed the execution successfully). Any transactions at this point would be committed as well
So in there, you can set the payload to your desired message to be returned etc.
There also an on-error-propogate handler and a try scope, more information on those are available here: https://docs.mulesoft.com/mule-runtime/4.1/intro-error-handlers
All errors thrown in Mule contain meta-data including a TYPE. If you need to catch specific HTTP Errors you can configure your error-handler like so:
<error-handler>
<on-error-continue type="HTTP:TIMEOUT">
<!-- error handling logic -->
</on-error-continue>
</error-handler>
Here is a list of all specific HTTP: errors thrown by the HTTP module:
HTTP:UNSUPPORTED_MEDIA_TYPE
HTTP:CONNECTIVITY
HTTP:INTERNAL_SERVER_ERROR
HTTP:METHOD_NOT_ALLOWED
HTTP:NOT_ACCEPTABLE
HTTP:TOO_MANY_REQUESTS
HTTP:SERVICE_UNAVAILABLE
HTTP:CLIENT_SECURITY
HTTP:FORBIDDEN
HTTP:UNAUTHORIZED
HTTP:RETRY_EXHAUSTED
HTTP:NOT_FOUND
HTTP:BAD_REQUEST
HTTP:PARSING
HTTP:TIMEOUT
HTTP:SECURITY
Each module's documentation should contain all specific error types thrown by that module. Here is the HTTP one example:
https://docs.mulesoft.com/connectors/http/http-documentation#throws
And here is a full list of core error types you can catch like EXPRESSION for example:
https://docs.mulesoft.com/mule-runtime/4.1/mule-error-concept

Spring Integration: How to use an "error gateway" with Splitter Aggregator when Exception thrown

I've seen more than a few posts about this topic, but can't seem to find a solution to my specific problem, which I think is a pretty typical one, namely: how to keep processing messages when an error occurs (Exception thrown) using a Splitter / Aggregator.
The best explanation that I have come upon is here. But there's no explanation of exactly what/how the filters/transformers work. And in the end, the author posts "That worked!" but without posting an updated SI.config.xml.
From what I understand, the idea is to use an "error gateway", which is downstream from the original calling gateway and after the Splitter. This Gateway's job would be if there is an Exception thrown, to deal with it, but to make sure (via a transformer or a filter) that all Messages make it to the Aggregator.
My very simplified SI.config.xml if more or less like this:
<int:gateway id="myGateway" ... /> // incoming gateway
<int:chain ... input-channel="in" output-channel="out">
<int:splitter ... />
<int:service-activator />
<int:aggregator />
</int:chain>
So my question is, where exactly to stick this other gateway? And how to configure filters/transformers that (from what I gather) would grab the Message which launched an Exception and put it back on the correct channel (after logging it or whatever ...) so all Messages make it to the Aggregator.
I have looked at the SI samples, on SO, and the 2 SI books (SI in Acton and Pro SI) and can't find an example of this.
The solution looks like:
<int:chain ... input-channel="in" output-channel="out">
<int:splitter ... />
<int:gateway request-channel="processChannel" errorChannel="processError"/>
<int:aggregator />
</int:chain>
<int:chain input-channel="processChannel">
<int:service-activator />
</int:chain>
The error handler on the processError channel should consult incoming ErrorMessage and returns some compensation which will be sent to the aggregator.
The ErrorMessage typically contains MessagingException with a failedMessage where error has caused. That failedMessage contains all useful headers to go ahead with a compensation. Some of them are replyChannel and errorChannel, but for your aggregator case you need all those correlationId, sequenceNumber, sequenceSize etc. In other words when you build compensation message to be sent forward to the downstream for the aggregator, you should copy all the headers from that failedMessage.
For more info: http://docs.spring.io/spring-integration/docs/4.3.5.RELEASE/reference/html/configuration.html#namespace-errorhandler

Bit rate error when trying to dial out to an ISDN line using Polycom XML API

I am having a problem connecting to an ISDN line using Polycom's XML API on an RMX_2000. Below is the request I am sending, and the response. I can do the same action from the RMX Manager, for the same number, in the same conference, and it works. When I trace the XML from the RMX Manager, I get an ADD_PARTY request that looks exactly like my constructed request, except with a lot more elements. I've reviewed and don't see any that seem like they could be relevant, and I am loath to manually code every single element, knowing that it is a long shot that it will even help. The same request (variant) works fine for IP and registered number requests, but no matter what I do, always get the bit rate error below. Can anyone tell me what I am doing wrong?
<TRANS_CONF_1>
<TRANS_COMMON_PARAMS>
<MCU_TOKEN>304</MCU_TOKEN>
<MCU_USER_TOKEN>304</MCU_USER_TOKEN>
<MESSAGE_ID>1</MESSAGE_ID>
</TRANS_COMMON_PARAMS>
<ACTION>
<ADD_PARTY>
<ID>18466</ID>
<PARTY>
<ID>0</ID>
<NAME>isdn</NAME>
<PHONE_LIST>
<PHONE1>12345678910</PHONE1>
</PHONE_LIST>
<INTERFACE>isdn</INTERFACE>
<CONNECTION>dial_out</CONNECTION>
<MEET_ME_METHOD>party</MEET_ME_METHOD>
<NUM_TYPE>taken_from_service</NUM_TYPE>
<MULTI_RATE>auto</MULTI_RATE>
<ALIAS>
<NAME>12345678910</NAME>
<ALIAS_TYPE>323_id</ALIAS_TYPE>
</ALIAS>
<VIDEO_BIT_RATE>automatic</VIDEO_BIT_RATE>
<ENHANCED_VIDEO>false</ENHANCED_VIDEO>
<UNDEFINED>false</UNDEFINED>
</PARTY>
</ADD_PARTY>
</ACTION>
</TRANS_CONF_1>
Here is the response:
<RESPONSE_TRANS_CONF>
<RETURN_STATUS>
<ID>1015</ID>
<DESCRIPTION>Conference bit rate must be set to a minimum of 128Kbps to enable ISDN participant connection</DESCRIPTION>
<YOUR_TOKEN1>0</YOUR_TOKEN1>
<YOUR_TOKEN2>0</YOUR_TOKEN2>
<MESSAGE_ID>1</MESSAGE_ID>
<DESCRIPTION_EX></DESCRIPTION_EX>
</RETURN_STATUS>
<ACTION>
<ADD_PARTY/>
</ACTION>
</RESPONSE_TRANS_CONF>
Thanks to a little help from someone at Polycom, I found out that the following node is required for this:
auto
I added that to the PARTY node, and now all is well.
After alot of troubleshooting and wiresharking on this error I found a combination of 2 properties being the issue
Reservation object needs
<TRANSFER_RATE>384</TRANSFER_RATE>
Party object needs
<NET_CHANNEL_NUMBER>auto</NET_CHANNEL_NUMBER>

NServiceBus 5 - Sql Transport not writing audit records

I am using the sql transport and have the following defined in my config file for the sender and endpoint.
<section name="AuditConfig" type="NServiceBus.Config.AuditConfig, NServiceBus.Core" />
<AuditConfig QueueName="audit" />
The tables get successfully created, however, when my message handlers complete successfully and i check the tables no records are present. Is there something else I need to do to get this working?
Thanks
Low and behold this was an error within the outbox and a fix has been committed.
https://github.com/Particular/NServiceBus/issues/2702

Mule / AMQP / RabbitMQ: Trying to send to the default exchange

Using Mule 3.4 with the AMQP Transport plugin and RabbitMQ, I am trying to send a message to the default AMQP exchange. The documentation for the exchangeName attribute states "leave blank or omit for the default exchange". However if I (a) omit it, like so:
<amqp:outbound-endpoint routingKey="my.queue" connector-ref="amqpDefaultConnector" />
Then I get the error message:
Element amqp:outbound-endpoint{connector-ref=amqpDefaultConnector,
name=.test:outbound-endpoint.17, routingKey=process.task.complete}
must have all attributes for one of the sets: [address] [ref]
[queueName] [exchangeName] [exchangeName, queueName].
Which seems to indicate that it is not valid to omit the attribute. However, if I (b) provide it but leave it blank, like so:
<amqp:outbound-endpoint exchangeName="" routingKey="my.queue" connector-ref="amqpDefaultConnector" />
then I get the error message:
java.net.URISyntaxException: Expected authority at index 7: amqp://
I believe that the rest of my configuration and setup is correct, as using a named exchange works as expected. Any help would be appreciated.
To dispatch to the default exchange, you need to pass the queue name in queueName not routingKey:
<amqp:outbound-endpoint exchangeName=""
queueName="my.queue"
connector-ref="amqpDefaultConnector" />