Iterating DSS response in BPEL (WSO2 BPS) - bpel

I am using WSO2 BPS and WSO2 DSS.
DSS has 2 services as below:
(1) Returns list of status and
(2) Inserts a record into table.
I succeeded invoking both the DSS services from BPEL Workflow. But I need to achieve the following thing.
My 1st DSS will return "List of Status". I have to iterate(using 'forEach' or 'while' or ...) that response and pick particular node(StatusDescription) from it and use it for the next DSS call. My 1st DSS response is below.
<Response xmlns="http://ws.wso2.org/dataservice">
<Status>
<StatusId>1</StatusId>
<StatusDescription>Active</StatusDescription>
</Status>
<Status>
<StatusId>2</StatusId>
<StatusDescription>Inactive</StatusDescription>
</Status>
</Response>
Can anyone suggest some tutorial or code snippet that would iterate through above DSS response? i.e, My bpel:finalCounterValue will be '2' as there are 2 'Status' nodes in the above XML.
Thanks in Advance.

I found the the way to iterate the nodes. Please find the code snippet below.
<bpel:forEach parallel="no" counterName="Counter" name="ForEach">
<bpel:startCounterValue>
<![CDATA[1]]>
</bpel:startCounterValue>
<bpel:finalCounterValue>
<![CDATA[count($GetStatusPLResponse.parameters/ns:Status)]]>
</bpel:finalCounterValue>
<bpel:scope>
<!-- Some activity goes here. Say Assign or Invoke or .... -->
</bpel:scope>
</bpel:forEach>
The count method available under the namespace xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable" helps us to find count of nodes('Status').
The count method returns the value '2' and so 'forEach' iterates twice.
Have Happy Learning.

Related

How to parse and edit XML in TypeScript without converting to JSON

I need to repair an XML file in TypeScript and I cannot find any info on it, since everyone who posts something like this has different needs. I'd like to be pointed in the right direction here.
I have an XML request as shown below. It is autogenerated by node-soap when given JSON. Using the WSDL, node-soap attempts to fill in the namespace prefixes for each property. The problem is, it gets them wrong a lot.
In this example below, q106 should be replaced with hep3.
<soap:Envelope q15="some-good-url" q106="some-good-url-1" q98-"some-good-url-2>
...
<q98:SalesOrderAuditInfo>
<q15:ConfirmedBy xsi:nil="true"></q15:ConfirmedBy>
<q15:ConfirmedDate>0001-01-01T00:00:00</q15:ConfirmedDate>
<q15:CreatedBy>
<q106:ID>103</q106:ID>
<q106:Value>System, System</q106:Value>
</q15:CreatedBy>
<q15:CreatedDate>2022-10-26T00:43:13.413</q15:CreatedDate>
<q15:SalesOrderType>Standard</q15:SalesOrderType>
</q98:SalesOrderAuditInfo>
I know which namespace prefixes are bad because I have a sample request that was supplied to me. It's just XML. It looks like this:
<soap:Envelope hep="some-good-url" hep1="some-good-url-1" hep2-"some-good-url-2 hep3="some-good-url-3">
...
<hep2:SalesOrderAuditInfo>
<hep:ConfirmedBy xsi:nil="true"></hep:ConfirmedBy>
<hep:ConfirmedBy:ConfirmedDate>0</hep:ConfirmedByConfirmedDate>
<hep:CreatedBy>
<hep3:ID>103</hep3:ID>
<hep3:Value>System, System</hep3:Value>
</hep:CreatedBy>
<hep:CreatedDate>0</hep:CreatedDate>
<hep:SalesOrderType>Standard</hep:SalesOrderType>
</hep2:SalesOrderAuditInfo>
Here is the part that really matters. The Sample Request is the entire possible request body. The supplied request (with incorrect namespaces) is a subset of the sample request. I need to loop through each of the elements in the supplied request, and check to make sure the URL of that element matches the URL of the respective element in the sample request.
So in this example, loop through each element of supplied request. Start with SalesOrderAuditInfo. It's namespace URL is some-good-url-2. If we check the Sample Request, we can see that SalesOrderAuditInfo also corresponds to some-good-url-2.
Continue until we hit the ID tag. This has a namespace set to some-good-url-1. If we check the Same ID (inside of CreatedBy, inside of SalesOrderAuditInfo), we can see the namespace should actually be set to some-good-url-3. So we replace q106 with hep3.
I also need to take all of the namespaces defined in the Sample Request Envelope and move them into the supplied request envelope so that this new hep3 will be defined.
At this point, I need to edit the namespace prefix. In this example, q106:ID would be replaced be the string hep3:ID. Same with all of the closing tags.
Which library can I use to accomplish this in XML? Is anyone familiar with node-soap screwing these namespaces up and know of any fix?
I am using node-soap v0.43

