Code Examples

The following JavaScript code examples are available from the code editor within API Creator. They are drawn from the sample APIs (Demo, Sample, Pavlov, and B2B Northwind), so you can study the code in context.
lac32
The following JavaScript code examples are available from the code editor within API Creator. They are drawn from the sample APIs (
Demo
Sample
Pavlov
, and 
B2B Northwind
), so you can study the code in context.
In this article:
 
 
General-use Patterns
The following examples are common patterns that you can use in any type of code.
Iterate Over Arrays
For any array, you can iterate using the following code snippet:
var items = row.lineitems;
for (i in items) {
log.debug("Found a line item: " + items[i].name);
}
// Same thing but different approach
for each (item in row.lineitems) {
log.debug("Found a line item: " + item.name);
}
Catch Exceptions
You can catch exceptions and process them by surrounding your code, including calls to Java, with try/catch blocks.
 
Example:
 
try {
// This will throw a NullPointerException
Java.type("java.lang.Long").parseLong(null);
}
catch(e) {
// The exception is caught here
log.debug("Got an exception: " + e);
}
Throw Exceptions
You can throw exceptions, for example, if your code detects an error condition and you cannot handle that error. The engine catches the error and stops processing the request.
 
Example:
 
if (row.price < 0) {
throw "Impossible condition: product " + product.name + " has a negative price";
}
Invoke a Command Line
Use this example to invoke a command from the operating system on which the server is running. This example show how to execute a Python script, but you can issue any command that can be run from the command line using this method.
This example uses the 
Runtime
 Java class, which offers several ways of invoking a process. It also uses the 
IOUtils
 Apache Commons class.
For more information:
 
Example
 
// Start an arbitrary process
var process = Java.type("java.lang.Runtime").getRuntime().exec("/usr/bin/python myScript.py " + row.myColumn);
// Optional: if you're interested in the output of the command. Note that the command will be running
// in a different process, therefore if you want to get the full output, you may have to wait until
// the process ends.
var output = Java.type("org.apache.commons.io.IOUtils").toString(process.inputStream, "UTF-8");
// Optional: if you're interested in the return value of the process. If the process has not yet finished,
// this will throw an exception.
if (process.exitValue() != 0) {
// Something probably went wrong -- the process did not return 0
}
Sending an email
Depending on your email provider, sending an email can be as simple as:
var props = new java.util.Properties(); props.put("mail.smtp.host", "mail.acme.com"); props.put("mail.debug", "true"); var Session = Java.type("javax.mail.Session"); var mailSession = Session.getInstance(props, null); var MimeMessage = Java.type("javax.mail.internet.MimeMessage"); var msg = new MimeMessage(mailSession); var InternetAddress = Java.type("javax.mail.internet.InternetAddress"); msg.setFrom( new InternetAddress("[email protected]")); var Message = Java.type("javax.mail.Message"); msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]")); msg.setSentDate(new java.util.Date()); msg.setSubject(parameters.subject); msg.setText(parameters.text); var Transport = Java.type("javax.mail.Transport"); Transport.send(msg);
Many, if not most, mail servers require authentication. If you need to send more than a few emails, you probably want to use a service like Amazon SMS or MailChimp, which have their own API.
With authentication, this sample is:
var props = new java.util.Properties();
props.put("mail.smtp.host", "smtp.mail.yahoo.com");
props.put("mail.debug", "true");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
var Authenticator = Java.type("javax.mail.Authenticator");
var auth = new Authenticator ({
getPasswordAuthentication: function() {
var PasswordAuthentication = Java.type("javax.mail.PasswordAuthentication");
return new PasswordAuthentication("[email protected]", "secret");
}
});
var Session = Java.type("javax.mail.Session");
var mailSession = Session.getInstance(props, auth);
var MimeMessage = Java.type("javax.mail.internet.MimeMessage");
var msg = new MimeMessage(mailSession);
var InternetAddress = Java.type("javax.mail.internet.InternetAddress");
msg.setFrom( new InternetAddress("[email protected]"));
var Message = Java.type("javax.mail.Message");
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("[email protected]"));
msg.setSentDate(new java.util.Date());
msg.setSubject("This is a test email");
msg.setText("Hi Jane,\n\nthis is a test email.\n\nSee you later,\n\n-- Joe\n");
var Transport = Java.type("javax.mail.Transport");
Transport.send(msg);
Validations
Validations are expressions assigned to an entity that must be true for a transaction to commit. The New/Old Values JavaScript code example is available from the validation rule code editor.
For more information about how to create validation rules, see Validation Rule Type.
New/Old Values
The following example verifies that employee salaries are not decreased: 
return row.base_salary >= oldRow.base_salary;
This code example is available from the validation rule code editor.
Custom Endpoints
You can define arbitrary new RESTful endpoints in JavaScript using custom endpoints. The Non-JSON endpoints JavaScript code example is available from the custom endpoint code editor.
For more information about how to run custom endpoints, see Custom Endpoints.
Non-JSON Endpoints
You can return non-JSON responses, such as this HTML for browser execution. The Business to Business (B2B) sample defines the 
Menu
 custom endpoint, as shown in the following code snippet:
