Loading...
Loading...
If you have an audited M2M table which contains a glide_list field as one the from field then a NullPointerException can be thrown when a history set is being generated for a record which had records in the related m2m table that have been deleted. The top of the exception stack is as follows: java.lang.NullPointerException at com.glide.script.GlideRecord.get(GlideRecord.java:756) at com.glide.script.GlideRecord.getElement(GlideRecord.java:7441) at com.glide.script.GlideRecord.getValue(GlideRecord.java:7148) at com.glide.audit.AuditRelation.addMTM(AuditRelation.java:372) at com.glide.audit.AuditRelation.addRelation(AuditRelation.java:326) at com.glide.audit.AuditRelation.addRelationDelete(AuditRelation.java:172) at com.glide.audit.AuditRelation.processEntries(AuditRelation.java:149) at com.glide.audit.AuditRelation.getLastEntries(AuditRelation.java:113) at com.glide.audit.AuditRelation.getEntries(AuditRelation.java:107) at com.glide.audit.AuditRelation.getBoundedEntries(AuditRelation.java:85) at com.glide.audit.HistorySetLoader.load(HistorySetLoader.java:125) at com.glide.audit.HistorySet.loadHistory(HistorySet.java:376) at com.glide.audit.HistorySet.createHistory(HistorySet.java:310) at com.glide.audit.HistorySet.getHistory(HistorySet.java:198) at com.glide.audit.HistorySet.generate(HistorySet.java:142) The Many to Many documentation does not stipulate any limitations on what types the from and to fields should be on the many to many table. However, when a m2m table is created the to and from fields are both reference fields and the table is not audited. Its only a consequence of changing a field from reference to glide_list and making the m2m table audited that this problem can be encountered. Steps to Reproduce 1. Import the attached update set, preview and commit. This creates a u_cmdb_role table which contains 'application' roles (not sys_user_roles) which are related to business applications in cmdb_ci_business_app. It also creates the M2M table u_m2m_users_app_roles to relate u_cmdb_role to sys_user and adds an "Access Permissions" related list to the sys_user form. 2. Import the two XML files from any list header to populate u_cmdb_role and u_m2m_users_app_roles (in that order) giving abel.tuter two separate set of roles. 3. Delete one of the records in u_m2m_users_app_roles, doesn't matter which, to generate a sys_audit_delete record. 4. Open able.tuter's sys_user record and attempt to view the history, should fail and should redirect you back to your previous page (e.g. sys_user.list). If there is already a history set delete it and re-open. 5. Check the localhost log of the node your session is attached to and you should find the error stack: 2023-01-20 01:44:54 (550) Default-thread-8 CB6BABF097EC2110E108F52E6253AF2A txid=d35c6f7097ec SEVERE *** ERROR *** JavaScript evaluation error on: var hs = new GlideHistorySet(current);^M var sys_id = hs.generate();^M ^M action.setRedirectURL("sys_history_set.do?sys_id=" + sys_id);^M action.setReturnURL(current); Root cause of JavaScriptException: java.lang.NullPointerException java.lang.NullPointerException at com.glide.script.GlideRecord.get(GlideRecord.java:757) at com.glide.script.GlideRecord.getElement(GlideRecord.java:7442) at com.glide.script.GlideRecord.getValue(GlideRecord.java:7149) at com.glide.audit.AuditRelation.addMTM(AuditRelation.java:372) at com.glide.audit.AuditRelation.addRelation(AuditRelation.java:326) at com.glide.audit.AuditRelation.addRelationDelete(AuditRelation.java:172) at com.glide.audit.AuditRelation.processEntries(AuditRelation.java:149) at com.glide.audit.AuditRelation.getLastEntries(AuditRelation.java:113) at com.glide.audit.AuditRelation.getEntries(AuditRelation.java:107) at com.glide.audit.AuditRelation.getBoundedEntries(AuditRelation.java:85) at com.glide.audit.HistorySetLoader.load(HistorySetLoader.java:125) at com.glide.audit.HistorySet.loadHistory(HistorySet.java:376) at com.glide.audit.HistorySet.createHistory(HistorySet.java:310) at com.glide.audit.HistorySet.getHistory(HistorySet.java:198) at com.glide.audit.HistorySet.generate(HistorySet.java:142) ...etc.
A workaround, without making any changes to the field type, is to: Turn off auditing on the M2M table (prevents the creation of the sys_audit_delete records). Export any sys_audit_delete records for the M2M table to XML and then delete those records. With this done the history set will be generated successfully. An alternative is to add the M2M table to the list of tables given by the "glide.db.audit.ignore.delete" system property. Note that out-of-the-box you will not find this property in the sys_properties table as the default list of values is set from a node's glide.properties configuration file on the filesystem. To add to this property you would have to first determine the current list, for example from Background Scripts with: gs.info(gs.getProperty('glide.db.audit.ignore.delete')); Then create a new string sys_properties record for "glide.db.audit.ignore.delete" with the value set to the list output from the above script, with the M2M table name appended to the list. The only other option is changing the field type, will not be trivial as changing from a list to a reference field would require the field length to be reduced. If the field contains data then the platform will prevent the data from being truncated. The existing records with multiple values in the list field would probably need to be used to generate new records for each value in the list field, and then the record with the list of values deleted. For example if you had a singe M2M record with: User A <==> Role A, Role B, Role C then you'd need to generate User A <==> Role A User A <==> Role B User A <==> Role C then delete the original record. Repeat for all records in the M2M table and the field may be able to be converted from List to Reference. It is possible you may need the assitance of ServiceNOW Support if you find you are blocked from changing the type. This would also mean any custom business logic would have to be adjusted appropriately.
PRB1594711
Click on a version to see all relevant bugs
ServiceNow Integration
Learn more about where this data comes from
Bug Scrub Advisor
Streamline upgrades with automated vendor bug scrubs
BugZero Enterprise
Wish you caught this bug sooner? Get proactive today.