How to get message body from message intercepted by ActiveMQServerMessagePlugin afterSend method - activemq-artemis

I intercept the message by public void afterSend(ServerSession session, Transaction tx, Message message, boolean direct, boolean noAutoCreateQueue, RoutingStatus result) throws ActiveMQException method. How do I get the message body? I try to get body by ((CoreMessage) message).getBodyBuffer().readUTF() but get Method threw 'java.lang.IndexOutOfBoundsException' exception. And in debugger body = null, but sended message has String body.

The first thing to note is that org.apache.activemq.artemis.api.core.Message#getBodyBuffer is deprecated and shouldn't be used.
If your message was sent using the core JMS client and it was sent as a javax.jms.TextMessage then you can use org.apache.activemq.artemis.api.core.Message#getStringBody to get the underlying byte array decoded as a String.

Related

How stop execution and send ack/nack with error message in mirth 3.4?

I'm new in mirth so sorry if my question may seems naive.
I've a mirth channel that recives hl7 messages, and this is fine, also I've some filters and transformers both in Source and Destination.
When all is fine at the end of destination I send an ACK with a message, for this for this purpose I've made this function in code Templates:
function getAck(success, detailMessage, statusMessage) {
if (!detailMessage)
detailMessage = success ? "Operation completed successfully" : "Some error occours";
if(!statusMessage)
statusMessage = detailMessage;
if (success) {
ack = ACKGenerator.generateAckResponse(connectorMessage.getRawData(), "AA", detailMessage);
resp = new Response(com.mirth.connect.userutil.Status.SENT, ack, statusMessage);
} else {
ack = ACKGenerator.generateAckResponse(connectorMessage.getRawData(), "AE", detailMessage);
resp = new Response(com.mirth.connect.userutil.Status.ERROR, ack, statusMessage, detailMessage);
}
return resp;
}
So I use ACKGenerator.generateAckResponse for creating an Ack and Response for send response at client. This work but only in destination and that's my problem.
If I get an error before destination (e.g. in filters, transformer, ...) I don't be able to stop execution and send an NACK with an explaination of the error and this is what I would like to do.
Am I wrong doing things in this way?
You can store a Response in the responseMap in any filters or transformers. Once you define a key in the responseMap, it should be available as a selection in the response drop down on the source tab of your channel (instead of picking a destination.)
Your current connector should stop processing a message with an ERROR status if you manually throw an exception after setting the desired value in the responseMap. If you are in a filter, you could also filter the message instead of throwing the exception.
If you are worried about an uncaught exception, you could initialize the responseMap variable with an "Unknown Error" message at the first point in the channel where your custom code is defined that affects messages directly (likely the source filter from your description, but could possibly be the pre-processor or attachment handler if you use those.) The expectation is that this would be replaced with a more descriptive error or a success if the message makes it all the way through to the end, but the channel will always have something to return.
There are filter and transformer in the "Source" tab. If your expecting an error there or on other destinations, you could try:
Adding a try-catch code block in your filter and transformer.
Use your custom code template function in your filter and transformer to catch the error or issue.
Create a separate channel that will receive the ACK/NACK which will be responsible in forwarding that message to the client.
In your try-catch code block or custom code template, use the method router.routeMessageByChannelId to forward the ACK/NACK to the other channel (step 3).
Note: You'll need to disable the default response in your original channel since you have the other channel that'll forward the ACK/NACK. You'll also need to consider if the client's machine expects a valid ACK/NACK immediately when they sent the HL7 message, depends on their setup.

Throw SOAP exception when there are pending Entity Framework database migrations for any SOAP request

I want to throw a SOAP exception when there are pending Entity Framework migrations and someone sends any SOAP request. If I throw a FaultException within my Global.asax, I get a html response from the IIS. This works but it is rather ugly. So I tried to throw it within the IServiceBehavior.Validate() method of my ServiceBehavior class.
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
var isDatabaseUpdateRequired = new MyDb().GetPendingMigrations().Any();
if (isDatabaseUpdateRequired) throw new FaultException("There are pending migrations.");
}
But I do not get any XML response with the error message on my SoapUI client. Where should I throw this exception?
You can throw this exception in a class that implements the interface IDispatchMessageInspector. Implement IDispatchMessageInspector to inspect or modify inbound or outbound application messages either prior to dispatching a request message to an operation or before returning a reply message to a caller.
When the server receives the client request, the DispatchMessageInspector intercepts all the client requests.
The picture above is the implementation of IDispatchMessageInspector, Throw an exception in the BeforeSendReply method.
The client sends a request to the server and gets an exception message.
Here is a link about the IDispatchMessageInspector interface.

SFTP to REST using Camel

