ServiceNow Certified Application Developer
SERVICENOW · Certified Application Developer (CAD)
By Mr Sparkles
Cheat Sheet
ServiceNow CAD Exam Mastery
Certified Application DeveloperPlease use my guide to finalize your training for the ServiceNow CAD exam. Reproduction of this is not allowed.
Created by:Mr. Sparkles
The Golden Rules
- If a UI Policy can do it, do not open a Client Script. Save the script for logic that actually branches.
- A module role only hides the menu. If the exam asks who can read the row, the answer is almost always an ACL.
- Calling current.update() inside a before Business Rule is a classic fail. The platform already saves. That call loops you into pain.
- New work goes in a scoped app. Global is the exception you justify, not the default.
- Managing Applications is about a quarter of the exam. If you only drilled GlideRecord, you are underprepared.
- Returning records to a portal user? Prefer GlideRecordSecure. Plain GlideRecord will happily ignore the caller's ACLs.
1
Blueprint Weights ~60 Q / 90 min
| Domain | Weight |
|---|---|
| Managing Applications | 25% |
| Security and Restricting Access | 20% |
| Working with Data | 20% |
| Automating Applications | 20% |
| Application User Experience | 10% |
| Design and Development Concepts | 5% |
Reality check: Weights and fees shift by release. Confirm the live blueprint on ServiceNow University before you book.
2
Decision hierarchy Design 5%
- Out-of-box platform features first
- Declarative tools next (UI Policy, Flow, Data Policy, dictionary)
- Script only when declarative cannot express the rule
- Scoped apps for new work; avoid global unless forced
- Ship ATF coverage for the paths that break production
Good fit vs poor fit
Usually a fit
- Task / request / approvals
- Forms + notifications
- Repeatable orchestration
Usually a poor fit
- Unstructured docs as system of record
- Heavy GPU / CAD graphics
- Streaming A/V as the product
3
Scope & tools
| Scoped | Global |
|---|---|
| Default for new apps; namespace prefix | Legacy / shared customizations |
| Application Access + App Repo + Git | Update sets for config bundles |
| Delegated Development supported | No Delegated Development |
| Tool | Use when |
|---|---|
| Studio | Full files, scripts, ACLs, source control |
| App Engine Studio | Guided / simpler app creation |
| Guided App Creator | Bootstrap scoped app (roles, tables, menu) |
Extend a table when parent fields or logic help (Task approvals, inheritance). Skip extend for seed/reference-only data, or when parent logic will fight your design.
4
Security picker 20%
| Need | Use |
|---|---|
| Hide module / menu | Menu / module roles |
| Block row or field data | ACL (server) |
| Rules on form + import + API | Data Policy |
| Other scope reads/writes your table | Application Access |
| Script returns user-visible rows | GlideRecordSecure |
| Assign permissions to people | Group → roles |
Trap: Passing a module role does not grant table CRUD. Menu visibility is not data access.
5
ACL sequence
- Scope / Application Access can block cross-scope work first
- Table ACL for the operation (create/read/write/delete). Fail table, get no fields.
- Field ACL if present. Pass table, fail field, field denied.
- Within an ACL: roles + condition + script must all pass
- No matching ACL → default deny
Table ACL
Field ACL
security_admin elevate
Debug Security Rules
Impersonate
Client checks like g_user.hasRole() are UI convenience only. Never treat them as the security boundary.
6
UX picker 10%
| Need | Prefer |
|---|---|
| Show / hide / mandatory / read-only | UI Policy (+ Reverse if false) |
| Complex browser logic | Client Script |
| Trusted validation always | Business Rule or Data Policy |
| Button / link / context menu | UI Action |
| Catalog-style create UI | Record Producer |
| Client needs server lookup | GlideAjax → client-callable Script Include |
| Workspace / Now Experience | UI Builder |
| Classic portal widgets | Service Portal |
Client Script types
onLoad
onChange
onSubmit
onCellEdit
UX gotchas
- Order: Client Scripts generally run before UI Policies on the form. If both fight over the same field, know which one actually wins in your scenario.
- Conflict: UI Policy marks a field mandatory, Client Script marks it read-only. The user can get stuck: required value they cannot edit. Design one owner for that field.
- Performance: Avoid synchronous GlideAjax. It freezes the browser. Async callbacks only.
- Loop trap: g_form.setValue() inside an onChange can re-fire onChange. Guard it.
7
UI Policy vs Client Script vs Data Policy
| UI Policy | Client Script | Data Policy | |
|---|---|---|---|
| Where | Browser / form | Browser | Server (all interfaces) |
| Code? | Optional | Yes | No |
| Import / REST? | No | No | Yes |
g_form.getValue('field');
g_form.setValue('field', 'value');
g_form.setMandatory('field', true);
g_form.setDisplay('field', false);
g_form.setReadOnly('field', true);
Exam angle: Need the rule on import and web services too? That is Data Policy, not a UI Policy.
7b
g_scratchpad vs GlideAjax
| g_scratchpad | GlideAjax | |
|---|---|---|
| When | Form load (Display Business Rule packs data) | On change / on demand after the form is open |
| Best for | Values you already know you need on open | Lookups that depend on what the user just typed |
| Server piece | Display BR sets g_scratchpad.foo | Client-callable Script Include + AbstractAjaxProcessor |
| Client piece | Read g_scratchpad in onLoad / onChange | GlideAjax + getXML / getXMLAnswer |
Rule of thumb: Know it at load time? Scratchpad. Depends on a field the user just changed? GlideAjax.
8
Data & imports 20%
| Concept | Meaning |
|---|---|
| Dictionary | Field metadata |
| Reference | FK; enables dot-walking |
| M2M | Join table between two tables |
| Data Policy | Field rules on every interface |
Import workflow
- Load Data → Import Set (staging)
- Transform Map maps source → target
- Coalesce decides insert vs update
- ACLs / Data Policies still apply on the target
Import Set
- Stages raw rows
- Temporary table
- Does not finalize target
Transform Map
- Writes real records
- Field maps + coalesce
- Insert / update / reject
9
Automation picker 20%
| Need | Prefer |
|---|---|
| Change fields before commit | Before Business Rule |
| React after save | After Business Rule |
| Heavy / slow work | Async BR or event + Script Action |
| Scratchpad for form load | Display BR → g_scratchpad |
| Readable multi-step process | Flow Designer |
| Reusable server library | Script Include |
| Client → server round trip | GlideAjax + client-callable SI |
| Timed housekeeping | Scheduled Script Execution |
Flow
Subflow
Action
Data pill
IntegrationHub spoke
10
Business Rule timing
| When | Notes |
|---|---|
| Before | Mutate current; can abort; no current.update() |
| After | Already committed; watch recursion if you update again |
| Async | Later; no reliable user-session UI |
| Display | Builds g_scratchpad for the client |
current / previous
current.operation()
current.changes()
current.field.changes()
Lower Order runs first (default 100).
11
Scripting quick hits
| API | Use |
|---|---|
| GlideRecord | Trusted server DML/query |
| GlideRecordSecure | Honors ACLs for current user |
| GlideAggregate | COUNT/SUM/AVG without loading every row |
GlideSystem (gs) you should know cold
| Method | What it does |
|---|---|
| gs.hasRole('x') | Role check on the server |
| gs.getUserID() | Current user sys_id |
| gs.getUserName() | User name string |
| gs.addInfoMessage() | Session info banner |
| gs.addErrorMessage() | Session error banner |
| gs.info() / gs.warn() / gs.error() | Server logs |
| gs.eventQueue() | Queue an event for notifications / Script Actions |
| gs.getProperty() | Read a system / app property |
var gr = new GlideRecord('incident');
gr.addQuery('active', true);
gr.addEncodedQuery('active=true^priority=1');
gr.setLimit(50);
gr.query();
while (gr.next()) { /* ... */ }
gr.setWorkflow(false);
Never direct SQL. Never lean on client-side GlideRecord for real lookups. Use GlideAjax.
12
Integrations
| Direction | Tooling |
|---|---|
| Inbound table CRUD | Table API /api/now/table/{table} |
| Inbound custom contract | Scripted REST API |
| Outbound HTTP | REST Message / Flow REST / IntegrationHub |
| Auth | Basic, OAuth 2.0, mutual TLS |
| Secrets | Connection & Credential Alias |
Pattern: Table API when the contract is table-shaped. Scripted REST when the external schema does not match your tables.
13
Managing applications 25% - study hard
| Mechanism | Best for |
|---|---|
| Update Set | Config changes, global fixes, operational bundles |
| Application Repository | Versioned scoped app install / upgrade / publish |
| Source Control (Git) | Peer review, branching, Studio ↔ Git |
| Need | Prefer |
|---|---|
| Move scoped app | App Repository |
| Global / config change | Update Set |
| Non-admin contributors | Delegated Development (scoped only) |
| Regression proof | ATF + impersonation steps |
| ACL mystery | Impersonate + Debug Security |
Trap: Scoped apps are products (repo). Update sets are change packages. Do not treat them as interchangeable.
Managing Applications gotchas
Delegated Development (scoped only)
- Lets non-admins work inside an app with limited file types
- Common grants: tables & forms, ACLs & roles, scripting, Flow Designer
- Source control and integrations can be part of what you allow or withhold
- Global apps do not get Delegated Development. Full stop.
Application Access on a table
- Can read / create / write / delete: what other scopes may do to records
- Accessible from: this scope only vs all application scopes
- Allow configuration: other scopes may add BRs, Client Scripts, UI Actions, fields (needs "all scopes")
- Allow access via web services: inbound Table API / web services still need user ACLs
Cross-scope silence: Your script "finds zero rows" but data exists. Check Application Access and cross-scope privileges before you rewrite the query.
!
Common traps
| Trap | Reality |
|---|---|
| Module role = data access | Module only hides navigation |
| Client Script = security | ACLs / Data Policies enforce data |
| current.update() in before BR | System already saves |
| Import Set "loads" prod table | Staging only; Transform writes target |
| UI Policy blocks imports | It does not. Use Data Policy. |
| Scope failure = "no rows" | Often Application Access |
| Study only scripting | Managing Apps is 25% |
✓
Last-minute checklist
- Managing Apps: update sets, repo, Git, ATF, delegated dev, Application Access
- ACLs: table then field; roles + condition + script; default deny
- UI Policy → Client Script → Data Policy for all interfaces
- Before BR mutates current without current.update()
- Flow for process; BR for commit-time data; Script Include for libraries
- g_scratchpad at load; GlideAjax on demand
- GlideRecordSecure for user-facing returns
- Coalesce on transforms; Import Set ≠ target
- Impersonate to validate security
Discussion
No comments yet.
Log in to comment.