- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
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?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
try this
// 1) Instantiate CartJS (no GUID needed in most recent docs)
var cart = new sn_sc.CartJS();
// 2) Build the item payload as a JS object
var itemOrderDetails = {
sysparm_id: routineCreationCatalogItem.sys_id, // catalog item sys_id
sysparm_quantity: '1',
variables: {
routine_name: 'Daily Routine - ' + businessApp.name,
activity: dailyActivity.sys_id,
business_application: businessApp.sys_id
}
};
// 3) Convert to JSON string before passing to addToCart
var itemJson = JSON.stringify(itemOrderDetails);
// 4) Add to cart
var addToCartResult = cart.addToCart(itemJson);
// Optional: log result for troubleshooting
gs.info('addToCart result: ' + JSON.stringify(addToCartResult));
// 5) Checkout
var checkoutResult = cart.checkoutCart();
gs.info('checkoutCart result: ' + JSON.stringify(checkoutResult));
// 6) Use the result
if (checkoutResult && checkoutResult.request_number) {
gs.info('Order submitted. Request: ' + checkoutResult.request_number);
// If you need sys_id, you may need to query sc_request by number
} else {
gs.error('Failed to submit order: ' + JSON.stringify(checkoutResult));
}
💡 If my response helped, please mark it as correct ✅ and close the thread 🔒— this helps future readers find the solution faster! 🙏
Ankur
✨ Certified Technical Architect || ✨ 10x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
2 weeks ago
Thanks for the reply, but stringify the item does not work
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi Terence,
That ClassCastException usually means one of the values in the request isn't a plain string. routineCreationCatalogItem.sys_id, dailyActivity.sys_id and businessApp.sys_id are GlideElement objects, not text, so CartJS ends up with an object where it expects a string.
Try passing everything as strings. I'd also drop the GUID from the constructor. That parameter is the cart name, so you'd get a new cart on every run.
var cart = new sn_sc.CartJS();
var request = {
sysparm_id: routineCreationCatalogItem.getUniqueValue(),
sysparm_quantity: '1',
variables: {
routine_name: 'Daily Routine - ' + businessApp.getValue('name'),
activity: dailyActivity.getUniqueValue(),
business_application: businessApp.getUniqueValue()
}
};
cart.addToCart(request);
var result = cart.checkoutCart();
gs.info('CartJS result: ' + JSON.stringify(result));If it still fails, can you confirm:
1. Are routineCreationCatalogItem, dailyActivity and businessApp all GlideRecords?
2. Is the business rule after or async?
3. Do the variable names match the item exactly, including any in a variable set?
If that works for you, mind marking it as the recommended solution? Helps me support these better for the community.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hello @Terence N ,
The issue might be, dailyActivity.sys_id and businessApp.sys_id aren't plain JS strings they're GlideElement objects. CartJS internally passes variables through CatalogUtil.jsonToMap(), which needs a primitive String.
try every variable value to a primitive string :
const cart = new sn_sc.CartJS();
const request = {
sysparm_id: routineCreationCatalogItem.sys_id.toString(),
sysparm_quantity: '1',
variables: {
routine_name: `Daily Routine - ${businessApp.name.toString()}`,
activity: dailyActivity.sys_id.toString(),
business_application: businessApp.sys_id.toString()
}
};
const cartResponse = cart.addToCart(request);
gs.info('Cart response: ' + JSON.stringify(cartResponse));
If my response helped mark as helpful and accept the solution.
