In Mule 4 how do I get error handling to use the payload? - mule

I am using Mule 4 to make a flow and on the error handling I want it to transform the message to something that uses the existing payload.
My code is
transactionNotification: {
"Testout": "Band",
"errorNotification": p("api.name"),
"transactionCode": p("notification.errorCode"),
"transactionStatus": p("notification.error"),
remark: {
messageCode: p("notification.messageCode"),
messageText: payload
}
}
and I get the error
Scripting language error on expression '%dw 2.0 output
application/json
transactionNotification: {
"Testout": "B...'. Reason: Unable to resolve reference of payload..
The same code seems to work in the normal flow and the error goes away
when I delete payload.

I managed to achieve this using a "Set Variable" to a java object.
Name: payloadString
Value: #[payload]
MIME Type
application/java
I can then use it like you
{
"Testout": "Band",
"errorNotification": p("api.name"),
"transactionCode": p("notification.errorCode"),
"transactionStatus": p("notification.error"),
remark: {
messageCode: p("notification.messageCode"),
messageText: (vars.payloadString as String)
}
}

Related

How to create a custom deserializer on spring kafka?

I've created a consumer to receive messages from a Kafka topic but I'm parsing the message manually, is there a way to parse automatically with a custom deserializer for this single topic consumer?
// I've tried to replace the second "String" with "MyMessage" but it didn't work
// e.g: onMessage(message: ConsumerRecord<String, MyMessage>)
fun onMessage(message: ConsumerRecord<String, String>) {
val myMessage = try {
jacksonObjectMapper.readValue<MyMessage>(message.value())
} catch (ex: Exception) {
logger.error(ex.message)
null
}
myMessage?.let{ // do stuff }
}
The expected result is:
fun onMessage(message: ConsumerRecord<String, MyMessage>) {
// do something with message.value() parameter that will be for sure a MyMessage instance.
}
In case of a parse error can I set a callback to handle this error?
Yes; just implement your own and add it to the consumer configuration value.deserializer.
https://kafka.apache.org/documentation/#consumerconfigs_value.deserializer
If you are using Spring Boot:
https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.integration.spring.kafka.consumer.value-deserializer
If configured this way, it is not managed by Spring; if you want Spring to manage it, add it to the DefaultKafkaProducerFactory via a constructor or setter.
Spring for Apache Kafka provides a JSON deserializer:
https://docs.spring.io/spring-kafka/docs/current/reference/html/#json-serde

Gradle with Kotlin DSL expecting Property<String> error

I need to set this
avro {
templateDirectory = "/path/to/velocity/templates"
}
But getting error stating that's it's expecting Property<String> not a String.
Not clear on how to set this value as Property<String>?
If you're using the gradle-avro-plugin, do note that the configuration should be set as below for Kotlin DSL
avro {
templateDirectory.set("/path/to/velocity/templates" as String?)
}
The syntax for all the configurations are as below:
avro {
isCreateSetters.set(true)
isCreateOptionalGetters.set(false)
isGettersReturnOptional.set(false)
fieldVisibility.set("PUBLIC_DEPRECATED")
outputCharacterEncoding.set("UTF-8")
stringType.set("String")
templateDirectory.set(null as String?)
isEnableDecimalLogicalType.set(true)
dateTimeLogicalType.set("JSR310")
}
The reference is here.

Post API using Ratpack and Groovy giving 405 Error and RxJava methods not working

I am building an API using Ratpack and Groovy. The POST API is always giving:
405-Method not Found Error
This is a snippet from POST Endpoint Handler. In this code, promiseSingle, then, observe, map, doOnNext, doOnError, etc.
RxJAVA functions are not working. Is there any reason why RxJava methods are not working?
saveJsonAsData(context, id)
.promiseSingle()
.then { Data updateddata ->
context.response.headers
.add(HttpHeaderNames.LOCATION, "/api/save/${updateddata.id}/${updateddata.value}")
context.response.status(HttpResponseStatus.CREATED.code())
.send()
}
}
protected Observable<Data> saveJsonAsData(GroovyContext context, String id) {
context.request.body.observe()
.map { TypedData typedData -> extractData(context, typedData) }
.doOnNext { Data data ->
data.id = id
validatorWrapper.validate(data)
}
.flatMap(data.&save as Func1)
.doOnError { Throwable throwable -> log.error("Error saving data", throwable) }
}
The issue is not so much with Rx as it is with the usage of the Context.
You should try to keep the response handling logic within your Handler, that is don't pass the Context around, rather get the objects you need and pass them to your services.
As an example
path('myendpoint') { MyRxService service ->
byMethod {
get {
// do something when request is GET
}
post {
request.body.map { typedData ->
extractItem(typeData) // extract your item from the request first
}.flatMap { item ->
service.saveJsonAsItemLocation(item).promiseSingle() // then once it's extracted pass the item to your "saveJsonAsItemLocation" method
}.then { ItemLocationStore updatedItem ->
response.headers.add(HttpHeaderNames.LOCATION, "/itemloc/v1/save/${updatedItem.tcin}/${updatedItem.store}")
context.response.status(HttpResponseStatus.CREATED.code()).send()
}
}
}
}
My guess is that you have something like this:
get {
// get stuff
}
post {
// post stuff
}
The reason this doesn't work is that Ratpack doesn't use Routing Table for handling incoming requests, instead it uses chain delegation. The get {} binds to root path and GET http method and post {} binds to root path and POST http method. Because get {} matches the path, Ratpack considers the handler matched and since the handler is for GET it considers it a 405.
There are chain methods available that binds regardless of HTTP Method such as all {} and path {}. Chain#all will handle all paths and methods where as Chain#path(String) matches against specific path.
Hope this helps.

Handling Windows Store App exceptions from GetFileAsync

I have a problem with the following code example:
Windows::Storage::StorageFolder^ location = Package::Current->InstalledLocation;
try
{
task<StorageFile^> GetFileTask(location->GetFileAsync(sn));
GetFileTask.then([=](StorageFile^ file)
{
try
{
task<IBuffer^> ReadFileTask(FileIO::ReadBufferAsync(file));
ReadFileTask.then([=](IBuffer^ readBuffer)
{
// process file contents here
});
}
catch(Platform::Exception^ ex)
{
// Handle error here
}
});
}
catch(Platform::Exception^ ex)
{
// Handle error here
}
When using a filename that doesn't exist the function throws an exception:
Unhandled exception at 0x0FFCC531 (msvcr110d.dll) in GameTest2.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
I've been searching the internet and this exception breaks only when connected to the debugger. I'm using VS 2012. I've turned off all the relevant 'break on exception' but it still causes the debugger to break and non of my handlers are getting a chance to handle the exception.
If the file is missing I would expect the GetFileAsync method to throw a 'File doesn't exist' exception. Not sure why it keeps throwing the 'Invalid parameter' exception.
This is starting to bother me and I just can't find any known solution to this issue. Anyone have any ideas?
I'm going to try and change the method to not use the task<> code. Instead I'll call the GetFileAsync using 'await'. However I believe 'await' will just cause the calling thread to wait until the GetFileAsync has finished, which kind of defeats the point of asynchronous loading.
I'm wondering if this is a common issue with exception handling when using tasks.
Update:
OK, I've now found the solution:
task<StorageFile^>( location->GetFileAsync(sn)).then([](StorageFile^ openedFile)
{
return FileIO::ReadBufferAsync(openedFile);
}).then([](IBuffer^ readBuffer)
{
// Process file
}).then([](task<void> t)
{
try
{
t.get();
}
catch(Platform::Exception^ e)
{
// Handle error
}
});
It seems there needs to be an extra 'then' condition added to the end of the chain to pick up the exception.

accessing javascript function arguments

Documentation for JQAjaxSetup>>onError: says:
onError: anObject
"A function to be called if the request fails. The function is passed three
arguments: The XMLHttpRequest object, a string describing the type of error that occurred
and an optional exception object, if one occurred. Possible values for the second argument
(besides null) are 'timeout', 'error', 'notmodified' and 'parsererror'."
I'd like to display the error message using something like
anAjax onError: ((html jQuery id: someId) before: (MyInstanceOfWAPainter error: 'An error message'));
How do I do that? Possibly doing it all on the client side.
Because the error happens client-side and you probably have a failing connection in such an event, you need to generate the complete javascript code that will display the error (i.e. without rendering callbacks to Seaside).
The snippet below will generate a JS function with two arguments. The body of the function is the jQuery expression that will put the error message (inside the _error variable) right before the html dom element with id someId.
anAjax
onError: (((html jQuery id: someId) before: (JSStream on: '_error'))
asFunction: #('_XMLHttpRequest' '_error'));
Personally, I would not use Seaside's JS-generation functionality here if the id in someId is not dynamically generated. If it's dynamically generated from within Seaside, the first snippet might still be easier.
anAjax onError: (JSStream on: 'function(_XMLHttpRequest,_error){
$(''#someId'').before(_error)})
According to documentation you can do below to show the error:
onError:function(_XMLHttpRequest, _error) {
alert(_error);
}
this basic idea would be:
jQuery ajax onError: (self javascript alert: 'error')
see JQAjaxTest>>testOnError.