Mastering the ‘current’ Object: Your Essential Guide to ServiceNow Server-Side Scripting
If you’ve spent any time customizing or automating processes in ServiceNow, you’ve undoubtedly encountered the mystical yet powerful current object. It’s not just a keyword; it’s the very heartbeat of your server-side scripts, enabling you to interact with the record that triggered your code. Think of it as your direct line to the data on the form, right when an action is happening.
In this comprehensive guide, we’re going to pull back the curtain on the current object, exploring its core functionalities, common pitfalls, and how it collaborates with other essential ServiceNow elements. Whether you’re a budding ServiceNow developer or a seasoned pro looking to refine your understanding, prepare to deepen your expertise and write more robust, efficient server-side logic. Let’s dive in!
The ‘current’ Object: Your Server-Side Companion
At its core, the current object in ServiceNow represents the record that is currently being inserted, updated, or queried on the server side. It’s an instance of a GlideRecord, specifically configured for the task at hand. This object becomes available primarily within server-side scripts like:
- Business Rules: The most common place, where
currentrefers to the record that triggered the rule. - Script Includes: When passed as a parameter from a Business Rule or other server-side script.
- Workflow Activities: Often represents the record associated with the workflow context.
- Flow Designer Actions (script steps): When dealing with records within a flow.
The beauty of current lies in its simplicity and directness. It allows you to both read values from the record and set new values before they are saved to the database (in before Business Rules) or after they’ve been saved (in after Business Rules, where you might query related records using its data).
💡 Current vs. g_form (Client-Side)
It’s crucial to understand that current is a server-side object. Its client-side counterpart, used in Client Scripts and UI Policies, is g_form. You cannot use current in a Client Script, just as you can’t use g_form in a Business Rule. Knowing this distinction is foundational for successful ServiceNow development.
Core ‘current’ Object Methods and Properties
Working with current often involves accessing or modifying field values. Let’s look at the most common ways to do this.
Accessing Field Values
To get a value from a field on the current record, you simply use dot-walking syntax:
// Get the value of the 'state' field
var incidentState = current.state;
// Get the system ID (sys_id) of the current record
var recordSysId = current.sys_id;
// Access a value from a reference field (e.g., Assigned To)
var assignedToUserSysId = current.assigned_to;
// Access the display value of a reference field (more on this later)
var assignedToUserName = current.assigned_to.getDisplayValue();
This is incredibly straightforward. You can also use current.getValue('field_name'), but direct dot-walking is more common and often more readable.
Setting Field Values
Modifying field values on the current record is just as easy. You have a couple of primary methods:
1. Direct Assignment
This is the simplest way to set a field’s value:
// Set the state of the current incident to 'Closed' (assuming 7 is the value)
current.state = 7;
// Set the short description
current.short_description = 'Incident closed due to parent closure.';
2. Using setValue()
The setValue() method provides a more explicit way to set a field value. It’s particularly useful for reference fields where you must provide the sys_id of the referenced record.
// Setting a string field
current.setValue('short_description', 'Updated via setValue.');
// Setting a reference field using the sys_id (e.g., setting 'Assigned To' to a specific user)
current.setValue('assigned_to', '624bdb4f0a0a0b25000010000000000a'); // Example sys_id
3. Using setDisplayValue()
This method is a lifesaver when working with reference fields and you only have the display value (e.g., the user’s name, not their sys_id). ServiceNow will automatically resolve the sys_id for you.
// Setting a reference field using the display value (e.g., setting 'Assigned To' to 'Abel Tuter')
current.setDisplayValue('assigned_to', 'Abel Tuter');
setDisplayValue() is incredibly convenient but be aware that it performs a lookup, which can have a minor performance implication compared to providing the sys_id directly. For high-volume operations, setValue() with the sys_id is generally preferred if you have it.
Other Essential ‘current’ Methods
current.update(): This method saves any changes made to thecurrentrecord to the database. It’s implicitly called by Business Rules (unless you abort the action), but you’ll need it when modifying other records usingGlideRecordor in Script Includes.// Example within a Script Include or a scenario where update isn't automatic current.state = 7; current.update(); // Explicitly save the changescurrent.insert(): Used to insert a new record into the database. Similar toupdate(), it’s called explicitly when creating new records withGlideRecord.current.setAbortAction(true): A critical method, typically used inbeforeBusiness Rules, to prevent the current record’s action (insert, update, delete) from completing. This is invaluable for enforcing data integrity and business logic.// Prevent an incident from closing if certain conditions aren't met gs.addErrorMessage('Cannot close this record!'); current.setAbortAction(true);current.changes(): Returnstrueif any field on the current record has changed its value since it was retrieved from the database.if (current.changes()) { gs.info('Something on this record changed!'); }current.field_name.changesTo(value): Checks if a specific field’s value has changed to a particular value. This is extremely useful for triggering logic only when a specific state transition occurs. The reference material showscurrent.state.changesTo(7).if (current.state.changesTo(7)) { // 7 often represents 'Closed' gs.info('Incident just moved to Closed state!'); }current.field_name.changesFrom(value): Checks if a specific field’s value has changed from a particular value.if (current.priority.changesFrom(1)) { // 1 often represents 'Critical' gs.info('Priority was just lowered from Critical.'); }current.isNewRecord(): Returnstrueif the current record is being inserted for the first time.if (current.isNewRecord()) { gs.info('A brand new record is being created!'); }
Real-World Scenarios with ‘current’
Let’s look at some practical examples, inspired by our reference, demonstrating how the current object powers automation in ServiceNow.
Scenario 1: Cascading Closure for Parent and Child Incidents
Requirement: Whenever a parent incident is closed, all its associated child incidents should also automatically close.
This is a classic use case for an after Business Rule. Why after? Because we need the parent incident to be successfully closed first, and its sys_id should be stable for us to query its children.
// Business Rule Configuration:
// Table: Incident
// When: After
// Update: true
// Condition: current.state.changesTo(7) (assuming 7 is 'Closed')
// Script:
if (current.state == 7 && current.parent == '') { // Ensure it's a top-level parent incident
// GlideRecord to find child incidents
var grChild = new GlideRecord('incident');
grChild.addQuery('parent', current.sys_id); // Query children using the parent's sys_id
grChild.query();
while (grChild.next()) {
grChild.state = 7; // Set the state of the child to Closed
grChild.update(); // Update the child incident, saving the change
}
}
Here, current.state.changesTo(7) ensures the rule only runs when the incident moves to a closed state. Inside the script, current.sys_id is crucial for identifying the child incidents. Notice how we use a new GlideRecord instance (grChild) to interact with other records, and explicitly call grChild.update() to save changes to each child incident.
Scenario 2: Preventing Incident Closure with Open Tasks
Requirement: An incident cannot be closed if it has any associated incident tasks that are still open. Similar logic should apply to Problem and Change Request with their respective tasks.
This requires a before Business Rule because we need to check conditions and potentially abort the action before the incident is saved in the closed state.
// Business Rule Configuration:
// Table: Incident
// When: Before
// Update: true
// Condition: current.state.changesTo(7) (or current.active.changesTo(false) if preferred)
// Script:
var grTask = new GlideRecord('incident_task');
grTask.addQuery('incident', current.sys_id); // Find tasks related to the current incident
grTask.addQuery('state', '!=', 3); // Assuming 3 is the state value for 'Closed' for tasks
grTask.query();
if (grTask.hasNext()) { // If any open tasks are found
gs.addErrorMessage('Cannot close the incident because there are open tasks. Please close all tasks first.');
current.setAbortAction(true); // Stop the incident from closing
}
In this example, current.sys_id links the incident to its tasks. If grTask.hasNext() returns true, it means there’s at least one open task. We then use gs.addErrorMessage() to notify the user and current.setAbortAction(true) to prevent the incident from being closed.
Scenario 3: Problem Closure Driving Incident Closure
Requirement: When a Problem record is closed, all associated Incidents (that are not already closed) should also be closed.
Another after Business Rule, this time on the Problem table.
// Business Rule Configuration:
// Table: Problem
// When: After
// Update: true
// Condition: current.state.changesTo(7) (assuming 7 is 'Closed' for Problems)
// Script:
if (current.state == 7) { // The problem just got closed
// GlideRecord to find incidents associated with this problem
var grIncident = new GlideRecord('incident');
grIncident.addQuery('problem_id', current.sys_id); // Link incidents by problem_id field
grIncident.addQuery('state', '!=', 7); // Only close incidents that aren't already closed
grIncident.query();
while (grIncident.next()) {
grIncident.state = 7; // Set the incident state to Closed
grIncident.update(); // Update the incident
}
}
Similar to the parent-child incident scenario, current.sys_id from the Problem record is used to identify related incidents. The loop iterates through each associated incident, updates its state, and explicitly calls update().
Expanding Beyond ‘current’: Related Server-Side Essentials
While current is vital, it rarely works in isolation. Let’s look at other crucial server-side objects and configurations that often work hand-in-hand with it.
The ‘gs’ Object (GlideSystem): Your Server-Side Utility Belt
The gs object, an instance of GlideSystem, is a Swiss Army knife for server-side scripting. It provides access to a wealth of system properties, user information, session details, and logging utilities. You’ll use it constantly.
User Information
gs.getUserID(): Retrieves the system ID (sys_id) of the currently logged-in user on the server side. This is crucial for server-side impersonation checks or auditing.// How to get the current logged in user system id in the server side? var serverUserId = gs.getUserID(); gs.info('Current server-side user ID: ' + serverUserId);gs.getUser().isMemberOf('group name'): A powerful method to check if the current user is a member of a specific group.// How to check if the current logged user is the member of particular group or not? if (gs.getUser().isMemberOf('Service Desk')) { gs.info('User is a member of the Service Desk group.'); } else { gs.info('User is NOT a member of the Service Desk group.'); }
Logging & Messaging
gs.info(),gs.warn(),gs.error(): Used to write messages to the system logs, invaluable for debugging and monitoring.gs.addInfoMessage(),gs.addErrorMessage(): These are special because they allow you to display messages to the user on the client-side form, even though they are called from a server-side script. We sawgs.addErrorMessage()in action earlier.
DateTime & Other Utilities
gs.nowDateTime(): Gets the current date and time in the system’s preferred format.gs.getProperty('property_name'): Retrieves the value of a system property.
Client-Side User Object: ‘g_user’
While current and gs are server-side, it’s good to briefly mention g_user for context, as it’s the client-side equivalent of getting user information.
g_user.userID: Retrieves the system ID (sys_id) of the currently logged-in user on the client side.// How to get the current logged in user system id in the client side? // This would be in a Client Script. var clientUserId = g_user.userID; console.log('Current client-side user ID: ' + clientUserId);
Controlling Form Behavior: Beyond Direct Scripting
Not everything requires a script. ServiceNow offers powerful declarative tools that often interact with or complement what you do with current.
Dictionary Configuration
The data dictionary is the bedrock of your instance, defining fields and their properties. Many form behaviors can be set here.
Mandatory/Read-Only Fields: (Reference Q42) You can make fields mandatory or read-only directly from their dictionary entry, applicable across the entire platform unless overridden.
Attributes: (Reference Q51) Attributes are powerful, comma-separated properties that modify a field’s behavior. Examples include
no_email(prevents email notifications for changes to this field),no_attachment(disables attachments for a record/field), ortree_picker.The Collection Field (Reference Q52) in the dictionary represents the table itself, not a specific field. Any attributes or properties applied here (like
no_attachmentfor the entire table as per Reference Q53) affect the whole table, not just one column.Calculated Values: (Reference Q50) You can define a field’s value to be calculated dynamically based on a script, often utilizing the
currentobject. For example, a “Full Name” field could concatenate “First Name” and “Last Name” using a calculated dictionary property script that accessescurrent.first_name.Dependent Values: (Reference Q49) This feature allows you to filter the choices in one field based on the selection in another, creating cascaded dropdowns (e.g., Subcategory choices depend on Category). This is configured in the dictionary entry by setting a “Dependent Field” and then defining choices linked to parent values.
Reference Qualifiers: (Reference Q48) These are crucial for restricting the data displayed in reference fields, ensuring users only see relevant options. There are three types:
- Simple: A fixed query (e.g.,
active=true) applied directly in the dictionary. - Dynamic: Uses a predefined Dynamic Filter Option to build a query based on context (e.g., “Assigned to my groups”).
- Advanced (JavaScript): The most flexible, allowing you to write a JavaScript function that returns a query string. This is where
currentcan shine, letting you build queries based on other field values on the form (e.g.,javascript:'assignment_group=' + current.assignment_group + '^active=true').
- Simple: A fixed query (e.g.,
Dictionary Overrides: (Reference Q54) Use these to modify a field’s properties (like default value, mandatory status, read-only, reference qualifiers, etc.) for a child table, overriding the definition inherited from its parent table. For instance, setting the default priority for Incidents differently than for Tasks.
UI Policies (Client-Side)
UI Policies (Reference Q58) are client-side rules that control the behavior of form fields and related lists based on specific conditions. They are declarative equivalents of many common Client Script actions.
- Key Actions: Make fields mandatory, read-only, visible/hidden, and show/hide related lists.
- Global Checkbox: (Reference Q59) If checked, the UI Policy applies to all form views. Unchecked, it asks for a specific view name.
- Reverse if False: (Reference Q60) If checked, the actions defined by the policy are reversed when the conditions are no longer met (e.g., a mandatory field becomes optional again).
- On Load: (Reference Q61) If checked, the policy’s conditions and actions are evaluated and applied immediately when the form loads. If unchecked, it only triggers when a field changes after load.
- Inherit Checkbox: (Reference Q62) When checked, the UI Policy applies to child tables that extend the table on which the policy is defined.
- Scripting in UI Policies: (Reference Q63) Yes, you can add client-side scripts to UI Policies by checking the “Run scripts” box. This allows for more complex logic than simple field actions.
Data Policies (Client & Server)
Data Policies (Reference Q66) are similar to UI Policies but are designed to enforce data consistency and integrity across all data entry points, including forms, import sets, web services, and API calls. They work on both the client and server side.
- Key Actions: Primarily make fields mandatory or read-only under certain conditions.
- Conversion from UI Policy: (Reference Q64) You can convert a UI Policy into a Data Policy, making its rules apply more broadly.
- Limitations for Conversion: (Reference Q65) Not all UI Policies can be converted. Specifically, those controlling data visibility, views, related lists, or containing scripts cannot be converted, as these are client-side UI concerns, not core data integrity rules.
Data Lookup Rules
Data Lookup Rules (Reference Q57) are a powerful, code-free way to automatically populate field values based on conditions defined in a separate lookup table. For example, if Category is ‘Hardware’ and Subcategory is ‘Laptop’, automatically set ‘Assignment Group’ to ‘Hardware Support’. They simplify automation that would otherwise require scripting.
Troubleshooting Common ‘current’ Issues
🔧 Troubleshooting Tips
Even with a solid understanding, you might run into bumps. Here are some common issues and how to tackle them:
- Using
currentin Client Scripts: This is a classic beginner mistake. Remember,currentis server-side. For client-side operations, you’ll needg_form. If you need server-side data on the client, consider GlideAjax or g_scratchpad. - Forgetting
.update(): When you modify a record that isn’t thecurrentrecord in a Business Rule (e.g., usinggrChild.state = 7;), you must explicitly callgrChild.update()to save those changes. If you modifycurrentin anafterBusiness Rule, an explicitcurrent.update()is often not needed as the system handles the initial update, but if you re-query and update again, you’ll need it. - Infinite Loops in Business Rules: An
afterBusiness Rule that updates thecurrentrecord without a condition to prevent re-triggering itself can lead to an infinite loop. Always use conditions likecurrent.field.changesTo()or check specific criteria to ensure the rule doesn’t re-run unnecessarily. - Performance Issues with GlideRecord Loops: Iterating through thousands of records within a
while(gr.next())loop, especially inbeforeorafterBusiness Rules, can severely impact performance. Look for ways to optimize queries or process in smaller batches. - Misunderstanding
.changesTo()vs.==: Usingcurrent.state == 7will trigger every time the record is updated while in state 7. Usingcurrent.state.changesTo(7)will only trigger the moment it enters state 7. Choose the right one for your logic. - Incorrect Data Types for
setValue(): Ensure you’re providing the correct data type (e.g., a sys_id string for a reference field, a number for an integer field).
Interview Relevance
💻 Ace Your ServiceNow Interviews!
Questions about the current object, gs, Business Rules, UI Policies, and Data Policies are absolute mainstays in ServiceNow developer interviews. Interviewers want to see that you:
- Understand the Fundamentals: Can you clearly articulate the difference between client-side and server-side scripting?
- Know Where to Use What: When would you use a Business Rule vs. a Client Script? When would you choose a UI Policy over a Data Policy?
- Demonstrate Practical Application: Can you explain a scenario where you used
current.setAbortAction(true)orcurrent.state.changesTo()? Being able to walk through the examples we discussed is a huge plus. - Are Aware of Best Practices: Do you consider performance, avoid infinite loops, and understand the implications of
.update()?
Be prepared to not just define these concepts but to explain when and why you would use them, backed by practical examples.
Conclusion
The current object is more than just a convenient variable; it’s the core mechanism through which you inject dynamic logic and automation into your ServiceNow instance. By mastering its properties and methods, and understanding its symbiotic relationship with objects like gs and declarative tools like Business Rules, UI Policies, and Data Policies, you unlock a powerful toolkit for customizing and extending the platform.
Remember that the best ServiceNow solutions often combine scripting with declarative configurations. Keep experimenting, keep learning, and you’ll find yourself building increasingly sophisticated and efficient automations. Happy coding!