Replace/Update a existing node value in groovy

Below is my sample xml.
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header>
<MessageHeader xmlns:ns3="http://csi.cingular.com/CSI/Namespaces/Types/Public/CingularDataModel.xsd" xmlns:ns39="http://csi.cingular.com/CSI/Namespaces/Types/Public/MessageHeader.xsd">
<ns39:TrackingMessageHeader>
<ns3:infrastructureVersion>86</ns3:infrastructureVersion>
<ns3:version>222</ns3:version>
<ns3:messageId>146100035386400076</ns3:messageId>
<ns3:originatorId>PEEPS</ns3:originatorId>
<ns3:timeToLive>120000</ns3:timeToLive>
<ns3:dateTimeStamp>2016-04-18T20:16:19.387Z</ns3:dateTimeStamp>
</ns39:TrackingMessageHeader>
<ns39:SecurityMessageHeader>
<ns3:userName></ns3:userName>
<ns3:userPassword></ns3:userPassword>
</ns39:SecurityMessageHeader>
<ns39:SequenceMessageHeader>
<ns3:sequenceNumber>1</ns3:sequenceNumber>
<ns3:totalInSequence>1</ns3:totalInSequence>
</ns39:SequenceMessageHeader>
</MessageHeader> </SOAP-ENV:Header> <SOAP-ENV:Body>
<InquireEnterpriseOrderListRequest xmlns="http://csi.cingular.com/CSI/Namespaces/InquireEnterpriseOrderListRequest.xsd">
<SelectionCriteria>
<organizationId>214256542</organizationId>
</SelectionCriteria>
</InquireEnterpriseOrderListRequest> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
I want to replace "organizationId" this tag value with the value read from file and trigger it using testRunner.runTestStepByName("InquireEnterpriseOrderList") once the value is updated in the node.
Can any help in understanding how to update/replace node with new value and re-trigger the API to capture result for many inputs.
Here you what you need to do:
Read file extract the required value and store it at test case level custom property. Assuming that you are using groovy script test step to do this. So, add the below additional code:
//You assign value from your code, for now using dummy assignment
def requiredvalue = '123453'
//Store that value at test case level custom property, say ORGANIZATION_ID
context.testCase.setPropertyValue('ORGANIZATION_ID', requiredValue.toString())
Now, you do not need to update the request. Instead use, property expansion as below, so that SoapUI automatically takes care of the required value from proerties
<organizationId>${#TestCase#ORGANIZATION_ID}</organizationId>

MarkLogic - node.js Client API - queryBuilder query array of IDs

This question is similar to:
MarkLogic - XQuery - cts:element-range-query using variable length sequence or map
But this time I need to do the query using the queryBuilder in the node.js client API.
I have a collection of 100,000 records structured like this:
<record>
<pk>1</pk>
<id>1234</id>
</record>
<record>
<pk>2</pk>
<id>1234</id>
</record>
<record>
<pk>3</pk>
<id>5678</id>
</record>
<record>
<pk>4</pk>
<id>5678</id>
</record>
I have setup a range index on id.
I want to write a query using the queryBuilder node.js client API that will allow me to pass in an array of IDs and get out a list of records.
It needs to:
1) query a specific collection
2) leverage the range indexes for performance
Nevermind, I figured out the problem.
db.db.documents.query(
q.where(
q.collection('Records'),
q.or(
q.value('id', ['1', '2'])
)
).slice(1, 99999999)
)
I originally tried to pass an array into q.value and I was only getting limited results (Got 10 when I expected 20). So I was under the impression that I was doing it wrong.
It turns out I just needed to slice the where clause to include everything. Apparently if you don't specify how much to take it defaults to 10.
Also note that when I tried .slice(0) which would have been preferred, I got an exception.

