How to externalise repeated SOAP response attributes in mule dataweave? - soap

I am constructing a SOAP response in Dataweave. Certain components (ESBHeader) of the response are repeated in multiple flows. I also need to set the Status code and message per request.
I need a generic/common way of loading these repeated lines into a common dwl file for code optimisation. How do I do it?
Example Response Message1 of flow1
{
ns1#ResponseMsg1: {
ns0#ESBHeader: {
ns0#InitialContext #(CreationTime: flowVars.req.ResponseMsg1.ESBHeader.InitialContext.#CreationTime, TrackingID: flowVars.req.ResponseMsg1.ESBHeader.InitialContext.#TrackingID): {
ns0#Actor #(Component: flowVars.req.ResponseMsg1.ESBHeader.InitialContext.Actor.#Component , Operation: flowVars.req.ResponseMsg1.ESBHeader.InitialContext.Actor.#Operation): null
},
ns0#MessageContext : {
ns0#Actor #(Component: flowVars.req.ResponseMsg1.ESBHeader.MessageContext.Actor.#Component , Operation: flowVars.req.ResponseMsg1.ESBHeader.MessageContext.Actor.#Operation): null
},
ns0#Status: {
ns0#Code: "Success",
ns0#Message: ""
}
},
ns1#var1: flowVars.var1
}
}
Example Response Message2 of flow2
{
ns1#ResponseMsg2: {
ns0#ESBHeader: {
ns0#InitialContext #(CreationTime: flowVars.req.ResponseMsg2.ESBHeader.InitialContext.#CreationTime, TrackingID: flowVars.req.ResponseMsg2.ESBHeader.InitialContext.#TrackingID): {
ns0#Actor #(Component: flowVars.req.ResponseMsg2.ESBHeader.InitialContext.Actor.#Component , Operation: flowVars.req.ResponseMsg2.ESBHeader.InitialContext.Actor.#Operation): null
},
ns0#MessageContext : {
ns0#Actor #(Component: flowVars.req.ResponseMsg2.ESBHeader.MessageContext.Actor.#Component , Operation: flowVars.req.ResponseMsg2.ESBHeader.MessageContext.Actor.#Operation): null
},
ns0#Status: {
ns0#Code: "Failure",
ns0#Message: ""
}
},
ns1#var1: flowVars.var1,
ns1#var2: flowVars.x.var2
}
}
Any pointers are greatly appreciated.
Thanks a lot.

If you are using Mule 4 it is easy to create and import a DataWeave module.
In Mule 3 there is a similar method but it is not really supported and you could run into some issues. From your script it looks like Mule 3. This blog post explains the method.

Related

I can't succeed to correctly handle exceptions in NestJs

