"ByteArrayBasedCursorStreamProvider cannot be cast to HttpRequestAttributes" when trying to set attributes before APIKit - http-headers

I have a requirement on my REST API where I might set some attributes before APIKit if some condition is met (because we have a logger which must write this information).
Following this solution, I created the script below to set Attribute object inside Transform component.
%dw 2.0
output application/json
---
(
(attributes
- "headers"
- "maskedRequestPath")
++
({
headers: attributes.headers
++
{
xpto: 123
}
})
)
as Object {
class: "org.mule.extension.http.api.HttpRequestAttributes"
}
However, I am getting org.mule.weave.v2.el.ByteArrayBasedCursorStreamProvider cannot be cast to org.mule.extension.http.api.HttpRequestAttributes error.
Is there a way where I can successfully set these values before APIKit Router?
I am using APIKit v1.6.1, with 4.3.0 runtime.

You should use output application/java in order to create an HttpAttributes

Related

Mule esb 3.8 how to add variable into payload?

let say I have payload:
{ Name=User1, Age=29 }
and variable:
{ Address=Planet Earth}
I want to have a check if that variable not null then add it into payload.
So final result will be:
{ Name=User1, Age=29, Address=Planet Earth }
How? Was try via payload.Put(variable) but that not allow me such.
With DataWeave using a Transform component you can use the expression: payload ++ flowVars.variable
If you don't want or can't use DataWeave then you can use a MEL expression that uses the Java method Map.putAll() of the Map interface. You can not use <set-payload> because it doesn't return a value. Instead you can use the <expression-component> component.
Example:
<expression-component doc:name="Expression"><![CDATA[payload.putAll(flowVars.variable)]]></expression-component>

How to get a value from a string value that is coming in a payload,

I am getting a payload with some keys that are having values for example
1. mulesoft[04444]
2. muleworld[88990]
now I want to extract content that is enclosed in square brackets here.
let's take an actual problem, here incoming payload
{
"message": "Hello world[009]",
"sender" : "myself[001]",
"to": "friend[0089]"
}
here I want to create a Mulesoft function inside data weave code that I can use to extract value that is enclosed in the square brackets
Please write a DWL code fro this.
I faced this issue today in one of the API, so I thought that I should share this with others too.
I had written DWL code for its as below
%dw 2.0
import * from dw::core::Strings
output application/json
fun extract(key)= substringBefore((substringAfter(key, "[")),"]")
---
{
value: extract(payload.message)
}
it gave me desired o/p
{
"value": "009"
}
Thanks
Assuming the contents in the [] would constitute the last part of a given text, you could also try this:
((payload.message splitBy("["))[1]) replace ("]") with ""

Mule : Placing DB select output as JSON array in Json Object

I need to construct a json object like below
{ "Name":"Tom", "Hobbies":["Fishing","Reading"],"Cars": [{"Make":"Honda","Model":"Civic","Price":"25000"},{"Make":"Toyota","Model":"Camry","Price":"20000"}]
I am constructing this JSON object in a Java transformer. I am get this value [{"Make":"Honda","Model":"Civic","Price":"25000"},{"Make":"Toyota","Model":"Camry","Price":"20000"}] from DB query. But when I try to add this as JSON array in the transformer, it's throwing string can't be casted as JSON Array. Please let me know how to go about it.
Just use transform message activity with snippet below.
%dw 1.0
%output application/json
{
Name: "Tom",
Hobbies: ["Fishing","Reading"],
Cars : payload
}

mule : Merge List of maps into single Map

I have scattergather in my flow, the output of which is a List of Maps, How can I convert that into a single Map in mule?
I have tried combine-collections-transfomer, flatten payload. Nothing seems to be working.
You can you following dataweave code, but it will override duplicate keys
%dw 1.0
%output application/java
---
{(payload)}
Hope this helps.
I would recommend using a custom Java Transformer so you can easily handle special situations such as duplicate keys with different values. A DataWeave function may also be able to do the trick, but you'll need Mule EE.
With a Transformer it's a simple question of Java code:
public class MyMapFlattener extends AbstractMessageTransformer{
public Object transformMessage(MuleMessage message, String outputEncoding) throws TransformerException {
//assuming your payload is the list of map
List<Map<?, ?>> listOfMap = message.getPayload();
Map<Object, Object> finalMap = new HashMap<Object, Object>();
for(Map<?, ?> map : listOfMap){
//you can use putAll if you don't care about duplicates
//finalMap.putAll(map);
// or a more complex algorithm to handle duplicates
for(Entry<?, ?> e : map.entrySet()){
if(finalMap.containsKey(e.getKey())){
//do something to handle situation when key is duplicate...
//you may want to check if both values are equals and skip this
//maybe throw an exception if values are different
//or keep a value
throw new Exception("Duplicate: " + e);
} else {
//key does not exists, put it
finalMap.put(e.getKey(), e.getValue());
}
}
}
return finalMap;
}
}
And then use this transformer in your flow. See the docs for details.
You have multiple ways of doing this one of which is flatten operator which merges 2 arrays into a single array. The other is to do it through the Dataweave Transform map operator and merging them as per your requirements.

Differences between $.ajax type put and model.save in backbone.js?

There seems to be some differences between saving a model using this.model.save() and using jquery ajax type PUT?
I have the following method in my api controller
public void Put(string id, [FromBody]IContent value) {
// save
}
I have also enabled TypeNameHandling on JSON formatter serializer setting like this:
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto;
If I PUT some data using jquery ajax like this
$.ajax({
url: "/api/page/articles/1",
type: "PUT",
dataType: "json",
contentType: "application/json",
data: JSON.stringify({"$type": "BrickPile.Samples.Models.Article,BrickPile.Samples","id": "articles/1", "heading": "Some heading..." })
});
my object binds correct in the put method but when I try to save my object using model.save() in backbone the input value is null and it cannot bind the object?
This is how I do it:
this.model.set({ heading: 'foo' });
this.model.save();
the request headers seem to look ok and the payload is seems to be JSON, at least if I look in firebug. It's also possible to PUT some data to my api using fiddler with the same payload but not if I copy the payload source from firebug see: http://cl.ly/Nked
Can anyone explain what I'm doing wrong here?
Without knowing more about your model implementation it is hard to say for sure. One thing I can see from your firebug screenshot is that the id attribute is being passed as "articles/1" which is unusual for standard Backbone. If you were saving a model object then the id would normally be "1". So a model.save() would generate a HTTP PUT to articles/1 and pass the json as something including {"id":"1", ... }. The Backbone.sync documentation has more details on the default behaviour.