var html = "<!DOCTYPE html>\n";
html += "<html>";
html += "<body>";
html += "<title>B2B Menu</title>";
html += "<p>Illustrates you can build simple html pages - no deploy";
html += "<p>.. See Custom Endpoints (disable Short Menus)";
html += "<h1>B2B Documentation</h1>";
html += "<a href='https://docops.ca.com/ca-live-api-creator/3-2/en/getting-started/business-to-business-example' target='_blank'>Docs</a>";
html += "<h1>B2B Execution</h1>";
html += "<a href='http://localhost:8080/DataExplorer/index.html#/?serverName=http:%2F%2Flocalhost:8080%2Frest%2Fdefault%2Fb2bderbynw%2Fv1%2F&forceLogin=true' target='_blank'>Run Data Explorer</a>";
html += "</body>";
html += "</html>";
responseHeaders.put('Content-Type', 'text/html');
return html;
This code example is available from the custom endpoint code editor.
Logic Events
API Creator invokes events with the current/old table rows on POST, PUT, and DELETE operations.
The following JavaScript code examples are available from the event rule code editor:
 For more information about how to create a event rule types, see Logic Event Rule Types.
Allocation
In this example, when a Customer Payment is added, the business logic allocates a provider's 
Payment.amount
 to designated Purchase Orders 
recipient
, creating Payment Purchaseorder Allocation allocation objects (a provider/recipient junction) for each such allocation. 
Payment_order_allocations
 logic determines the exact amount allocated.
For more information about the 
allocateFromTo
 system method, including detailed information about this example, see allocateFromTo System Method.
 
Example
 
The following code snippet shows the code for allocating a payment to outstanding orders by way of a rule:
if (logicContext.verb == "INSERT") {
SysLogic.allocateFromToUndisbursed(
logicContext,
SysLogic.findWhere(
row.paymentCustomer.ordersList,
"row.is_ready == true && row.amount_un_paid > 0",
"placed_date a"),
"payment_order_allocations",
"amount_un_disbursed");
}
This code example is available from the event rule code editor.
Auditing
This example creates a child 
purchaseorder_audit
 row if the purchaseorder's 
amount_total
 is changed. This is often called state transition logic. API Creator does the following:
  • Compares the old/new values of the 
    amount_total
     using the row/oldRow supplied variables.
    The row/oldRow variables are part the JavaScript object model that API Creator builds. For more information about the object model, see Row Objects.
  • Creates the 
    purchaseorder_audit
     row either by direct code or by 
    SysLogic.insertChildFrom
    .
    For more information about the 
    InsertIntoFrom
     system method for auditing rule type, see Rule Types.
 
Example
 
The following code snippet shows the code for the auditing JavaScript code example:
if (row.amount_total != oldRow.amount_total) {
var newPurchaseorder_audit = logicContext.createPersistentBean("purchaseorder_audit");
newPurchaseorder_audit.amount_total = oldRow.amount_total; // set attributes from old values
newPurchaseorder_audit.paid = oldRow.paid;
newPurchaseorder_audit.customer_name = oldRow.customer_name;
newPurchaseorder_audit.order_number = oldRow.order_number; // set the foreign key
logicContext.insert(newPurchaseorder_audit); // saves (fires logic)
}
// better: re-use alternative using System or your own Loadable Libraries:
// if (row.amount_total != oldRow.amount_total) {
// SysLogic.insertChildFrom("purchaseorder_audit", logicContext);
// }
This code example is available from the event rule code editor.
Event Sourcing (RPC-style APIs)
Table event handlers are invoked with the current/old table rows on POST, PUT and DELETE operations.
In this example you can update (parent) employee salaries when a row is inserted into (child) EmployeeRaises: 
  1. We define the event for table EmployeeRaises, inserts only as shown here. 
  2. We invoke a shared library routine 
    B2B.copyAttributes
    . to copy like-named attributes from the source row (EmployeeRaises, wrapped in logicContext) to the parent (Employee) Row. We obtain the parent row through the parent accessor, part of the automatically created Object Model.