How can I clear an external ID on a record in NetSuite?

I need to clear/reset the external ID on a record in NetSuite, but nothing I do is working.
Some of the InventoryItem records are incorrectly mapped to records in another system. I have an application that can sync up the two systems, but I need to clear NetSuite's external IDs first.
Responses don't really need to be SOAP-specific. If you know how to do it with some specific NetSuite/SuiteTalk client, that might point me in the right direction.
What I've Tried
First up, I tried using the nullFieldList... but maybe it doesn't work because externalId is an attribute, not an element?
<messages:update>
<messages:record internalId="7777" xsi:type="accounting:InventoryItem">
<core:nullFieldList xsi:type="core:NullField">
<core:name>externalId</core:name>
</core:nullFieldList>
</messages:record>
</messages:update>
The external ID is just a string, so I tried just setting it to blank. Didn't work either.
<messages:update>
<messages:record internalId="7777" xsi:type="accounting:InventoryItem">
<accounting:externalId></accounting:externalId>
</messages:record>
</messages:update>
I even tried setting the external ID to 0, but I get back a "not unique identifier" error
<messages:update>
<messages:record internalId="7777" xsi:type="accounting:InventoryItem">
<accounting:externalId>0</accounting:externalId>
</messages:record>
</messages:update>
Other Info
I'm using NetSuite's SOAP API v.2013_1
When I say "it doesn't work", I mean: after I do the update, I get a success response similar to the following:
<readResponse>
<platformCore:status isSuccess="true" xmlns:platformCore="urn:core_2013_1.platform.webservices.netsuite.com"/>
<record internalId="7777" externalId="42" xsi:type="listAcct:InventoryItem" xmlns:listAcct="urn:accounting_2013_1.lists.webservices.netsuite.com">
<!-- snip -->
</record>
</readResponse>
If you are using scripts in netsuite you can run a scheduled script to clear records in NS by loading each record and setting the externalid to '' using the following simple code:
var rec= nlapiLoadRecord(type,id);
rec.setFieldValue('externalid','');
nlapiSubmitRecord(rec);
This seemed to work for me in my enviornment which was on 2015.2.
Unfortunately my understanding is that once you set an externalid you cannot clear it, you can set it to another value, but not back to null. I have experienced this both using SuiteScript as well as a Boomi process that uses the 2014.1 endpoint. This may have changed in the recent releases, as I have not tried it recently with SuiteScript nor with a newer endpoint.
You can eliminate the externalId on a record once it's been set. Here's an example using the NetSuite gem:
ns_customer = NetSuite::Records::Customer.get external_id: 'ext_id'
ns_customer.external_id = ''
ns_customer.update
Here's the corresponding XML for update:
<env:Body>
<platformMsgs:update>
<platformMsgs:record xsi:type="listRel:Customer" platformMsgs:internalId="199113" platformMsgs:externalId=""/>
</platformMsgs:update>
</env:Body>
I have had to attempt this before as well. I know the pains you describe. I ended up putting a "-" in front of my external ID to unlink it between my systems. You can do this in SOAP or even as a simple one time csv upload. As it was one time, I did csv.

WSO2 - Using get-property() function in Property/Xquery Mediators

Our current service has 7 operations. when writing an outbound xquery "local entry" in wso2, we're trying to retrieve the name of the current operation being executed (how can this be so difficult?).
After reading what i could find in wso2's documentation. it appears as if we need to set up both a Property and an Xquery mediator. supposedly the property mediator would pull the value doing something like get-property('OperationName') and then this would be referenced and passed thru the Xquery mediator.
The other idea was that we needed to define it as a variable in the "Local Registry entry definitions" and than it would be around at all parts of the sequence.
I've tried for 2 days but haven't quite got it.
Please tell me what I'm missing...
Did you try the following xquery sample[1]? I modified the query mediator to get the operation name as follows.
<variable xmlns:ax21="http://services.samples/xsd" xmlns:m0="http://services.samples" name="code" expression="get-property('OperationName')" type="STRING" />
this worked fine. I could see the getQuote in the response message.
[1] http://wso2.org/project/esb/java/4.0.2/docs/samples/advanced_mediation_samples.html#Sample390

Resources