Interested in a ServiceNow event built for developers? Registration for now[dev]26 is officially open!

Difficulty in using CartJS in Business Rule

Terence N
Tera Contributor

Hi,

 

I am trying to submit a catalog item request through a business rule. I came across the CartJS documentation and followed the sample code there. However, when using cart.addToCart() or the other submission calls, I got the following error:

 

Root cause of JavaScriptException: java.lang.ClassCastException 
: java.lang.ClassCastException: class org.json.simple.JSONObject cannot be cast to class java.lang.String (org.json.simple.JSONObject is in unnamed module of loader com.snc.orbit.container.tomcat8.ParallelOrbitTomcat8ClassLoader @29fe1f17; java.lang.String is in module java.base of loader 'bootstrap'):  com.glideapp.servicecatalog.CatalogUtil.jsonToMap(CatalogUtil.java:619)
 

 

Below is my code:

 

const cart = new sn_sc.CartJS(gs.generateGUID());
const request = {
	sysparm_id: routineCreationCatalogItem.sys_id,
	sysparm_quantity: '1',
	variables:{
		routine_name: `Daily Routine - ${businessApp.name}`,
		activity: dailyActivity.sys_id,
		business_application: businessApp.sys_id
	}
};

cart.addToCart(request);​

 

In the example code provided in the documentation, there was no need to do JSON.stringify() on the request. This is the first issue.

 

Subsequently I tried using JSON.stringify() on the request and there was no error thrown anymore. However, nothing was returned and I am not able to log out the cart details so I cannot do any troubleshooting.

 

Is anyone facing the same issues as me? 

1 ACCEPTED SOLUTION

musislam
Kilo Sage

Hi @Terence N

 

One more thing worth flagging before you go further with this. new sn_sc.CartJS() with no cart name works against the session user's DEFAULT cart, and in a business rule the session user is whoever triggered the record. So the script is reaching into a real person's live cart. If they already have something sitting in there, checkoutCart submits that too.

 

For a single programmatic order I would use orderNow instead. It takes the item straight through without touching the shared cart, and it accepts sysparm_requested_for so you can say who the item is actually for. Without that the request just lands on whoever tripped the rule.

 

One catch: if two step checkout is turned on in your instance, orderNow returns cart_id rather than request_id and request_number, so you need submitOrder after it to create the REQ. Worth handling both so it does not depend on how the instance is configured.

 

var cart = new sn_sc.CartJS();

var request = {
    sysparm_id: routineCreationCatalogItem.getUniqueValue(),
    sysparm_quantity: '1',
    sysparm_requested_for: requestedForSysId,
    variables: {
        routine_name: 'Daily Routine - ' + businessApp.getValue('name'),
        activity: dailyActivity.getUniqueValue(),
        business_application: businessApp.getUniqueValue()
    }
};

var result = cart.orderNow(request);
if (!result.request_number)
    result = cart.submitOrder(request);

gs.info('Order result: ' + JSON.stringify(result));

 

requestedForSysId just needs to be a user sys_id as a string. Run it from Scripts - Background first so you can see the result object before you put it back in the rule.

 

If that works for you, mind marking it as the recommended solution? Helps me support these better for the community.

Macki | Deloitte AU | Engineer Lead

View solution in original post

6 REPLIES 6

Hi yes, that's correct. But sorry I am marking @musislam's answer as correct because it is more complete

musislam
Kilo Sage

Hi @Terence N

 

One more thing worth flagging before you go further with this. new sn_sc.CartJS() with no cart name works against the session user's DEFAULT cart, and in a business rule the session user is whoever triggered the record. So the script is reaching into a real person's live cart. If they already have something sitting in there, checkoutCart submits that too.

 

For a single programmatic order I would use orderNow instead. It takes the item straight through without touching the shared cart, and it accepts sysparm_requested_for so you can say who the item is actually for. Without that the request just lands on whoever tripped the rule.

 

One catch: if two step checkout is turned on in your instance, orderNow returns cart_id rather than request_id and request_number, so you need submitOrder after it to create the REQ. Worth handling both so it does not depend on how the instance is configured.

 

var cart = new sn_sc.CartJS();

var request = {
    sysparm_id: routineCreationCatalogItem.getUniqueValue(),
    sysparm_quantity: '1',
    sysparm_requested_for: requestedForSysId,
    variables: {
        routine_name: 'Daily Routine - ' + businessApp.getValue('name'),
        activity: dailyActivity.getUniqueValue(),
        business_application: businessApp.getUniqueValue()
    }
};

var result = cart.orderNow(request);
if (!result.request_number)
    result = cart.submitOrder(request);

gs.info('Order result: ' + JSON.stringify(result));

 

requestedForSysId just needs to be a user sys_id as a string. Run it from Scripts - Background first so you can see the result object before you put it back in the rule.

 

If that works for you, mind marking it as the recommended solution? Helps me support these better for the community.

Macki | Deloitte AU | Engineer Lead