Example
 
The following code snippet shows the code for the Event sourcing (RPC-style APIs) JavaScript code example:
B2B.copyAttributes(logicContext, row.EmployeeRaises_OwnedBy_Employees);
This code example is available from the event rule code editor.
Posting WebHooks
Use this example to send an inserted or altered order to a supplier, formatted per a resource ShipperAPIDef:
  1. We obtain the shipper (if any); if there is one.
  2. We invoke 
    transformCurrentRow
     to transform the order into the required format, including related data such as items in the order.
  3. The transformation is defined by declaring a custom resource (ShipperAPIDef), where you can choose/alias attributes, include related data, etc.
  4. Invoke the 
    B2B.sendToWebHook
     re-usable JavaScript library function to post the transform.
 
Example
 
The following code snippet shows the code for the Posting WebHooks JavaScript code example:
// object model (row) provides accessors to related objects var shipper = row.FK_Orders_Shippers; if (shipper !== null) { // resource defines transform: cols, aliases, related objects var transform = logicContext.transformCurrentRow("ShipperAPIDef"); // find with code completion B2B.sendToWebHook(transform, shipper.webHookURL); // loadable library (API Properties > Libraries) }
This code example is available from the event rule code editor.
Formulas
Formulas are derivation rules that compute the value of a table or view column. Formulas can reference other columns in the row as 
row.attribute
, as well as parent columns.
You can get a list of attribute names using the 
Control-Space
 keys on your keyboard.
You specify rules using JavaScript notation. This supports normal JavaScript services for if/else, looping, and date datatype handling.
The following JavaScript code examples are available from the formula rule code editor:
For more information about how to create formula rule types, see Formula Rule Type.
If/Else Logic
Use this example to compute the amount of line item as price*quantity, conditionally applying a discount.
 
Example
 