I am very new to camel. I want to pull some xml file from a sftp location and feed the content to existing REST endpoint. Below is my configuration,
<route id="xml.FOEBRE">
<from uri="<sftp server uri>"/>
<marshal>
<string/>
</marshal>
<setHeader headerName="Content-Type">
<constant>application/xml</constant>
</setHeader>
<doTry>
<to uri="<REST URI>?httpMethod=POST"/>
<bean ref="myListener" method="onPushSuccess"/>
<doCatch>
<exception>java.lang.Exception</exception>
<!--<log message="error : ${exception.message}" loggingLevel="ERROR"/>-->
<process ref="globalExceptionListener"/>
</doCatch>
</doTry>
</route>
I am able to call it, but I want to capture the response status and body of the REST call. In my success processor I have written,
Message message = exchange.getIn();
int status = message.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
LOG.debug("Response status : {}", status);
LOG.debug("Payload successfully sent to securecargo");
String body = message.getBody(String.class);
LOG.debug("Response Body : {}", body);
This code is returning me the proper response body. But the same code (in catch listener) is not working when the status code is 400. I have two question,
How to catch this response body when status code is 400? My processor in catch block is never invoked.
Why I getting this body in exchange.getIn(), not in exchange.getOut()?
Note: My REST service returns two status, 201 for success and 400 for failure. I know my service returns a JSON payload both in success and failre scenario.
You'll get the response code from headers inside getIn() method instead. By facing any issue (I mean, HTTP-call errors) other than the expected response, an exception will be thrown and set into the exchange properties (Exchange.EXCEPTION_CAUGHT).
Finally I got the answer
My processor was getting invoked, but encounters a NPE while excuting the processor body and that exception was internally consumed by camel
During an exception, all exception related information can be retrieved from exception object itself rather than In/Out
Below is my exception handler (processor) code,
HttpOperationFailedException cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class);
LOG.error(cause.getMessage());
final String responseBody = cause.getResponseBody();
LOG.error(responseBody);

Azure Service Bus Queue gives control characters in fetched message

I am using BizTalk Server SB-Messaging adapter to retreive messages from Azure Service Bus Queue. I have successfully managed to send message to queue myself (using same adapter), and retreive message from queue and do further processing.
Problem arises when a 3rd party software supplier is sending messages to the queue, and for BizTalk Server to retreive and process message. I then receive the following additional "header"-information and control characters in the beginning of the message:
In text: #ACKstringBShttp://schemas.microsoft.com/2003/10/Serialization/?$SOH
Seems like there is some sort of enveloped message, including headers to handle ACKnowledgement of the message to the queue.
SB-Messaging adapter gave following initial error message:
"The WCF service host at address has faulted and as a result no
more messages can be received on the corresponding receive location.
To fix the issue, BizTalk Server will automatically attempt to restart
the service host."
And, another error message:
"No Disassemble stage components can recognize the data."
Did anyone hit this problem before, and, what can be the cause of the problem? Can character encoding be a possible cause of this problem?
Here comes the feedback!
Turned out 3rd party software supplier had a setting to send message as stream, instead of string. Turns out it is a .Net application using BrokeredMessage object. Using string makes message serialized, and meta-data is added to the message. Using stream, no such serialization takes place, and message is kept untouched.
So, problem was using string and automatic serialization when sending to Service Bus Queue.
I have legacy Microsoft.ServiceBus.Messaging clients sending BrokeredMessage Xml content as <string> and I want to receive using the latest Microsoft.Azure.ServiceBus library and Message type.
Using Encoding.UTF8.GetString(message.Body) I get a unusable string prefaced with
#\u0006string\b3http://schemas.microsoft.com/2003/10/Serialization/��#
My approach is to explicitly use XmlDictionaryReader binary deserialization to undo the hidden serialization magic from the legacy library
private static string GetMessageBodyHandlingLegacyBrokeredMessage(Message message)
{
string str = null;
if (message.ContentType == null)
{
using (var reader = XmlDictionaryReader.CreateBinaryReader(
new MemoryStream(message.Body),
null,
XmlDictionaryReaderQuotas.Max))
{
var doc = new XmlDocument();
doc.Load(reader);
str = doc.InnerText;
}
}
else
throw new NotImplementedException("Unhandled Service Bus ContentType " + message.ContentType);
return str;
}
References
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messages-payloads#payload-serialization
https://carlos.mendible.com/2016/07/17/step-by-step-net-core-azure-service-bus-and-amqp/

Catch MailException

Is it possible to catch a MailException when sending an e-mail?
I want to catch it in scenarios like mail server is down, malformed e-mail address, etc.
I see the MailException in the console but I cannot catch it when I call Mailer.send(). The Mailer.send() sends the e-mail asynchronously and thus I cannot catch the exception. How can I wait for the result suspending the HTTP request?
Another question: Does the Mailer.sendAndWait() suspend the request?
First the mail() method might throw a MailException if sending mail fails.
The send methods return a Future of type Boolean, if you call get() on the future you will get the result of the mail sending, mind that this call is blocking and will wait for the mail sending to finish.
This is the same thing as using sendAndWait()
This get can also throw an ExecutionException but I don't have the impression this is used by the play mailer. Instead you get back false from the future and the exception is logged.
SendAndWait() does not suspend the request as far as I can see in the sources
more info here:
http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/Future.html
https://github.com/playframework/play/blob/master/framework/src/play/mvc/Mailer.java
https://github.com/playframework/play/blob/master/framework/src/play/libs/Mail.java