I'm trying to learn NestJs by creating a CRUD API.
I've created my controller, module, service etc...
And created a get users/id endpoint. Everything worked fine, and I decided to add some security.
I want to check if the id is not null and is a string. If not, I want to throw an exception (bad request) + console.log a message.
I also want to check if when I look for a user with a good if, the user exists. if not, throw a not found exception.
Here is my service:
async findOne(id: string): Promise<IUser | null> {
if (id === null || typeof id !== 'string') {
throw new BadRequestException('Id must be a string');
}
const user = await this.userModel.findById(id).exec();
if (user === null) {
throw new NotFoundException('No user found for this id');
}
return user;
}
and controller:
#Get(':id')
async find(#Param('id') id: string) {
try {
return await this.userService.findOne(id);
} catch (error) {
if (error instanceof BadRequestException) {
throw new HttpException(
{
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
},
HttpStatus.FORBIDDEN,
{
cause: error,
},
);
} else if (error instanceof NotFoundException) {
throw new HttpException(
{
status: HttpStatus.NOT_FOUND,
error: 'This is a custom not found message',
},
HttpStatus.NOT_FOUND,
{
cause: error,
},
);
}
}
}
The problem is when I try a get request with .../users/1111 ,I got a 200 response. And when I try with a good id (a string) but with no user linked, I also get a 200 response.
I don't understand why.. Can you help me please ?
I also want to log the message.
And have you any advices ? Is the right way (standard + elegant) to do ?
Thanks guys ;)
In your code you are checking id to be of a type string and not null. Technically any param is a string, so even 1111 becomes "1111". You can verify that by logging it like so console.log({ id }) (expected result: { id: "1111" }).
For the validation I would suggest to follow the documentation on validation pipes: NestJS documentation.
TLDR;
The following code will add a global pipe to validate payloads
app.module.ts (copied from NestJS | Pipes)
import { Module } from '#nestjs/common';
import { APP_PIPE } from '#nestjs/core';
#Module({
providers: [
{
provide: APP_PIPE,
useClass: ValidationPipe,
},
],
})
export class AppModule {}
To make it work you will need to have class-validator and class-transformer installed, so run:
npm i --save class-validator class-transformer
Then declare a class that will serve as a blueprint of a DTO (Data Transfer Object), like so:
import { IsString, IsNotEmpty } from 'class-validator';
export class IdDto {
#IsNotEmpty()
#IsString()
id: string;
}
Then in your controller use the IdDto:
#Get(':id')
async find(#Param() { id }: IdDto) {
...
This already should be enough to have a basic validation. Moreover, this will convert the payload to a format that you expect (or fail and throw validation error). It is done via plainToClass method exposed from class-transformer. So there won't be any surprises with JavaScript type coercion like "1" + 1 = "11".
If you need to format your exceptions (or enrich them with additional data) you can use exception filters. There is a nice documentation about it in the official documentation.
Hope that helps!

Drools: Executing multiple rules simultaneously via REST

I am new to drools. I want to fire multiple rules simultaneously depending on the condition.
I am using batch-execution command as follows, but it gives me error : "Bad request, no commands to be executed - either wrong format or no data"
{
"batch-execution":{
"lookup":"defaultKieSession",
"commands":[
{
"insert":{
"out-identifier":"TestAdvance",
"object":{
"LoanAdvance":{
"tenure":4,
"isBlacklisted":false
}
}
}
},
{
"insert":{
"out-identifier":"TestAdvance",
"object":{
"LoanAdvance":{
"tenure":3,
"isBlacklisted":false
}
}
}
},
{
"fire-all-rules":{
}
}
]
}
}
My rule in guided decision table looks like this:
I want to make a REST request to the rule engine and get the result set as a list.
Please confirm if my JSON request is correct. Or is there any better way to achieve the same?
Any help would be appreciated.
Thanks & Regards
you are using incorrect json request format. With JSON request payload no need to use ''batch-execution", remove that. And correct JSON request will look like as:
{
"commands":[
{
"insert":{
"out-identifier":"obj",
"object":{
"example.project4_91839699.Person":{
"firstName":"abc",
"lastName":"abc",
"hourlyRate":22,
"wage":100
}
}
}
},{
"insert":{
"out-identifier":"obj2",
"object":{
"example.project4_91839699.Person":{
"firstName":"xyz",
"lastName":"xyz",
"hourlyRate":24,
"wage":100
}
}
}
}
{
"fire-all-rules":""
}
]
}

Elastic search - Unable to filter the JSON exact body using RestClient

Trying to query the exact JSON body by using Elastic search with RestClient API, but getting the whole body as response with hits,_source,etc.
So tried the filter_path [[filter_path=hits.hits._source]] approach in order to resolve this, but even that won't help to fetch exact body and coming with _source tag as mentioned below filter_path Response.
Can any one suggest please howt to get the exact json body as response like
{ "testAcct":"1234" }
Client.java:-
RestClient client = RestClient.builder(
new HttpHost(HOST, 9200, HTTP)).build();
Response response1 = client.performRequest("GET", SERVICE_URL + "_search",
Collections.<String, String>emptyMap(), new BasicHeader("testAcct", "1234"));
System.out.println(EntityUtils.toString(response1.getEntity()));
Response:-
{
"took":6,
"timed_out":false,
"_shards":{
"total":1,
"successful":1,
"failed":0
},
"hits":{
"total":21,
"max_score":1.0,
"hits":[
{
"_index":"testindex",
"_type":"testexternal",
"_id":"AVmHwA7Pkw5MudRUOp-q",
"_score":1.0,
"_source":{
"testAcct":"1234"
}
}
}
]
}
filter_path Response:-
{
"hits":{
"hits":[
{
"_source":{
"testAcct":"1234"
}
}
}
}

Prediction request end up with "invalid data" errors

I get errors when posting prediction requests, but when posting the same requests from the online interface (from Google's API reference page) works well.
I have also posted a new issue on the Git repository, but it seems that no-one even looks at these issues. How lame of Google !!
Well I am posting predict request, which look like this:
var parameters = {
auth: jwtClient,
project: googleProjectID,
id: 'interest_classifier',
input: {
csvInstance: ["country united states", "/location/location"]
}
};
return prediction.trainedmodels.predict(parameters, function(err, response) {
if (err) {
logger.info(null, "prediction err ", err);
}
logger.info(null, "response from predict ", response);
return callback(null, response);
});
And I get this:
err { [Error: Input data invalid.]
code: 400,
errors:
[ { domain: 'global',
reason: 'invalidValue',
message: 'Input data invalid.' } ] }
To clarify: my trained model contains a value and two textual features.
Again, when running this from the online tool (client side) it works well, only when I run it from my node.js server, does it fail.
What's up with that? Anyone knows?
Could this be some encoding issue? request headers?
EDIT:
this is how i authenticate :
var jwtClient = new google.auth.JWT('*****#developer.gserviceaccount.com', 'keys/key.pem', null, ['https://www.googleapis.com/auth/prediction']);
jwtClient.authorize(function(err, tokens) {
logger.info(null, "authorizing");
if (err) {
logger.info(null, "error ", err);
} else {
return logger.info(null, "authenticated ", tokens);
}
});
OK,
So I've dug into Google's code and found out an important detail that is not properly documented.
I think this might be relevant to other people using this library, not only the ones who use google predict.
So most requests need to include a project id in the parameters, but in some cases you also need to include post data (like in my case).
I was trying to include this post data directly in the parameters like so :
var parameters = {
auth: jwtClient,
project: googleProjectID,
id: 'interest_classifier',
input: {
csvInstance: ["country united states", "/location/location"]
}
};
Now I found (this is not documented !!) that the whole part which belongs to the post data should be included within a "resource" field, like this:
var parameters = {
auth: jwtClient,
project: googleProjectID,
id: 'interest_classifier',
resource:{
input: {
csvInstance: ["country united states", "/location/location"]
}
}
};
I believe this will be relevant to any request which includes post data.
Cheers,
Ilan

Creating Job from REST API returns a request property name error

I have my Asset and MediaProcessor ready. Now I am trying to encode my asset. When I send the request specified in the tutorial (http://msdn.microsoft.com/en-us/library/jj129574.aspx):
{
"Name":"CurlTestJob",
"InputMediaAssets":[
{
"__metadata":{
"uri":"https://wamsbluclus001rest-hs.cloudapp.net/api/Assets('nb%3Acid%3AUUID%3A429967f5-4709-4377-bab2-4680ae2a0dd87')"
}
}
],
"Tasks":[
{
"Configuration":"H.264 HD 720p VBR",
"MediaProcessorId":"nb%3Ampid%3AUUID%3A2e7aa8f3-4961-4e0c-b4db-0e0439e524f5",
"TaskBody":"<?xml version=\"1.0\" encoding=\"utf-8\"?><taskBody><inputAsset>JobInputAsset(0)</inputAsset><outputAsset>JobOutputAsset(0)</outputAsset></taskBody>"
}
]
}
I get the following response
{
"odata.error":
{
code: "";
message:
{
lang: "en-US";
value: "Parsing request content failed due to: Make sure to only use property names that are defined by the type";
};
};
}
I am using api-version 2.2
Can someone explain to me where am I wrong?
Try setting the Header "DataServiceVersion: 2.0"
I ran into the same issue when using "DataServiceVersion: 3.0"
The error says that properties in json file does not match the properties in the deserialized type.
http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.mediaservices.client.iasset.aspx shows that IAsset has property Uri, but say nothing about __metadata. You could try to change your json to
"InputMediaAssets":[{
"Uri":"https://wamsbluclus001rest-hs.cloudapp.net/api/Assets('nb%3Acid%3AUUID%3A429967f5-4709-4377-bab2-4680ae2a0dd87')"
}],