The following code snippet shows the code for the If/Else logic JavaScript code example:
if (row.qty_ordered <= 6) { // discount (using conditional JavaScript logic) return row.product_price * row.qty_ordered; } else { return row.product_price * row.qty_ordered * 0.8; }
This code example is available from the formula rule code editor.
Dealing with dates
You can compute the 
due_date
 from the 
placed_date
, if it has not already been set.
This example uses the 
moment.js
 system library for date handling. You must make this library available inside your API to use this example in JavaScript logic.
For more information about how to make this library available, see Logic Libraries.
 
Example
 
The following code snippet shows the different types of date values that are acceptable:
if (row.due_date === null) {
// specify use of moment() library;
return new Date(moment(row.placed_date).add('months', 1));
}
else {
return row.due_date;
}
/*
You can also manipulate dates as follows:
var due_date = row.getRawObject("due_date");
if (due_date === null) {
var SimpleDate = Java.type("com.kahuna.util.SimpleDate");
due_date = SimpleDate.valueOf("2016-12-31");
// due_date = new SimpleDate(2016,12,31);
// due_date = SimpleDate.fromJavaUtilDate(row.placed_date); //use existing placed_date
// due_date = new Date(row.placed_date);
// due_date = "2016-12-31";
}
*/
This code example is available from the formula rule code editor.
Dealing with times
You can check to see if the current attribute CurrentTime is null and calculate a default value.  
 
Example
 
The following code snippet shows the different types of time values that are acceptable:
var time = row.getRawObject("CurrentTime");
if (time === null) {
var SimpleTime = Java.type("com.kahuna.util.SimpleTime");
time = SimpleTime.valueOf("23:59:59");
// time = new Date();
// time = "23:59:59";
// time = "23:59:59.123456789012";
// time = new SimpleTime(23, 59, 59, 123456789012); // hour, minute, second, picos
// time = SimpleTime.fromJavaUtilDate(new Date());// time on server
}
return time;
This code example is available from the formula rule code editor.
Dealing with timestamps
You can check to see if the current attribute CurrentTimestamp is null and calculate a default value.  
 
Example
 
The following code snippet shows the different types of timestamp values that are acceptable:
var sts = row.getRawObject("CurrentTimestamp");
if (sts === null) {
var SimpleTimestamp = Java.type("com.kahuna.util.SimpleTimestamp");
sts = SimpleTimestamp.valueOf("2016-12-31T23:59:59");
// sts = new Date();
// sts = "2016-12-31T23:59:59.123456789012";
// sts = new SimpleTimestamp(2016, 12, 31, 23, 59, 59, 123456789012); //year, month, day, hour, minute, second, picos
// sts = SimpleTimestamp.fromJavaUtilDate(new Date()); // time on server
}
return sts;
This code example is available from the formula rule code editor.
Dealing with timestamps with offset
You can check to see if the current attribute CurrentTimestamp (with GMT offset) is null and calculate a default value. 
Example
 
The following code snippet shows the different types of values that are acceptable:
var stso = row.getRawObject("CurrentTimestamp");
if (stso === null) {
var SimpleTimestampOffset = Java.type("com.kahuna.util.SimpleTimestampOffset");
stso = SimpleTimestampOffset.valueOf("2016-12-31T23:59:59-05:00"); // New York from GMT
// stso = new Date();
// stso = "2016-12-31T23:59:59+05:00";
// stso = "2016-12-31T23:59:59.123456789012GMT";
// stso = new SimpleTimestampOffset(2016, 12, 31, 23, 59, 59, 123456789012, false, 5, 0); // year, month, day, hour, minute, second, picos, offsetPositive, offsetHours, offsetMinutes
// stso = SimpleTimestampOffset.fromJavaUtilDate(new Date()); // time on server
}
return stso;
This code example is available from the formula rule code editor.
Functions
Functions are coded in JavaScript, with full access to the JavaScript libraries and Java JAR files. They are user-defined endpoints that:
  • You can associate with one or more tables, views, and/or normal resources.
  • Can have optional input parameters.
  • Should return a proper JSON response.
  • Are authenticated.
  • Are included in Swagger documentation.
The following JavaScript code examples are available from the functions code editor:
For more information about how to create functions and define the JavaScript code in functions, see Manage Functions.
Resource-Oriented Functions
Use this example to create a function associated with an entity and a resource.
 
Example
 
The following code snippet shows the code for the Row Operations (methods) JavaScript code example:
var theRaise = parameters.percentRaise * (row.Salary/100);
row.Salary += theRaise; // runs logic, persists change row(s) to database...
return [ {"status": "Success"}, {"raise": theRaise} ];
/*
This works with the Employees Table:
http://localhost:8080/rest/default/b2bderbynw/v1/nw:Employees/1/giveRaise?percentRaise=10
It also works with the EmployeesWithRaises Custom Resource, even though the Salary field as aliased.
The 'row.Salary' reference above works because the system has already performed Resource/Object Mapping.
So, row is a *table* row. This enables you to re-use the function over many Resources.
http://localhost:8080/rest/default/b2bderbynw/v1/EmployeesWithRaises/1/giveRaise?percentRaise=10
*/
This code example is available from the functions code editor.
Top-Level Functions
Use this example to create a function not associated with a table.
 
Example
 
The following code snippet shows the code for the Code (unrelated to data row) JavaScript code example:
// Trivial example: find greatest common divisor for two positive numbers
// with a URL like: http://localhost:8080/rest/default/demo/v1/gcd
//
var div = 2
var gcd = 1;
if (parameters.n1 < 2 || parameters.n2 < 2) {
return {
n1: parameters.n1,
n2: parameters.n2,
gcd: 1,
message: "One or both of your parameters were less than 2, so the result is 1"
};
}
if (parameters.n1 > 1000000000000 || parameters.n2 > 1000000000000) {
return {
n1: parameters.n1,
n2: parameters.n2,
gcd: null,
message: "One or both of your parameters were greater than 1,000,000,000,000, so the result is too expensive to compute"
};
}
while (parameters.n1 >= div && parameters.n2 >= div) {
if (parameters.n1%div === 0 && parameters.n2%div === 0) {
gcd = div;
}
div++;
}
return {
n1: parameters.n1,
n2: parameters.n2,
gcd: gcd
};
This code example is available from the functions code editor.
Request/Response Events
Request events fire prior to system processing, where you can alter the Request JSON. Response events fire after all system processing, giving you an opportunity to change the response before it is sent to the caller.
The following JavaScript code examples are available from the request and response event code editor:
For more information about how to create request and response events, see Event Handlers.
Insert Lookup and Merge-Insert Actions
Use this example to insert metadata actions that activate system services to:
  • Lookup foreign keys.
  • Merge-Insert: cause request row to be updated, or inserted if they do not exist.
You must specify the resource property part of the defined key for the attributes used for the lookup/match.
This code example is available from the request events code editor.
 
Lookup
 
External systems typically cannot know internal keys such as part numbers, so the API must accept part names and look up the associated foreign key.
This example uses the 
insertActions.js
 & 
jsonpath-0.8.0.js
 JavaScript libraries from the B2B example quick install. You must make this library available inside your API to use this example in JavaScript logic.
The request event defined in this example does the following:
  • Inserts action tags to activate lookup processing.
  • Defines an array of resource names, paths, and associated insert tags.
  • Invokes a shared library routine to insert actions.
  • The API Server processes the transformed request.
    For more information about metadata tags for parent lookup, see Explore B2B.
 
Example
 
The following code snippet shows the code for the Insert lookup and merge-insert actions, to the PartnerOrder resource. The third action within this code snippet activates Merge-Insert processing for posts to the SupplierSelfService resource. This enables Suppliers (the source of data) to update or create their information.
var actions = [ {resource: "PartnerOrder", path: "$..Product", insertActions: "LOOKUP"}, {resource: "PartnerOrder", path: "Shipper", insertActions: "LOOKUP"}, {resource: "SupplierSelfService", path: "", insertActions: "MERGE_INSERT"} ]; json = insertActions.insertActions(req, json, actions); // API Server processes this... // log.debug("requestEvent json: " + json);
 
Merge Insert
 
The previous code activates Merge-Insert processing for posts to the SupplierSelfService resource. This enables Suppliers (the source of data) to maintain their information by posting a request for their organization: 
  1. If their Supplier row does not exist, insert the row.
  2. If their Supplier row exists, update the row (merge).
For more information:
Reformat Request
In this example, our API agreement with external systems or partners may designate a request format different from the standard formats 
CA Live API Creator
 supports. As illustrated in the Business to Business (B2B) sample, in the Pavlov API, you can define request events to transform the incoming request:
  1. Restrict the transformation to POST operations on the SalesReports resource.
  2. Alter the JSON.
    The API Server now processes the transformed request.
 
Example
 
The following code snippet shows the code for the Reformat request JavaScript code example:
if ("SalesReports" == req.resourceName && req.verb.toString() == 'POST') {
// log.debug('***SalesReports Req Event - json: ' + json);
var data = JSON.parse(json); // json from the request
if(Array.isArray(data) && data.length > 0) {
var theOrder = data[0];
var keptItemNum = 0;
var keptItems = [];
log.debug("theOrder: " + JSON.stringify(theOrder));
for ( var i = 0; i < theOrder.Order_DetailsList.length; i ++) {
var eachItem = theOrder.Order_DetailsList[i];
delete eachItem["@metadata"];
if (eachItem.SupplierName == "Pavlova, Ltd.") {
delete eachItem.OrderID;
delete eachItem.ProductID;
delete eachItem.Quantity;
delete eachItem.SupplierName;
eachItem.CompanyName = theOrder.CompanyName;
log.debug("*********keep item: " + JSON.stringify(eachItem));
log.debug("from Order: " + JSON.stringify(theOrder));
keptItems[keptItemNum] = eachItem;
keptItemNum ++;
}
}
log.debug("Kept Items"); log.debug(keptItems);
json = JSON.stringify(keptItems); // Important: you must serialize the data back to a string if you want to change it
}
log.debug('***SalesReports Req Event - ALTERED json: ' + json);
}
This code example is available from the request events code editor.
Reformat Response
In this example, our API agreement with external systems/partners may designate a response format different from the standard formats 
CA Live API Creator
 supports. As illustrated in the Sample API, you can define request events to transform the outgoing response:
  1. Restrict the transformation to POST operations on Resource PartnerOrders.
  2. Alter the JSON.
    The API Server now returns the transformed response.
 
Example
 
The following code snippet shows the code for the Reformat response JavaScript code example:
var reqResourceName = req.resourceName;
if ("POST" == req.verb && "PartnerOrder" == reqResourceName) {
delete json.txsummary; // remove from response
delete json.rulesummary;
var reqJson = JSON.parse(req.json); // convert req's JSON string to JSON objects
var custName = reqJson.customer; // get the name from the request (e.g., 'Max Air')
var options = { filter: "\"name\" = '" + custName + "'" };
// so.. http://localhost:8080/rest/default/sample/v1/cust?filter="name"='Max Air'
var custAccount = SysUtility.getResourceAsString("cust", options); // get resource JSON
log.debug("***return account summary as response: " + custAccount);
json.accountSummary = JSON.parse(custAccount); // inject into response
}
This code example is available from the request events code editor.
Resource Row Events
Use the JavaScript resource type to write server-side JavaScript code that is executed whenever the resource is accessed.
The following JavaScript code examples are available for resources:
Service Calls to Integrate External Data
Use this example to make a call to an outside REST services and connect to multiple servers of any type. Your JavaScript code is responsible for retrieving data and for formatting it into JSON. Use containingRow to access data from the containing resource. 
Use 
req.json
 if you POST to your JavaScript resource endpoint. This contains the payload passed by the client.
 
Example
 
The following code snippet shows the code for the Details Event JavaScript code example:
var url = req.baseUrl; log.debug(url); // this is the base URL for this server url = url.replace("/demo","/sample");// compute baseURL of target system url = url + "v1/orders"; // add version/ resource endPoint on target var key = containingRow.name; // containingRow is system supplied log.debug("..using key: " + key + ", and url: " + url); key = JSON.stringify(key, null, 0); var params= { sysfilter: "equal(customer_name:" + key + ")" }; //special Auth Token in this project to allow access from url (?auth=AdminKey:1) var settings = { headers: { Authorization: "CALiveAPICreator AdminKey:1" } }; //////////// Built in utility to make REST GET call var response = SysUtility.restGet(url, params, settings); return JSON.parse(response);
This code example is available from the code editor for JavaScript resources.
Row Event
Provide JavaScript that is executed for each row, for example, alter/create attributes.
For more information about how to create resource row events, see Resource Row Events.
New attributes are not reflected in the Swagger definition. We recommend using non-persistent attributes.
For more information about how to create non-persistent attributes, see Manage Non-Persistent Attributes 
 
Example
 
The following code snippet shows the code for the Row Event JavaScript code example. A new attribute called foo is created:
row.foo = 'these reps have sold more than 20 items';
This code example is available from the resource row event code editor.
User Libraries
User libraries are logic libraries contain JavaScript functions that you can reuse across APIs. You can use user libraries from your logic, for example, formulas, events, validations, and functions.
The following JavaScript code examples are available for user libraries:
For more information about user libraries, see Logic Libraries.
Authentication Provider
Use the exampleauthprovider.js example to create a custom authentication provider, such as OAuth, Microsoft Azure Active Directory (AD), Lightweight Directory Access Protocol (LDAP), that authenticates against a database table.
For more information about creating custom authentication providers, see Create Custom Authentication Providers using JavaScript.
Saving State
Use this example to create a function that can save data between table event handlers.
 
Example
 
The following code snippet shows the code for the Saving State JavaScript code example:
/* you can save state in logicContext.userProperties, including complex objects such as Maps to save (e.g., from event-1):
B2B.putPropertyMap(logicContext, "order.supplierHooks", supplier.CompanyName, supplier.URL);
to retrieve (e.g., from event-2):
var webHooks = req.getUserProperties().get("order.supplierHooks"); // userProperties to maintain state in transaction
*/
B2B.putPropertyMap = function putPropertyMap(logicContext, propertyName, key, value) {
var RestRequest = Java.type('com.kahuna.server.rest.RestRequest');
var req = RestRequest.getCurrentRestRequest();
logicContext.logDebug("*** B2B.putPropertyMap - propertyName: " + propertyName + ", key: " + key + ", value: " + value + ", on req: " + req);
var property = req.getUserProperties().get(propertyName); // userProperties to maintain state in transaction
if (property === null) {
var HashMap = Java.type('java.util.HashMap');
property = new HashMap();
}
property.put(key, value);
req.setUserProperty(propertyName, property);
};
This example is available in the 
B2B.js
 JavaScript library from the B2B sample quick install. You must make this library available inside your API to use this example in JavaScript logic.
For more information about the B2B quick install, including how add the 
B2B.js
 JavaScript library, see Install B2B.