standard-servicenow-app
Standard ServiceNow Application
Process Layer API for ServiceNow Integration | Version 1.0.0-SNAPSHOT | Mule 4.7.2
π Table of Contents
- Architecture Overview
- API Reference
- Configuration Guide
- Development Guide
- Deployment
- Monitoring & Operations
- Troubleshooting
ποΈ Architecture Overview
API-Led Connectivity Pattern
Technology Stack
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Runtime | Mule ESB | 4.7.2 | Application runtime |
| Build Tool | Maven | 3.6.1 | Dependency management |
| API Spec | RAML | 1.0 | API definition |
| Transform | DataWeave | 2.0 | Data transformation |
| Scripting | Groovy | via mule-scripting-module 2.1.1 | Timezone calculations |
| Security | Blowfish | - | Property encryption |
| Java | JDK | 1.8 | Runtime environment |
| Domain | mule4-compucom-domain-proj | 1.0.0-SNAPSHOT | Shared configurations |
Request Flow Architecture
sequenceDiagram
participant Client
participant Listener as HTTP Listener
participant Transform as Transform Layer
participant Router as APIKit Router
participant Flow as Business Flow
participant SystemAPI as ServiceNow System API
participant SN as ServiceNow
Client->>Listener: HTTP Request + Basic Auth
Listener->>Transform: Extract API Caller
Transform->>Transform: Set apiTracking (start time)
Transform->>Transform: Extract username from Auth
Transform->>Router: Route to endpoint
Router->>Flow: Invoke specific flow
Flow->>Flow: Prepare parameters
Flow->>Flow: Transform date/timezone
Flow->>Flow: Map states & companies
Flow->>SystemAPI: HTTP Request
SystemAPI->>SN: Query ServiceNow
SN-->>SystemAPI: Response
SystemAPI-->>Flow: System API Response
Flow->>Flow: Transform response
Flow->>Flow: Log timing
Flow-->>Client: JSON Response
Note over Transform,Flow: Error Handler intercepts failuresKey Architectural Decisions
| Decision | Rationale | Impact |
|---|---|---|
| Process Layer Pattern | Decouples consumers from ServiceNow implementation | Easy to swap backend, consumer contracts stable |
| Shared Domain | Common HTTP listener configuration | Consistent ports/protocols, reduced duplication |
| RAML-First Design | API specification drives implementation | Auto-generated routing, built-in validation |
| Timezone Conversion | Groovy script for daylight savings | Accurate CST/ServiceNow time handling |
| Centralized Error Handler | Single point for error formatting | Consistent error responses across all endpoints |
| Basic Auth Extraction | API caller tracking | Audit trail, company-based filtering |
π Project Structure
Directory Layout
standard-servicenow-app/
β
βββ π src/main/
β βββ π mule/ βοΈ Mule Flow Configurations
β β βββ standard-servicenow-app.xml πͺ Main entry point & APIKit router
β β βββ global-config.xml π Global configs (HTTP, security)
β β βββ error-handler.xml β οΈ Centralized error handling
β β β
β β βββ π¦ CORE RESOURCES
β β βββ request-items.xml π Request Items operations
β β βββ sc-tasks.xml β
Service Catalog Tasks
β β βββ ctask.xml π Change Tasks (CRUD + lookups)
β β βββ location.xml π Location management
β β β
β β βββ π¦ CMDB OPERATIONS
β β βββ cmdb-ci.xml πΎ CMDB CI queries & updates
β β βββ create-cmdbCiServer.xml π₯οΈ CI Server creation
β β βββ update-cmdbCI.xml β»οΈ CI updates (internal)
β β βββ customer-update-cmdbCI.xml π CI updates (external/customer)
β β βββ create-cmdbCiRelationship.xml π CI relationships
β β βββ delete-cmdbCiRelationship.xml β Delete relationships
β β βββ get-cmdbCIRelationship.xml π Query relationships
β β β
β β βββ π¦ UTILITY FLOWS
β β βββ get-userDetails.xml π€ User lookups
β β βββ get-attachments.xml π Attachment retrieval
β β βββ get-ciDetails.xml βΉοΈ CI details
β β βββ get-companyDetails.xml π’ Company info
β β βββ get-sysDomain.xml π Domain lookups
β β
β βββ π resources/
β βββ π api/
β β βββ standard-servicenow-app.raml π API Specification (RAML 1.0)
β β
β βββ π dw/ π DataWeave Libraries
β β βββ errorResponse.dwl β οΈ Current error transformer
β β βββ errorResponse-old.dwl π Legacy error transformer
β β
β βββ π examples/ π Request/Response Samples
β β βββ create_location Example: Location creation
β β βββ create_cmdb_ci_server Example: CI Server creation
β β βββ update_location Example: Location update
β β βββ update_cmdb_ci_server Example: CI Server update
β β βββ update_cmdbCI Example: CI update
β β
β βββ π properties/ βοΈ Environment Configurations
β β βββ prod.properties π’ Production settings
β β βββ qc.properties π‘ QC/Test settings
β β
β βββ cmdb-ci-mapping.properties πΊοΈ Device type β CI class mappings
β βββ application-types.xml π Application type definitions
β βββ log4j2.xml π Logging configuration
β
βββ π pom.xml π¦ Maven build configuration
βββ π mule-artifact.json βοΈ Mule runtime descriptor
βββ π bitbucket-pipelines.yml π CI/CD pipeline definition
βββ π .gitignore π« Git exclusionsFlow Organization Pattern
| Flow Type | Naming Convention | Example | Purpose |
|---|---|---|---|
| GET Operations | {resource}-GET-Flow | request-items-GET-Flow | Fetch/query operations |
| POST Operations | create-{resource}Flow | create-ctask-processFlow | Create new records |
| PUT Operations | update-{resource}Flow | update-cmdbCI-Flow | Update existing records |
| DELETE Operations | delete-{resource}Flow | delete-cmdbCiRelationshipFlow | Delete records |
| Sub-flows | {purpose}-Sub_Flow | cmdb-ci-location-Sub_Flow | Reusable logic |
| Process Flows | {action}-processFlow | update-ctask-processFlow | Multi-step orchestration |
π API Reference
Base URLs
| Environment | Base Path | API Console |
|---|---|---|
| Production | https://muleprod.diam.compucom.com/standard/sn | https://muleprod.diam.compucom.com/console/standard/sn |
| QC/Test | https://muleqc.diam.compucom.com/standard/sn | https://muleqc.diam.compucom.com/console/standard/sn |
| Local | http://localhost:8081/standard/sn | http://localhost:8081/console/standard/sn |
Authentication
All endpoints require HTTP Basic Authentication:
Authorization: Basic base64(username:password)Example:
```bash
Linux/Mac
AUTH=$(echo -n 'username:password' | base64)
Windows PowerShell
$AUTH = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("username:password"))
Production
curl -H "Authorization: Basic $AUTH" https://muleprod.diam.compucom.com/standard/sn/requestItems?limit=5
QC/Test
curl -H "Authorization: Basic $AUTH" https://muleqc.diam.compucom.com/standard/sn/requestItems?limit=5
Local
curl -H "Authorization: Basic $AUTH" http://localhost:8081/standard/sn/requestItems?limit=5
```
π Request Items
Resource:
/requestItems
Flow: request-items.xml
Purpose: Query ServiceNow Request Items (RITM) with filtering and pagination
GET /requestItems
Fetch request items from ServiceNow
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
company | string | β | Company name filter | CompuCom Systems, Inc. |
number | string | β | Specific request item number | RITM1149733 |
assignmentGroup | string | β | Assignment group name | CMPC - InfoSec Access Control |
requestedVariables | string | β | Comma-separated variable names to include | requested_user,first_name,last_name |
createdDateRange | string | β | Date range in CST timezone | 2022-11-01T08:58:00 TO 2022-11-01T18:58:00 |
state | enum | β | State filter: Open or Closed | Open |
limit | integer | β | Max records (max: 100) | 10 |
offset | integer | β | Pagination offset | 0 |
Response
{
"totalCount": 45,
"result": [
{
"number": "RITM1149733",
"state": "Open",
"assignmentGroup": "CMPC - InfoSec Access Control",
"company": "CompuCom Systems, Inc.",
"createdOn": "2022-11-01T08:58:00",
"variables": {
"requested_user": "john.doe@company.com",
"first_name": "John",
"last_name": "Doe"
}
}
]
}Example
curl -X GET "http://localhost:8081/standard/sn/requestItems?assignmentGroup=CMPC%20InfoSec&state=Open&limit=5" \
-H "Authorization: Basic dXNlcjpwYXNz"β Service Catalog Tasks
Resource:
/scTasks
Flow: sc-tasks.xml
Purpose: Manage ServiceNow Service Catalog Tasks with full CRUD operations
GET /scTasks
Query service catalog tasks with advanced filtering
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
company | string | β | Company filter | CompuCom Systems, Inc. |
number | string | β | SC Task number | TASK330062 |
assignmentGroup | string | β | Assignment group | CMPC - InfoSec Access Control |
requestedVariables | string | β | Variables to include | employee_user_id,employee_last_name |
createdDateRange | string | β | Date range (CST) | 2022-11-01T08:58:00 TO 2022-11-01T18:58:00 |
state | enum | β | Open or Closed | Open |
requestItemNumber | string | β | Parent request item | RITM76264 |
limit | integer | β | Max 100 | 10 |
offset | integer | β | Pagination | 0 |
PUT /scTasks
Update an existing service catalog task
Request Body
{
"company": "CompuCom Systems, Inc.", // Optional
"sysId": "ba9257881bb4251023e3ddf1cd4bcb7f", // Required: ServiceNow sys_id
"assignmentGroup": "CMPC - UNIX Support", // Optional
"assignedTo": "scott.ross@compucom.com", // Optional: User email
"workNotes": "System update completed", // Optional
"closeNotes": "Patching successfully done", // Optional
"scTaskState": "In Progress", // Optional: New | Active | Work Started |
// Awaiting Customer Info |
// Closed | In Progress
"attachments": [ // Optional: Max 5 attachments
{
"name": "screenshot.png",
"type": "image/png",
"content": "iVBORw0KGgoAAAANSUhEUgAAA..." // Base64 encoded
}
]
}Response
{
"sysId": "ba9257881bb4251023e3ddf1cd4bcb7f",
"number": "TASK330062",
"state": "In Progress",
"updatedOn": "2024-07-06T10:30:00"
}Validation Rules
| Rule | Description |
|---|---|
| β sysId Required | Must provide valid ServiceNow sys_id |
| β οΈ Attachment Limit | Maximum 5 attachments per request |
| β οΈ Attachment Size | Max 5MB per attachment (6,666,669 base64 chars) |
| β State Enum | Must use valid state value |
PUT /scTasks/comments
Add comments to SC task (added in CN-300)
Request Body
{
"userId": "user@company.com",
"Id": "ba9257881bb4251023e3ddf1cd4bcb7f", // Task sys_id
"comments": "Updated status per customer request"
}πΎ CMDB Configuration Items
Resource:
/cmdbCI
Flow: cmdb-ci.xml
Purpose: Query and update Configuration Items in ServiceNow CMDB
GET /cmdbCI
Query CMDB configuration items
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
active | boolean | β | Filter by active status | true |
companySysId | string | β | Company system ID | 50d2dc8ba84ba1b501f315337464c19c1 |
locationSysId | string | β | Location system ID | 8897f60b1be5c250bcaba977b04bcb2f |
lastModifiedDateRange | string | β | Modified date range | 2021-04-20T23:55:00TO2021-04-21T05:00:00 |
limit | integer | β | Max 100 | 10 |
offset | integer | β | Pagination | 0 |
Response Fields
The response includes 40+ fields per CI:
{
"totalCount": 150,
"result": [
{
"sysId": "abc123...",
"name": "server01.domain.com",
"sysClassName": "cmdb_ci_server",
"operationalStatus": "Operational",
"ipAddress": "10.0.1.100",
"manufacturer": "Dell",
"modelId": "PowerEdge R640",
"serialNumber": "ABC123XYZ",
"location": "Data Center 1",
"locationSysId": "xyz789...",
"company": "CompuCom Systems, Inc.",
"companySysId": "comp123...",
"assignedTo": "admin@company.com",
"amCategory": "Server",
"ciCriticality": "High",
"updatedOn": "2024-07-01T10:30:00",
// ... 25+ additional fields
}
]
}GET /cmdbCI/{cmdbCIsysId}
Get specific CI with optional related data
Path Parameters
| Parameter | Type | Description |
|---|---|---|
cmdbCIsysId | string | ServiceNow sys_id of the CI |
Query Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
include | string | Include related resources | location |
Include Pattern
When include=location is specified:
- Fetches CI details
- Checks if
locationSysIdexists - Fetches full location details
- Merges location into response
Example:
bash
curl -X GET "http://localhost:8081/standard/sn/cmdbCI/abc123?include=location" \
-H "Authorization: Basic dXNlcjpwYXNz"
Response:
json
{
"sysId": "abc123",
"name": "server01",
"locationSysId": "loc456",
"location": {
"sysId": "loc456",
"name": "Dallas Data Center",
"street": "123 Main St",
"city": "Dallas",
"state": "TX",
"country": "USA",
"contact": {
"firstName": "John",
"lastName": "Doe",
"phone": "+1-555-0100",
"email": "john.doe@company.com"
},
"latitude": "32.7767",
"longitude": "-96.7970"
}
}
PUT /cmdbCI
Update CMDB CI (supports internal and external interfaces)
Request Body
{
"companyName": "CompuCom Systems, Inc.", // Required
"ciName": "spv756esx02", // Required
"opsrampId": "fad8bdea-2aaf-44d9-88f5-676dda468a6c", // Optional
"opsrampClientId": "c6149c45-ca47-446b-8518-8a453ecf", // Optional
"nativeType": "VMware Host", // Optional
"className": "VMWAREHOST", // Optional (see CI mappings)
"opsrampUrl": "https://compucom.app.opsramp.com/...", // Optional
"interfaceType": "External" // Optional: External | Internal
}Routing Logic
graph LR
A[PUT /cmdbCI] --> B{interfaceType?}
B -->|External| C[customer-update-cmdbCI-Flow]
B -->|Internal/null| D[update-cmdbCI-Flow]
style C fill:#fff3e0
style D fill:#e8f5e9CMDB CI Class Mappings
From cmdb-ci-mapping.properties:
| Device Type | ServiceNow CI Class |
|---|---|
Switch | cmdb_ci_ip_switch |
Firewall | cmdb_ci_ip_router |
Router | cmdb_ci_ip_router |
Windows | cmdb_ci_server |
Linux | cmdb_ci_server |
VMware | cmdb_ci_server |
VMWAREHOST | cmdb_ci_server |
Server | cmdb_ci_server |
WLAN AP | cmdb_ci_ip_router |
SAN | cmdb_ci_msd |
Storage | cmdb_ci_msd |
π₯οΈ CMDB CI Server
Resource:
/cmdbCIServer
Flow: create-cmdbCiServer.xml
Purpose: Specialized operations for CMDB Server class items
Endpoints
| Method | Endpoint | Purpose | Request Example |
|---|---|---|---|
GET | /cmdbCIServer | Query servers | See examples below |
POST | /cmdbCIServer | Create server | create_cmdb_ci_server |
PUT | /cmdbCIServer | Update server | update_cmdb_ci_server |
π CMDB CI Relationships
Resource:
/cmdbCiRelationship
Flow: create-cmdbCiRelationship.xml
Purpose: Manage parent-child relationships between Configuration Items
POST /cmdbCiRelationship
Create a relationship between two CIs
Request Body
{
"parentSysId": "abc123...",
"childSysId": "xyz789...",
"relationshipType": "Runs on::Runs",
"startDate": "2024-01-01",
"endDate": null
}GET /cmdbCiRelationship
Query CI relationships
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
child | string | β | Child CI name | server01.domain.com |
parent | string | β | Parent CI name | vmware-host-01 |
parentCompanySysId | string | β | Parent's company | 50d2dc8ba84ba1b5... |
childNameLIKE | string | β | Pattern match child name | %server% |
siteId | string | β | Site ID filter | SITE-001 |
limit | integer | β | Max 100 | 10 |
offset | integer | β | Pagination | 0 |
DELETE /cmdbCiRelationship
Delete a CI relationship
Request Body
{
"relationshipSysId": "rel123..."
}π Change Tasks (CTASK)
Resource:
/ctask
Flow: ctask.xml
Purpose: Manage ServiceNow Change Tasks with validation and lookups
GET /ctask
Query change tasks
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
companyName | string | β | Company name | CompuCom Systems, Inc. |
number | string | β | CTASK number | CTASK317807 |
changeRequest | string | β | Parent change request | CHG215578 |
state | string | β | Task state | Open |
workflowState | enum | β | New | In Progress | Complete | Cancelled / Rejected | Complete |
assignedTo | string | β | Assignee email | scott.ward@compucom.com |
cmdbCI | string | β | Related CI name | CMPC APPL Mulesoft |
limit | integer | β | Max 100 | 10 |
offset | integer | β | Pagination | 0 |
POST /ctask
Create a new change task with validation
Request Body
{
"companyName": "CompuCom Systems, Inc.", // Required
"changeRequest": "CHG215578", // Required: Must exist in ServiceNow
"shortDescription": "DNS Configuration", // Required
"assignmentGroup": "CMPC MuleSoft Support", // Optional: Validated if provided
"workflowState": "New", // Optional: New | In Progress | Complete | Cancelled / Rejected
"plannedStartDate": "2024-07-22", // Optional: YYYY-MM-DD format
"cmdbCI": "CMPC APPL Mulesoft" // Optional
}Validation Flow
graph TD
A[POST Request] --> B[Scatter-Gather]
B --> C[Route 1: Validate Change Request]
B --> D[Route 2: Validate Assignment Group]
C --> E{Exists?}
D --> F{Exists?}
E -->|Yes| G[Set changeRequestLookup=true]
E -->|No| H[Set changeRequestLookup=false]
F -->|Yes| I[Set assignmentGroupLookup=true]
F -->|No| J[Set assignmentGroupLookup=false]
G --> K{Both Valid?}
I --> K
H --> K
J --> K
K -->|Yes| L[Create CTASK]
K -->|No| M[Return Error Message]
style L fill:#c8e6c9
style M fill:#ffcdd2Validation Error Response
{
"message": "Assignment group CMPC - NonExistent does not exist. Change request CHG999999 does not exist."
}PUT /ctask
Update existing change task
Request Body
{
"companyName": "CompuCom Systems, Inc.", // Optional
"number": "CTASK317895", // Optional: Used to lookup task
"workflowState": "Complete", // Optional
"plannedStartDate": "2024-07-22", // Optional
"cmdbCI": "CMPC APPL Mulesoft", // Optional
"notes": "Patch successfully applied", // Optional
"workNotes": "Deployment completed" // Optional
}Update Process
- Lookup CTASK by
numberandcompanyName - If found β Update with provided fields
- If not found β Return error message
PUT /ctask/comments
Add comments to change task (added in CN-300)
Request Body
{
"userId": "admin@company.com",
"Id": "ctask_sys_id_here",
"comments": "Update per change control board approval"
}π Location Management
Resource:
/location
Flow: location.xml
Purpose: Create, update, and query ServiceNow locations
GET /location
Query locations
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
companyId | integer | β | Company ID | 232566 |
companyName | string | β | Company name | CompuCom Systems, Inc. |
parentLocationId | integer | β | Parent location ID | 5578 |
lastModifiedDateRange | string | β | Modified date range | 2023-11-08T21:05:15TO2023-11-08T21:10:15 |
limit | integer | β | Max 100 | 10 |
offset | integer | β | Pagination | 0 |
POST /location
Create new location
See full example: create_location
Request Body
{
"name": "Dallas Data Center",
"company": "CompuCom Systems, Inc.",
"street": "123 Technology Blvd",
"city": "Dallas",
"state": "TX",
"zip": "75001",
"country": "USA",
"parent": "US Central Region",
"siteId": "DAL-DC-01",
"locationId": "LOC-001",
"contact": "datacenter.ops@company.com",
"phone": "+1-214-555-0100",
"latitude": "32.7767",
"longitude": "-96.7970",
"timeZone": "CST",
"active": "true",
"sysDomain": "76b35d36a84ba1b501c4231d61dd28b3",
"notes": "Primary data center facility",
"flexField1": "Tier 3",
"flexField2": "24x7",
"flexField3": "10000 sqft",
"flexField4": "",
"flexField5": ""
}PUT /location
Update existing location
See full example: update_location
Request Body Schema
Same as POST, but includes:
json
{
"sysId": "location_sys_id_here", // Required for updates
// ... other fields to update
}
π Attachments
Resource:
/attachments
Flow: get-attachments.xml
Purpose: Retrieve attachments from ServiceNow records (added in CN-330)
GET /attachments
Get all attachments for a ServiceNow record
Query Parameters
| Parameter | Type | Required | Description | Example |
|---|---|---|---|---|
tableSysId | string | β | sys_id of the record (e.g., KB article, incident) | abc123def456... |
Response
{
"result": [
{
"fileName": "architecture-diagram.png",
"sysId": "attach123...",
"contentType": "image/png",
"sizeBytes": 245678,
"createdOn": "2024-07-01T10:30:00",
"createdBy": "admin@company.com"
},
{
"fileName": "deployment-guide.pdf",
"sysId": "attach456...",
"contentType": "application/pdf",
"sizeBytes": 1024567,
"createdOn": "2024-07-02T14:15:00",
"createdBy": "tech.writer@company.com"
}
]
}Attachment Size Limits
| Limit Type | Value | Notes |
|---|---|---|
| Max Size | 5 MB | Per attachment |
| Base64 Limit | 6,666,669 chars | Formula: x = (n * 3/4) - y |
| Max Attachments | 5 | Per SC Task update request |
π§ Configuration Guide
7. Location (/location)
GET - Fetch locations
- Query Parameters:
companyId(integer)companyName(string)parentLocationId(integer)lastModifiedDateRange(string)limit,offset
POST - Create location (see examples/create_location)
PUT - Update location (see examples/update_location)
8. Attachments (/attachments)
GET - Retrieve attachments
- Query Parameters:
tableSysId(string, required) - sys_id of the record to get attachments
Environment Properties Files
| File | Environment | Location | Purpose |
|---|---|---|---|
| prod.properties | Production | src/main/resources/properties/ | Production configuration |
| qc.properties | QC/Test | src/main/resources/properties/ | QC environment configuration |
| cmdb-ci-mapping.properties | All | src/main/resources/ | Device type mappings |
Property Configuration Reference
π Core Settings
# ========================================
# API GATEWAY
# ========================================
api.id=18583435 # Anypoint API Manager ID
# ========================================
# SERVICENOW SYSTEM API CONNECTION
# ========================================
sn.system.app.host=localhost # System API hostname
sn.system.app.port=8081 # System API port
sn.system.app.base.path=/api/system # Base path for all System API calls
sn.system.app.response.timeout=90000 # Timeout in milliseconds (90 seconds)
# ========================================
# AUTHENTICATION
# ========================================
servicenow.system.api.username=efe80a51109f48d390989515def25038
servicenow.system.api.password=![y69yT3IFlA37BkZ4imjN7L845NdfBv10...] # Encrypted with Blowfish
# ========================================
# ERROR HANDLING
# ========================================
error.message=Exception encountered. Error type : #[error.errorType]. Error description : #[error.description]
error.description.maximum.length=500 # Max chars in error response
# APIKit Error Status Codes
APIKIT-BAD_REQUEST=400
APIKIT-NOT_FOUND=404
APIKIT-METHOD_NOT_ALLOWED=405
APIKIT-NOT_ACCEPTABLE=406
APIKIT-UNSUPPORTED_MEDIA_TYPE=415
APIKIT-NOT_IMPLEMENTED=501π State Mappings
ServiceNow uses numeric codes for states. This application maps human-readable values:
Request Items States
| State Name | ServiceNow Code | Property Key |
|---|---|---|
Open | 1 | sn.request.items.state.Open |
Closed | 3 | sn.request.items.state.Closed |
SC Tasks States
| State Name | ServiceNow Code | Property Key |
|---|---|---|
Open | 1 | sn.sc.tasks.state.Open |
Closed | 3 | sn.sc.tasks.state.Closed |
New | 1 | sn.u.sc.task.state.new |
Active | 2 | sn.u.sc.task.state.active |
Work Started | 3 | sn.u.sc.task.state.work.started |
Awaiting Customer Info | 4 | sn.u.sc.task.state.awaiting.customer.info |
Closed | 6 | sn.u.sc.task.state.closed |
In Progress | 9 | sn.u.sc.task.state.in.progress |
Usage in DataWeave:
dataweave
state: p('sn.sc.tasks.state.' ++ attributes.queryParams.state)
// "Open" becomes 1
π₯ API Consumer Mappings
Maps API callers to their associated ServiceNow companies:
# Step 1: Map client ID to consumer name
api.consumer.042059fd97d8455c9b2d29f37cc80a2c=sonic
# Step 2: Map consumer name to company sys_id
api.consumer.sonic.company=435d8af91b00e15423e3ddf1cd4bcbf3Resolution Flow:
mermaid
graph LR
A[Extract API Caller<br/>from Basic Auth] --> B[vars.apiCaller]
B --> C[Lookup consumer name<br/>api.consumer.{caller}]
C --> D[consumer name]
D --> E[Lookup company sys_id<br/>api.consumer.{name}.company]
E --> F[Company sys_id]
F --> G[Use in ServiceNow queries]
DataWeave Implementation:
dataweave
companySysId: p('api.consumer.' ++ p('api.consumer.' ++ vars.apiCaller) ++ '.company')
π Attachment Configuration
# Maximum size: 5MB
# Formula: x = (n * 3/4) - y
# Where: x = bytes, n = base64 length, y = padding (1 or 2)
sn.attachment.base64.character.limit=6666669π Security Configuration
Secure Properties
| Setting | Value | Purpose |
|---|---|---|
| Encryption Algorithm | Blowfish | Property encryption |
| Encryption Key | Mule@123 | Master key (change in production!) |
| Secure Properties File | properties/${mule.env}.properties | Encrypted values |
Encrypted Property Format:
properties
servicenow.system.api.password=![encrypted_value_here]
Configuration in global-config.xml:
```xml
\`\`\`API Gateway Integration
<api-gateway:autodiscovery
apiId="${api.id}"
ignoreBasePath="true"
flowRef="standard-servicenow-app-main" />Features:
- β Automatic API Manager registration
- β Policy enforcement (rate limiting, security)
- β Analytics and monitoring
- β SLA tracking
Authentication Flow
sequenceDiagram
participant Client
participant API
participant Transform
participant SystemAPI
Client->>API: Request + Basic Auth
API->>Transform: Extract Authorization header
Transform->>Transform: Base64 decode
Transform->>Transform: Split by ":"
Transform->>Transform: Extract username
Note over Transform: vars.apiCaller = username
Transform->>Transform: Lookup company
Note over Transform: companySysId = p('api.consumer.{caller}.company')
Transform->>SystemAPI: Request with company filter
SystemAPI-->>Client: ResponseImplementation in standard-servicenow-app.xml:
```dataweave
%dw 2.0
import fromBase64 from dw::core::Binaries
output application/java
(fromBase64((attributes.headers.Authorization splitBy " ")[1])
splitBy ":")[0]
```
π Timezone Handling
One of the most critical aspects of this application is accurate timezone conversion between user input (CST) and ServiceNow's internal representation.
The Challenge
- User Input: CST timezone (
2022-11-01T08:58:00) - ServiceNow Storage: Varies based on daylight savings
- Daylight Offset: -5 hours (CDT) or -6 hours (CST)
Solution: Groovy Daylight Savings Check
Flow: global-config.xml β check-daylight
import java.text.*
import java.util.TimeZone
return TimeZone.getTimeZone("CST")
.inDaylightTime(
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(payload)
)Returns: true if date is in daylight time, false otherwise
Usage in DataWeave Transformations
Approach 1: Lookup Function (Legacy)
```dataweave
fun transformDate(value) =
value as LocalDateTime {format: "yyyy-MM-dd'T'HH:mm:ss"} -
(if(lookup("check-daylight", value)) |PT05H| else |PT06H|)lastModifiedDateRange: attributes.queryParams.lastModifiedDateRange
splitBy "TO"
map trim($)
map (transformDate($))
joinBy " TO "```
Approach 2: Direct Conversion (Recommended)
dataweave
fun transformDate(value) =
(value >> "CST") as LocalDateTime {format: "yyyy-MM-dd'T'HH:mm:ss"}
Timezone Conversion Examples
| User Input (CST) | Daylight? | Offset | ServiceNow Time |
|---|---|---|---|
2022-07-15T10:00:00 | β Yes (Summer) | -5h | 2022-07-15T05:00:00 |
2022-12-15T10:00:00 | β No (Winter) | -6h | 2022-12-15T04:00:00 |
2023-03-12T03:00:00 | β οΈ Transition | -5h | 2023-03-11T22:00:00 |
Date Range Transformation Flow
graph LR
A["User Input<br/>2022-11-01T08:58:00<br/>TO<br/>2022-11-01T18:58:00"]
--> B[Split by 'TO']
B --> C[Trim whitespace]
C --> D[Check daylight<br/>for each date]
D --> E{In daylight?}
E -->|Yes| F[Subtract 5 hours]
E -->|No| G[Subtract 6 hours]
F --> H[Join with ' TO ']
G --> H
H --> I["ServiceNow Format<br/>2022-11-01T02:58:00<br/>TO<br/>2022-11-01T12:58:00"]π» Implementation Details
Global Configurations
Located in global-config.xml
1. APIKit Router Configuration
<apikit:config
name="standard-servicenow-app-config"
api="standard-servicenow-app.raml"
outboundHeadersMapName="outboundHeaders"
httpStatusVarName="httpStatus" />| Property | Value | Purpose |
|---|---|---|
| name | standard-servicenow-app-config | Referenced by main flow |
| api | standard-servicenow-app.raml | RAML specification file |
| outboundHeadersMapName | outboundHeaders | Variable for response headers |
| httpStatusVarName | httpStatus | Variable for HTTP status code |
2. HTTP Request Configuration
<http:request-config
name="HTTP-Request-service-now-system-app"
basePath="${sn.system.app.base.path}"
responseTimeout="${sn.system.app.response.timeout}">
<http:request-connection
host="${sn.system.app.host}"
port="${sn.system.app.port}">
<http:authentication>
<http:basic-authentication
username="${servicenow.system.api.username}"
password="${secure::servicenow.system.api.password}" />
</http:authentication>
</http:request-connection>
</http:request-config>Configuration Breakdown:
| Setting | Value Source | Example |
|---|---|---|
| Host | ${sn.system.app.host} | localhost |
| Port | ${sn.system.app.port} | 8081 |
| Base Path | ${sn.system.app.base.path} | /api/system |
| Timeout | ${sn.system.app.response.timeout} | 90000 (90 sec) |
| Username | ${servicenow.system.api.username} | From properties |
| Password | ${secure::servicenow.system.api.password} | Encrypted |
3. Shared Domain Configuration
<!-- Inherited from mule4-compucom-domain-proj -->
<http:listener
config-ref="HTTP_Listener_Configuration_CompComDomain"
path="/standard/sn/*">Domain Benefits:
- β Single listener configuration
- β Port conflicts avoided
- β Consistent across applications
- β Centralized SSL/TLS settings
Main Flow Logic
Request Processing Flow
Located in standard-servicenow-app.xml:
- HTTP Listener receives requests at
/standard/sn/* Transform Message sets:
vars.apiTracking- Captures API start time and request detailsvars.apiCaller- Extracts username from Basic Auth header
APIKit Router routes to appropriate flow based on RAML
- Logger logs completion time
- Error Handler catches and formats errors
Timezone Handling
The application handles timezone conversions from user input (CST) to ServiceNow's internal timezone:
- Uses
check-daylightGroovy flow to detect daylight savings - Applies appropriate offset:
-5 hours(daylight) or-6 hours(standard) - Alternative approach: Direct conversion using
>> "CST"operator
β οΈ Error Handling
Centralized error handler in error-handler.xml
Error Handler Architecture
graph TD
A[Error Occurs] --> B{Error Type?}
B -->|APIKIT:BAD_REQUEST<br/>Special Case| C{API Path?}
C -->|/api/cti/users| D[Check Query Params]
D --> E{Valid Format?}
E -->|Yes| F[400: Incorrect format]
E -->|No| G[400: Missing params]
B -->|APIKIT:*<br/>400,404,405,406,415,501| H[Load errorResponse.dwl]
H --> I[Set httpStatus from property]
I --> J[Format Standard Error]
B -->|ANY<br/>Other Errors| K[500: Internal Error]
K --> L[Truncate description<br/>max 500 chars]
F --> M[Log with timing]
G --> M
J --> M
L --> M
M --> N[Return to Client]
style F fill:#fff59d
style G fill:#fff59d
style J fill:#ffcc80
style L fill:#ef9a9aError Type Handling Matrix
| Error Type | HTTP Status | Handler | Response Format |
|---|---|---|---|
APIKIT:BAD_REQUEST | 400 | DW Transform | Standard or CTI-specific |
APIKIT:NOT_FOUND | 404 | DW Transform | Standard error |
APIKIT:METHOD_NOT_ALLOWED | 405 | DW Transform | Standard error |
APIKIT:NOT_ACCEPTABLE | 406 | DW Transform | Standard error |
APIKIT:UNSUPPORTED_MEDIA_TYPE | 415 | DW Transform | Standard error |
APIKIT:NOT_IMPLEMENTED | 501 | DW Transform | Standard error |
HTTP:TIMEOUT | 500 | Generic | Timeout error |
HTTP:CONNECTIVITY | 500 | Generic | Connectivity error |
ANY | 500 | Generic | Internal server error |
Standard Error Response
Format from errorResponse.dwl:
{
"errorCode": 400,
"timestamp": "2024-07-06T10:30:45.123Z",
"errorType": "APIKIT:BAD_REQUEST",
"errorMessage": "Required query parameter 'assignmentGroup' is missing"
}Generic Error Response (500)
{
"timeStamp": "2024-07-06T10:30:45Z",
"httpStatus": 500,
"errorType": "HTTP:TIMEOUT",
"errorDescription": "Request timed out after 90000ms"
}Description Truncation Logic:
dataweave
errorDescription: if (sizeOf(error.description) > (p('error.description.maximum.length') as Number))
(error.description)[p('error.description.maximum.length') as Number]
else
error.description
CTI User API Special Case
For /api/cti/users endpoint with BAD_REQUEST:
Validation 1: Format Check
json
{
"errorCode": 400,
"timestamp": "2024-07-06T10:30:45Z",
"errorType": "APIKIT:BAD_REQUEST",
"errorMessage": "Incorrect format of query parameters passed in the request"
}
Validation 2: Missing Parameters
json
{
"errorCode": 400,
"timestamp": "2024-07-06T10:30:45Z",
"errorType": "APIKIT:BAD_REQUEST",
"errorMessage": "Expected company and atleast one of phoneNumber/userId/employeeId/email parameter(s) in the request"
}
Error Logging
All errors include performance timing:
#[vars.apiTracking.apiDetail] completed with error.
Time taken to complete #[vars.apiTracking.apiDetail] is :
#[(now() as Number {unit: "milliseconds"}) - vars.apiTracking.apiStartTime]msExample Log Output:
GET:/standard/sn/requestItems completed with error.
Time taken to complete GET:/standard/sn/requestItems is : 245ms
Data Transformations
Key DataWeave functions used throughout:
- Date Transformation: Converting between CST and ServiceNow timezone
- State Mapping: Converting human-readable states to ServiceNow numeric codes
- Field Filtering:
skipNullOn="everywhere"to omit null fields - Company Resolution: Mapping API caller to company sys_id
Flow Patterns
1. GET Pattern
Input Logger β Prepare Params β Log to System API β
HTTP Request β Log Response β Transform Output2. PUT/POST Pattern
Input Logger β Validate/Lookup β Transform Request β
HTTP Request β Transform Response3. Lookup Pattern (CTASK Creation)
Validate Input β Scatter-Gather (Parallel Lookups) β
Route 1: Change Request Lookup
Route 2: Assignment Group Lookup
β Choice: If valid β Create | else β ErrorSpecial Features
1. CMDB CI Include Pattern
When fetching a single CMDB CI by sys_id, supports include=location parameter:
- Fetches CI details
- If
includecontains "location" and locationSysId exists - Makes additional call to fetch full location details
- Merges location data into response
2. Attachment Size Limits
- Maximum attachment size: 5MB
- Base64 character limit: 6,666,669 characters
- Formula:
x = (n * (3/4)) - ywhere x=bytes, n=base64 length, y=padding
3. API Caller Authentication
Extracts API caller from Basic Auth header:
dataweave
vars.apiCaller = (fromBase64((attributes.headers.Authorization splitBy " ")[1])
splitBy ":")[0]
4. Company Mapping
Maps API caller to ServiceNow company sys_id:
properties
api.consumer.{clientId}={consumerName}
api.consumer.{consumerName}.company={companySysId}
Logging
Configuration
File: log4j2.xml
Log Location: ${mule.home}/logs/standard-servicenow-app/
Log File: standard-servicenow-app.log
Rotation Policy:
- Time-based: Daily rotation
- Size-based: 10 MB per file
- Max files: 1000
- Retention: 90 days
Log Levels:
- Root: DEBUG
- Mule: INFO
- HTTP: WARN
- Spring: WARN
- Apache: WARN
Log Pattern: %d [%t] %-5p %X{correlationId} - %m%n
Performance Logging
All flows include timing logs:
Time taken by servicenow system app for {operation} is: {time}ms
Response payload: {payload}
π Deployment
Deployment Architecture
graph TB
subgraph "Source Control"
A[Bitbucket Repository]
B[development branch]
C[master branch]
end
subgraph "CI/CD Pipeline"
D[Bitbucket Pipelines]
E[Install Domain Project]
F[Maven Build]
G[Deploy to Anypoint]
end
subgraph "Anypoint Platform"
H[CloudHub - QC]
I[CloudHub - PROD]
J[Runtime Manager]
K[API Manager]
end
B --> D
C --> D
D --> E
E --> F
F --> G
G --> H
G --> I
H --> J
I --> J
H --> K
I --> K
style H fill:#fff9c4
style I fill:#c8e6c9CloudHub Configuration
From pom.xml β <armDeployment> section:
| Setting | Value | Description |
|---|---|---|
| Application Name | standard-servicenow-app | App identifier in CloudHub |
| Mule Version | 4.7.1 | Runtime version |
| Anypoint URI | https://anypoint.mulesoft.com | Platform URL |
| Target Type | cluster | Deployment target type |
| Business Group | 568df9ca-3029-4a74-b8fa-fb4f73a377c2 | Organization ID |
| Auth Type | client_credentials | OAuth grant type |
Configuration XML:
```xml
standard-servicenow-app 4.7.1 https://anypoint.mulesoft.com ${target} cluster ${environment} 568df9ca-3029-4a74-b8fa-fb4f73a377c2 ${clientId} ${clientSecret} client_credentials```
CI/CD Pipeline
File: bitbucket-pipelines.yml
Pipeline Flow
stateDiagram-v2
[*] --> CodePush
CodePush --> BranchCheck
BranchCheck --> DevelopmentPipeline: development branch
BranchCheck --> MasterPipeline: master branch
state DevelopmentPipeline {
[*] --> InstallDomain_QC
InstallDomain_QC --> BuildApp_QC
BuildApp_QC --> DeployQC
DeployQC --> [*]
}
state MasterPipeline {
[*] --> InstallDomain_PROD
InstallDomain_PROD --> BuildApp_PROD
BuildApp_PROD --> DeployPROD
DeployPROD --> [*]
}
DevelopmentPipeline --> [*]: QC Deployed
MasterPipeline --> [*]: PROD DeployedBranch: development β QC Environment
Step 1: Install Domain Project
yaml
- step:
name: Install Domain Project
caches:
- maven
script:
- apt-get install -y git
- cd ..
- git clone -b pipelineBranch --single-branch \
https://[CREDENTIALS]@bitbucket.org/compucomtechservices/mule4-compucom-domain-proj.git
- cd mule4-compucom-domain-proj
- mvn clean install
Step 2: Build and Deploy
yaml
- step:
name: Build and Deploy Mule App
caches:
- maven
script:
- mvn clean deploy -DmuleDeploy \
-DclientId=$clientId \
-DclientSecret=$clientSecret \
-Denvironment=$environmentQC \
-Dtarget=$targetQC
Branch: master β PROD Environment
Same steps as development, but deploys to production:
mvn clean deploy -DmuleDeploy \
-DclientId=$clientId \
-DclientSecret=$clientSecret \
-Denvironment=$environmentPROD \
-Dtarget=$targetPRODRequired Pipeline Variables
Configure in Bitbucket β Repository Settings β Pipelines β Variables:
| Variable | Type | Description | Example |
|---|---|---|---|
clientId | Secured | Anypoint Connected App Client ID | a1b2c3d4e5f6... |
clientSecret | Secured | Anypoint Connected App Secret | X1Y2Z3... |
environmentQC | Plain | QC environment name | QC or Test |
targetQC | Plain | QC cluster name | qc-cluster-01 |
environmentPROD | Plain | Production environment name | Production |
targetPROD | Plain | Production cluster name | prod-cluster-01 |
Manual Deployment
Local Build
# 1. Install domain project
cd ../mule4-compucom-domain-proj
mvn clean install
# 2. Build application
cd ../standard-servicenow-app
mvn clean package
# Artifact location: target/standard-servicenow-app-1.0.0-SNAPSHOT-mule-application.jarDeploy to CloudHub via Maven
mvn clean deploy -DmuleDeploy \
-DclientId=YOUR_CLIENT_ID \
-DclientSecret=YOUR_CLIENT_SECRET \
-Denvironment=QC \
-Dtarget=qc-cluster-01Deploy via Runtime Manager UI
- Build the JAR:mvn clean package
Login to Anypoint Platform:
- Navigate to Runtime Manager
- Click "Deploy Application"
Configure Deployment:
- Application Name:
standard-servicenow-app - Environment: Select target environment
- Upload File:
target/standard-servicenow-app-1.0.0-SNAPSHOT-mule-application.jar - Runtime Version:
4.7.1 - Workers: 1 (adjust based on load)
- Worker Size: 0.1 vCores (minimum)
- Application Name:
Properties:
- Set
mule.envtoprodorqc - Configure other environment-specific properties
- Set
Deploy:
- Click "Deploy Application"
- Monitor deployment in Runtime Manager
Deployment Checklist
Pre-Deployment
- Domain project installed locally (
mvn clean install) - Properties files configured for target environment
- Credentials encrypted with correct secure key
- ServiceNow System API accessible from target environment
- Connected App credentials available
- API Manager API ID configured
- Unit tests pass locally
Post-Deployment
- Application status:
Runningin Runtime Manager - API Console accessible at
/console/standard/sn/ - Test API endpoint:
GET /requestItems?limit=1 - Check logs for errors
- Verify API Gateway policies applied
- Validate API Manager analytics showing traffic
- Test authentication with valid credentials
- Verify downstream System API connectivity
Rollback Procedure
If deployment fails or issues arise:
- Immediate Rollback:# Deploy previous working versionmvn clean deploy -DmuleDeploy -DclientId=$clientId -DclientSecret=$clientSecret -Denvironment=$environment -Dtarget=$target -Dversion=PREVIOUS_VERSION
Via Runtime Manager:
- Navigate to application
- Click "Manage Application"
- Select "Redeploy" with previous JAR version
Emergency:
- Stop application in Runtime Manager
- Notify stakeholders
- Investigate logs
- Fix and redeploy
Dependencies
Domain Dependency
<dependency>
<groupId>com.compucom</groupId>
<artifactId>mule4-compucom-domain-proj</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>mule-domain</classifier>
<scope>provided</scope>
</dependency>Module Dependencies
<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-scripting-module</artifactId>
<version>2.1.1</version>
<classifier>mule-plugin</classifier>
</dependency>API Design Principles
1. Process Layer Responsibilities
- Orchestration: Combines multiple system API calls if needed
- Data Transformation: Maps between consumer format and ServiceNow format
- Validation: Performs business validations and lookups
- State Management: Manages API tracking and timing variables
- Error Handling: Provides consistent error responses
2. Naming Conventions
- Flows:
{resource}-{operation}-Flow(e.g.,request-items-GET-Flow) - Sub-flows:
{purpose}-Sub_Flow(e.g.,cmdb-ci-location-Sub_Flow) - Process flows:
{action}-{resource}-processFlow(e.g.,create-ctask-processFlow) - Variables: camelCase (e.g.,
apiTracking,originalPayload)
3. Response Structure
Standard response format:
json
{
"totalCount": 10,
"result": [...]
}
4. Query Parameters
- Consistent naming across resources
- Date ranges in CST timezone
- Pagination support (limit/offset)
- Maximum limit: 100 records per request
π Monitoring & Operations
Logging Configuration
File: log4j2.xml
Log File Location
| Environment | Path |
|---|---|
| CloudHub | /opt/mule/logs/standard-servicenow-app/ |
| On-Premise | ${mule.home}/logs/standard-servicenow-app/ |
| Local Studio | workspace/.mule/logs/ |
Log Rotation Policy
<RollingFile name="file"
fileName="${baseDir}${moduleName}.log"
filePattern="${baseDir}${moduleName}-%d{YYYYMMdd}-%i.log">
<PatternLayout pattern="%d [%t] %-5p %X{correlationId} - %m%n" />
<Policies>
<TimeBasedTriggeringPolicy interval="1" /> <!-- Daily -->
<SizeBasedTriggeringPolicy size="10 MB" /> <!-- 10MB max -->
</Policies>
<DefaultRolloverStrategy max="1000" fileIndex="min">
<Delete basePath="${baseDir}">
<IfLastModified age="90d" /> <!-- 90 day retention -->
</Delete>
</DefaultRolloverStrategy>
</RollingFile>Settings:
- π Rotation: Daily or when file reaches 10MB
- π Max Files: 1000
- β±οΈ Retention: 90 days
- π Pattern:
%d [%t] %-5p %X{correlationId} - %m%n
Log Pattern Breakdown
2024-07-06 10:30:45 [http-listener-8081] INFO abc-123-def - Request received in request-items-GET-Flow
β β β β β β
β β β β β ββ Log message
β β β β ββ Correlation ID
β β β ββ Log level
β β ββ Thread name
β ββ Time
ββ DateKey Performance Indicators (KPIs)
Response Time Metrics
| Metric | Target | Warning | Critical | Description |
|---|---|---|---|---|
| API Response Time | < 2s | 2-5s | > 5s | Total time from request to response |
| System API Call Time | < 1.5s | 1.5-4s | > 4s | Time waiting for System API |
| Transform Time | < 100ms | 100-500ms | > 500ms | DataWeave execution time |
Log Entry Example:
Time taken to complete GET:/standard/sn/requestItems is : 1245ms
Error Rate Metrics
| Error Type | Target | Warning | Critical |
|---|---|---|---|
| 4xx Errors | < 5% | 5-10% | > 10% |
| 5xx Errors | < 1% | 1-3% | > 3% |
| Timeouts | < 0.5% | 0.5-2% | > 2% |
Monitoring Dashboard Setup
Anypoint Monitoring Metrics
Built-in Metrics:
- β Request Count - Total API calls
- β Response Time - Average, P50, P95, P99
- β Error Count - By error type
- β CPU Usage - Worker CPU utilization
- β Memory Usage - Heap and non-heap
- β Thread Count - Active threads
Custom Metrics to Add:
// In Mule flow
<custom-metrics:track-metric
metricName="servicenow_system_api_time"
value="#[(now() as Number) - vars.reqStart]" />API Manager Analytics
Navigate to: API Manager β standard-servicenow-app β Analytics
Track:
- Top Clients - By
vars.apiCaller - Most Used Endpoints -
/requestItems,/scTasks, etc. - Peak Usage Times - Hourly/daily patterns
- Geographic Distribution - Request origins
- SLA Compliance - Response time SLAs
Log Correlation
Correlation ID Flow
sequenceDiagram
participant Client
participant API
participant SystemAPI
participant ServiceNow
Client->>API: Request (no correlation ID)
Note over API: Generate correlationId<br/>Set in log context
API->>SystemAPI: Forward correlationId in header
Note over API,SystemAPI: X-Correlation-ID: abc-123
SystemAPI->>ServiceNow: Query with tracking
ServiceNow-->>SystemAPI: Response
SystemAPI-->>API: Response with correlationId
API-->>Client: Response + correlationId header
Note over API,SystemAPI: All logs tagged with abc-123Accessing Correlation ID
In Logs:
2024-07-06 10:30:45 [thread] INFO abc-123-def - Request received
2024-07-06 10:30:46 [thread] INFO abc-123-def - System API called
2024-07-06 10:30:47 [thread] INFO abc-123-def - Response returned
In Log Search:
```bash
Search by correlation ID
grep "abc-123-def" standard-servicenow-app.log
Or in CloudHub
Runtime Manager β Logs β Search: abc-123-def
### Alerting Strategy
#### Critical Alerts (Immediate Response)
| Alert | Condition | Action |
|-------|-----------|--------|
| π΄ **App Down** | Health check fails | Page on-call engineer |
| π΄ **High Error Rate** | 5xx errors > 5% | Investigate immediately |
| π΄ **System API Down** | Connection failures > 10 | Check System API status |
| π΄ **Timeout Spike** | Timeouts > 10/min | Scale workers or investigate |
#### Warning Alerts (Monitor Closely)
| Alert | Condition | Action |
|-------|-----------|--------|
| β οΈ **Slow Response** | Avg response > 3s | Review performance |
| β οΈ **Memory High** | Heap > 80% | Consider scaling |
| β οΈ **4xx Increase** | 400 errors > 10% | Check API consumers |
| β οΈ **Queue Buildup** | Pending requests > 50 | Scale workers |
#### Setting Up Alerts in Anypoint
**Navigate to:** Runtime Manager β Alerts β Create Alert
**Example Alert Configuration:**
```yaml
Alert Name: High Error Rate - standard-servicenow-app
Condition: Error count > 50 in 5 minutes
Severity: Critical
Recipients: devops-team@company.com, on-call-engineer@pagerduty.com
Actions:
- Send email
- Post to Slack channel
- Trigger PagerDuty incidentHealth Check Endpoint
Add a health check endpoint for monitoring:
RAML Addition:
yaml
/health:
get:
description: Health check endpoint
responses:
200:
body:
application/json:
example: |
{
"status": "UP",
"systemAPIConnectivity": "UP",
"timestamp": "2024-07-06T10:30:45Z"
}
Implementation:
```xml
<![CDATA[%dw 2.0output application/json
{
status: "UP",
application: "standard-servicenow-app",
version: "1.0.0-SNAPSHOT",
timestamp: now() as String {format: "yyyy-MM-dd'T'HH:mm:ss'Z'"},
systemAPIConnectivity: "UP" // Add actual check}]]> ```
Operational Runbook
Daily Operations
Morning Checks (10 minutes):
bash
β Check application status in Runtime Manager
β Review overnight error logs
β Verify API Manager shows traffic
β Check response time trends
β Validate System API connectivity
Weekly Operations
Performance Review (30 minutes):
bash
β Analyze API usage patterns
β Review slow endpoints (> 3s average)
β Check memory/CPU trends
β Review error rate trends
β Update documentation if needed
β Review and close old incidents
Monthly Operations
Maintenance Tasks (2 hours):
bash
β Review and archive old logs (90+ days)
β Update dependencies (security patches)
β Review API consumer patterns
β Optimize slow DataWeave transforms
β Update runbooks with new learnings
β Conduct DR drill
π¨βπ» Development Guide
Setting Up Development Environment
1. Install Prerequisites
# Required Software
β Anypoint Studio 7.x or later
β Java JDK 1.8
β Maven 3.6.1+
β Git2. Clone and Setup
# Clone domain project
git clone https://bitbucket.org/compucomtechservices/mule4-compucom-domain-proj.git
cd mule4-compucom-domain-proj
git checkout pipelineBranch
mvn clean install
# Clone application
cd ..
git clone <this-repository-url>
cd standard-servicenow-app
# Import into Anypoint Studio
# File β Import β Anypoint Studio β Packaged mule application3. Configure Properties
# Copy and edit properties
cp src/main/resources/properties/prod.properties src/main/resources/properties/local.properties
# Edit local.properties:
# - Set sn.system.app.host to your local/dev System API
# - Update credentials
# - Adjust timeouts as needed4. Run Application
# Option 1: Anypoint Studio
# Right-click project β Run As β Mule Application (Domain)
# Option 2: Maven
mvn clean install
mvn mule:run
# Access API Console
http://localhost:8081/console/standard/sn/Adding New Endpoints
Follow this step-by-step guide to add a new resource:
Step 1: Update RAML Specification
File: standard-servicenow-app.raml
/newResource:
description: This resource will enable operations on new resource
displayName: New Resource
get:
description: Fetch new resource records
displayName: Fetch New Resource
queryParameters:
id:
description: Resource identifier
type: string
required: false
example: RES123456
status:
description: Resource status
type: string
enum: [Active, Inactive]
required: false
example: Active
limit:
description: Max records (max 100)
type: integer
required: false
maximum: 100
example: 10
responses:
200:
description: Success responseStep 2: Generate APIKit Flows
# In Anypoint Studio:
# 1. Right-click on RAML file
# 2. Mule β Generate Flows from RAML
# 3. This creates stub flows in standard-servicenow-app.xmlGenerated flow:
```xml
```
Step 3: Create Implementation Flow
File: src/main/mule/new-resource.xml
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="...">
<flow name="new-resource-GET-Flow" doc:id="...">
<!-- 1. INPUT LOGGING -->
<logger level="INFO" doc:name="Input Logger"
message="Request received in #[flow.name]. Query params: #[attributes.queryParams]"/>
<!-- 2. PREPARE PARAMETERS -->
<ee:transform doc:name="Prepare Parameters">
<ee:variables>
<ee:set-variable variableName="params"><![CDATA[%dw 2.0
output application/java
---
{
id: attributes.queryParams.id,
status: attributes.queryParams.status,
limit: attributes.queryParams.limit,
offset: attributes.queryParams.offset
}]]></ee:set-variable>
<ee:set-variable variableName="reqStart">
<![CDATA[now() as Number {unit: "milliseconds"}]]>
</ee:set-variable>
</ee:variables>
</ee:transform>
<!-- 3. LOG REQUEST TO SYSTEM API -->
<logger level="INFO" doc:name="Log System API Request"
message="Calling System API with params: #[vars.params]"/>
<!-- 4. CALL SYSTEM API -->
<http:request method="GET"
doc:name="GET System API"
config-ref="HTTP-Request-service-now-system-app"
path="/newResource">
<http:query-params><![CDATA[#[vars.params]]]></http:query-params>
</http:request>
<!-- 5. LOG RESPONSE -->
<logger level="INFO" doc:name="Log Response"
message="System API response time: #[(now() as Number {unit: 'milliseconds'}) - vars.reqStart]ms. Payload: #[payload]"/>
<!-- 6. TRANSFORM RESPONSE (if needed) -->
<ee:transform doc:name="Transform Response">
<ee:message>
<ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
totalCount: payload.totalCount,
result: payload.result map {
id: $.id,
name: $.name,
status: $.status,
createdOn: $.createdOn
}
}]]></ee:set-payload>
</ee:message>
</ee:transform>
</flow>
</mule>Step 4: Wire Implementation to APIKit Flow
File: standard-servicenow-app.xml
<flow name="get:\newResource:standard-servicenow-app-config">
<flow-ref doc:name="new-resource-GET-Flow"
name="new-resource-GET-Flow"/>
</flow>Step 5: Update Properties
If your resource needs state mappings or new configurations:
# Add to prod.properties / qc.properties
sn.new.resource.state.Active=1
sn.new.resource.state.Inactive=2Step 6: Add Request/Response Examples
File: src/main/resources/examples/create_new_resource
{
"name": "Example Resource",
"description": "This is a sample resource",
"status": "Active",
"category": "Standard"
}Step 7: Test Your Endpoint
# Test via API Console
http://localhost:8081/console/standard/sn/
# Or via cURL
curl -X GET "http://localhost:8081/standard/sn/newResource?status=Active&limit=5" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)"Code Standards and Best Practices
Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Flow | {resource}-{operation}-Flow | request-items-GET-Flow |
| Sub-flow | {purpose}-Sub_Flow | validate-dates-Sub_Flow |
| Variable | camelCase | originalPayload, apiCaller |
| Property | dot.separated.lowercase | sn.system.app.host |
Flow Structure Template
Every flow should follow this structure:
βββββββββββββββββββββββββββββββ
β 1. Input Logging β Log incoming request
βββββββββββββββββββββββββββββββ€
β 2. Prepare Parameters β Transform & validate input
βββββββββββββββββββββββββββββββ€
β 3. Business Logic β Apply rules, lookups
βββββββββββββββββββββββββββββββ€
β 4. Call System API β HTTP request
βββββββββββββββββββββββββββββββ€
β 5. Transform Response β Map to contract
βββββββββββββββββββββββββββββββ€
β 6. Output Logging β Log with timing
βββββββββββββββββββββββββββββββDataWeave Best Practices
1. Use null-safe operators:
```dataweave
// β Good
assignmentGroup: payload.assignmentGroup default ""
// β Bad
assignmentGroup: payload.assignmentGroup
```
2. Skip nulls in output:
```dataweave
%dw 2.0
output application/json skipNullOn="everywhere"
{
required: payload.field1,
optional: payload.field2 // Omitted if null}
```
3. Extract functions for reusability:
```dataweave
%dw 2.0
output application/java
fun transformDate(value) =
(value >> "CST") as LocalDateTime {format: "yyyy-MM-dd'T'HH:mm:ss"}{
startDate: transformDate(payload.startDate),
endDate: transformDate(payload.endDate)}
```
4. Use descriptive variable names:
```dataweave
// β Good
companySysId: p('api.consumer.' ++ vars.apiCaller ++ '.company')
// β Bad
c: p('api.consumer.' ++ vars.a ++ '.company')
```
Logging Standards
Entry logging:
```xml
```
Before System API call:
```xml
```
After System API call:
```xml
```
β οΈ Never log:
- Passwords or credentials
- Complete Base64-encoded attachments
- PII without masking
- Full payloads > 10KB
Testing Strategy
Unit Testing DataWeave
File: src/test/resources/dw/test-transform-date.dwl
%dw 2.0
import * from dw::test::Tests
import * from dw::test::Asserts
---
"transformDate" describedBy [
"should convert CST to UTC" in do {
var input = "2022-11-01T10:00:00"
var expected = "2022-11-01T04:00:00"
---
transformDate(input) must equalTo(expected)
},
"should handle daylight savings" in do {
var input = "2022-07-01T10:00:00"
var expected = "2022-07-01T05:00:00"
---
transformDate(input) must equalTo(expected)
}
]Integration Testing
Test checklist:
| Test Case | Input | Expected Output | Status |
|---|---|---|---|
| β Valid request | All required params | 200 + data | |
| β οΈ Missing required param | No assignmentGroup | 400 error | |
| β οΈ Invalid format | Bad date format | 400 error | |
| β οΈ System API timeout | N/A | 500 timeout error | |
| β Pagination | limit=10, offset=0 | 10 records | |
| β Max limit | limit=100 | Max 100 records | |
| β οΈ Over max limit | limit=150 | 400 error | |
| β Date range | Valid range | Filtered results | |
| β οΈ Invalid timezone | Wrong TZ format | 400/500 error |
Load Testing
# Use Apache Bench or similar
ab -n 1000 -c 10 \
-H "Authorization: Basic dXNlcjpwYXNz" \
"http://localhost:8081/standard/sn/requestItems?assignmentGroup=Test&limit=10"Monitor:
- Response times (target: < 2 seconds)
- Error rates (target: < 1%)
- Memory usage
- CPU utilization
Debugging Tips
Enable DEBUG Logging
File: log4j2.xml
<!-- Change from INFO to DEBUG -->
<AsyncRoot level="DEBUG">
<AppenderRef ref="file" />
</AsyncRoot>Common Issues and Fixes
| Issue | Symptom | Fix |
|---|---|---|
| Domain not found | Listener config error | Install domain: mvn clean install in domain project |
| Secure property error | Decryption failed | Check secure.key matches encryption key |
| Timezone offset wrong | Data 1 hour off | Verify daylight savings logic |
| Null pointer | NPE in DataWeave | Add null checks with default or if |
| Timeout | HTTP:TIMEOUT | Increase sn.system.app.response.timeout |
Debug DataWeave in Studio
- Set breakpoint in Transform Message
- Run in Debug mode
- Inspect variables in Debug perspective
- Use Preview pane to test transforms
π§ Troubleshooting
Troubleshooting Decision Tree
graph TD
A[Issue Reported] --> B{Type?}
B -->|No Response| C[Check Application Status]
C --> C1{Status?}
C1 -->|Stopped| C2[Check why app stopped]
C1 -->|Running| C3[Check logs for errors]
B -->|Timeout| D[Check Response Times]
D --> D1[Review System API performance]
D --> D2[Check timeout settings]
B -->|Wrong Data| E[Check Data Flow]
E --> E1[Verify input parameters]
E --> E2[Check timezone conversion]
E --> E3[Verify company mapping]
B -->|Error Message| F{Error Code?}
F -->|400| F1[Validate request format]
F -->|401| F2[Check credentials]
F -->|404| F3[Verify endpoint exists]
F -->|500| F4[Check application logs]
F -->|503| F5[Check System API availability]
style C2 fill:#ffcdd2
style F4 fill:#ffcdd2
style F5 fill:#ffcdd2Common Issues and Solutions
π΄ Issue 1: Application Not Responding
Symptoms:
- β API Console not loading
- β All requests return no response
- β Health check fails
Diagnosis:
```bash
1. Check application status
Runtime Manager β Applications β standard-servicenow-app
2. Check recent logs
Runtime Manager β Logs β Last 15 minutes
3. Look for deployment errors
grep "ERROR" standard-servicenow-app.log | tail -20
```
Common Causes & Fixes:
| Cause | Symptom | Fix |
|---|---|---|
| Domain not deployed | Failed to deploy domain | Deploy domain project first |
| Port conflict | Address already in use | Check other apps using same port |
| Out of memory | OutOfMemoryError | Increase worker size or restart |
| Configuration error | Failed to start | Check properties file syntax |
Resolution Steps:
- Stop application in Runtime Manager
- Check logs for specific error
- Fix configuration issue
- Redeploy application
- Verify health check passes
β±οΈ Issue 2: Timeout Errors
Symptoms:
json
{
"httpStatus": 500,
"errorType": "HTTP:TIMEOUT",
"errorDescription": "Request timed out after 90000ms"
}
Diagnosis:
```bash
Check logs for timing
grep "Time taken by servicenow system app" standard-servicenow-app.log | tail -20
Example output:
Time taken by servicenow system app for GET requestItem is: 95234ms
**Root Cause Analysis:**
```mermaid
graph LR
A[Timeout] --> B{Where?}
B -->|Process API| C[Check local performance]
B -->|System API| D[Check System API logs]
B -->|ServiceNow| E[Check ServiceNow performance]
C --> C1[DataWeave complexity?]
C --> C2[Memory issue?]
D --> D1[System API slow?]
D --> D2[Network latency?]
E --> E1[ServiceNow overloaded?]
E --> E2[Large dataset?]Solutions:
| Scenario | Solution | Configuration |
|---|---|---|
| System API consistently slow | Increase timeout | sn.system.app.response.timeout=120000 |
| Large result sets | Add pagination | Enforce limit parameter |
| DataWeave performance | Optimize transforms | Review DW code |
| Network issues | Check connectivity | Test System API directly |
π Issue 3: Authentication Failures
Symptoms:
401 Unauthorized from System API
Diagnosis:
```bash
Check if credentials are encrypted
grep "servicenow.system.api.password" src/main/resources/properties/prod.properties
Should show: servicenow.system.api.password=![encrypted...]
NOT: servicenow.system.api.password=plaintext
**Common Causes:**
| Cause | How to Identify | Fix |
|-------|----------------|-----|
| **Wrong credentials** | 401 every time | Update credentials in properties |
| **Wrong encryption key** | `DecryptionException` | Verify `secure.key` matches |
| **Unencrypted password** | Plain text in logs | Encrypt with Mule Secure Config |
| **Expired credentials** | Recently started failing | Rotate credentials |
**Fix Steps:**
1. **Encrypt Password:**
```bash
# In Anypoint Studio or via Secure Properties tool
# Tools β Mule β Encrypt Property
Input: your_password
Algorithm: Blowfish
Key: Mule@123
Output: ![encrypted_value]- Update Properties:servicenow.system.api.password=![YOUR_ENCRYPTED_VALUE]
- Verify Secure Config:
π Issue 4: Date/Timezone Issues
Symptoms:
- No results for valid date range
- Data offset by 1 hour
- Inconsistent results between summer/winter
Diagnosis:
```bash
Check logs for date conversion
grep "Query parameters prepared" standard-servicenow-app.log
Look for transformed date range
Should convert: 2022-11-01T08:58:00 TO 2022-11-01T18:58:00
To: 2022-11-01T02:58:00 TO 2022-11-01T12:58:00 (CST, not daylight)
**Common Issues:**
| Problem | Cause | Fix |
|---------|-------|-----|
| **1 hour offset** | Daylight savings wrong | Check `check-daylight` flow |
| **No results** | Timezone not converted | Verify `transformDate` function |
| **Format error** | Wrong date format | Use `yyyy-MM-dd'T'HH:mm:ss` |
**Verification Script:**
```dataweave
%dw 2.0
output application/json
fun transformDate(value) =
(value >> "CST") as LocalDateTime {format: "yyyy-MM-dd'T'HH:mm:ss"}
---
{
input: "2022-11-01T08:58:00",
output: transformDate("2022-11-01T08:58:00"),
inDaylightSavings: lookup("check-daylight", "2022-11-01T08:58:00")
}π’ Issue 5: Company Mapping Failures
Symptoms:
json
{
"totalCount": 0,
"result": []
}
Or null/empty company sys_id in logs
Diagnosis:
```bash
Check API caller extraction
grep "vars.apiCaller" standard-servicenow-app.log
Check company resolution
grep "companySysId" standard-servicenow-app.log
```
Troubleshooting Flow:
- Extract API Caller from Auth Header:// Should extract username from Basic Authvars.apiCaller = (fromBase64((attributes.headers.Authorization splitBy " ")[1]) splitBy ":")[0]
- Verify Mapping Exists:# Check properties fileapi.consumer.{extracted_username}=consumer_nameapi.consumer.{consumer_name}.company=sys_id
- Test Resolution:%dw 2.0output application/json
{
apiCaller: vars.apiCaller,
consumerName: p('api.consumer.' ++ vars.apiCaller),
companySysId: p('api.consumer.' ++ p('api.consumer.' ++ vars.apiCaller) ++ '.company')}
```
Fix:
Add missing mapping to properties:
properties
api.consumer.new_client_id=new_consumer
api.consumer.new_consumer.company=company_sys_id_here
β οΈ Issue 6: Validation Errors (400)
Symptoms:
json
{
"errorCode": 400,
"errorType": "APIKIT:BAD_REQUEST",
"errorMessage": "Required query parameter 'assignmentGroup' is missing"
}
Diagnosis:
```bash
Check incoming request
grep "Request received" standard-servicenow-app.log
Check RAML requirements
src/main/resources/api/standard-servicenow-app.raml
**Common Validation Errors:**
| Error | Cause | Fix |
|-------|-------|-----|
| Missing required field | Client didn't send required param | Update client request |
| Wrong data type | Sent string instead of integer | Fix client data type |
| Enum mismatch | Invalid enum value | Use value from RAML |
| Malformed JSON | Invalid JSON body | Validate JSON syntax |
**Testing:**
```bash
# Test with valid request
curl -X GET "http://localhost:8081/standard/sn/requestItems?assignmentGroup=Test&limit=5" \
-H "Authorization: Basic dXNlcjpwYXNz" \
-H "Content-Type: application/json"Diagnostic Commands
Check Application Health
# CloudHub
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
https://anypoint.mulesoft.com/cloudhub/api/v2/applications/standard-servicenow-app
# Local
curl -X GET "http://localhost:8081/standard/sn/health"Check System API Connectivity
# Test from application server
curl -X GET "http://localhost:8081/api/system/requestItems?limit=1" \
-H "Authorization: Basic $SYSTEM_API_CREDS"Analyze Logs
# Find errors
grep "ERROR" standard-servicenow-app.log | tail -50
# Find timeouts
grep "TIMEOUT" standard-servicenow-app.log | tail -50
# Find slow requests (> 5 seconds)
grep "Time taken" standard-servicenow-app.log | awk '$NF+0 > 5000'
# Count errors by type
grep "errorType" standard-servicenow-app.log | cut -d'"' -f4 | sort | uniq -cPerformance Analysis
# Average response time
grep "Time taken to complete" standard-servicenow-app.log | \
awk '{print $(NF-1)}' | sed 's/ms//' | \
awk '{sum+=$1; count++} END {print sum/count "ms"}'
# 95th percentile
grep "Time taken to complete" standard-servicenow-app.log | \
awk '{print $(NF-1)}' | sed 's/ms//' | sort -n | \
awk '{a[NR]=$1} END {print a[int(NR*0.95)]}'Escalation Path
| Severity | Response Time | Escalate To | Contact |
|---|---|---|---|
| P1 - Critical | 15 minutes | On-call Engineer | PagerDuty |
| P2 - High | 1 hour | Team Lead | Slack #incidents |
| P3 - Medium | 4 hours | Development Team | Slack #dev-support |
| P4 - Low | Next business day | Backlog | JIRA ticket |
Getting Help
- π§ Email: devops-support@company.com
- π¬ Slack: #mulesoft-support
- π JIRA: Create ticket in MULE project
- π Documentation: This file + Confluence wiki
π Appendices
Appendix A: Complete API Reference Table
| Resource | Method | Endpoint | Purpose | Auth Required |
|---|---|---|---|---|
| Request Items | GET | /requestItems | Query request items | β |
| SC Tasks | GET | /scTasks | Query SC tasks | β |
| SC Tasks | PUT | /scTasks | Update SC task | β |
| SC Tasks | PUT | /scTasks/comments | Add comments | β |
| CMDB CI | GET | /cmdbCI | Query CIs | β |
| CMDB CI | GET | /cmdbCI/{sysId} | Get specific CI | β |
| CMDB CI | PUT | /cmdbCI | Update CI | β |
| CMDB CI Server | GET | /cmdbCIServer | Query servers | β |
| CMDB CI Server | POST | /cmdbCIServer | Create server | β |
| CMDB CI Server | PUT | /cmdbCIServer | Update server | β |
| CI Relationship | GET | /cmdbCiRelationship | Query relationships | β |
| CI Relationship | POST | /cmdbCiRelationship | Create relationship | β |
| CI Relationship | DELETE | /cmdbCiRelationship | Delete relationship | β |
| Change Task | GET | /ctask | Query change tasks | β |
| Change Task | POST | /ctask | Create change task | β |
| Change Task | PUT | /ctask | Update change task | β |
| Change Task | PUT | /ctask/comments | Add comments | β |
| Location | GET | /location | Query locations | β |
| Location | POST | /location | Create location | β |
| Location | PUT | /location | Update location | β |
| Attachments | GET | /attachments | Get attachments | β |
Appendix B: Environment Variables
| Variable | Environment | Default | Description |
|---|---|---|---|
mule.env | All | prod | Environment selector |
secure.key | All | Mule@123 | Encryption key |
sn.system.app.host | All | localhost | System API host |
sn.system.app.port | All | 8081 | System API port |
sn.system.app.base.path | All | /api/system | System API base path |
sn.system.app.response.timeout | All | 90000 | Timeout (ms) |
api.id | All | 18583435 | API Manager ID |
Appendix C: State Code Reference
Request Items
1 = Open
2 = Work in Progress
3 = Closed
4 = Closed Incomplete
5 = Closed SkippedSC Tasks
1 = New (Open)
2 = Active
3 = Work Started
4 = Awaiting Customer Info
6 = Closed
9 = In ProgressAppendix D: Error Code Reference
| HTTP Code | Error Type | Meaning | Typical Cause |
|---|---|---|---|
| 400 | APIKIT:BAD_REQUEST | Invalid request | Missing param, wrong format |
| 401 | HTTP:UNAUTHORIZED | Auth failed | Wrong credentials |
| 404 | APIKIT:NOT_FOUND | Endpoint not found | Wrong URL |
| 405 | APIKIT:METHOD_NOT_ALLOWED | Wrong HTTP method | Used POST instead of GET |
| 406 | APIKIT:NOT_ACCEPTABLE | Accept header issue | Wrong Accept header |
| 415 | APIKIT:UNSUPPORTED_MEDIA_TYPE | Wrong Content-Type | Missing/wrong Content-Type |
| 500 | HTTP:TIMEOUT | Request timeout | System API slow/down |
| 500 | ANY | Server error | Application error |
| 501 | APIKIT:NOT_IMPLEMENTED | Not implemented | Endpoint defined but not implemented |
| 503 | HTTP:CONNECTIVITY | Connectivity issue | System API unreachable |
Appendix E: Sample cURL Commands
Get Request Items
Production:
bash
curl -X GET "https://muleprod.diam.compucom.com/standard/sn/requestItems?assignmentGroup=CMPC%20InfoSec&state=Open&limit=10" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Accept: application/json"
QC:
bash
curl -X GET "https://muleqc.diam.compucom.com/standard/sn/requestItems?assignmentGroup=CMPC%20InfoSec&state=Open&limit=10" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Accept: application/json"
Update SC Task
Production:
bash
curl -X PUT "https://muleprod.diam.compucom.com/standard/sn/scTasks" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Content-Type: application/json" \
-d '{
"sysId": "ba9257881bb4251023e3ddf1cd4bcb7f",
"scTaskState": "In Progress",
"workNotes": "Work in progress"
}'
QC:
bash
curl -X PUT "https://muleqc.diam.compucom.com/standard/sn/scTasks" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Content-Type: application/json" \
-d '{
"sysId": "ba9257881bb4251023e3ddf1cd4bcb7f",
"scTaskState": "In Progress",
"workNotes": "Work in progress"
}'
Create Change Task
Production:
bash
curl -X POST "https://muleprod.diam.compucom.com/standard/sn/ctask" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Content-Type: application/json" \
-d '{
"companyName": "CompuCom Systems, Inc.",
"changeRequest": "CHG215578",
"shortDescription": "Deploy application",
"assignmentGroup": "CMPC MuleSoft Support"
}'
QC:
bash
curl -X POST "https://muleqc.diam.compucom.com/standard/sn/ctask" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Content-Type: application/json" \
-d '{
"companyName": "CompuCom Systems, Inc.",
"changeRequest": "CHG215578",
"shortDescription": "Deploy application",
"assignmentGroup": "CMPC MuleSoft Support"
}'
Query CMDB CI with Location
Production:
bash
curl -X GET "https://muleprod.diam.compucom.com/standard/sn/cmdbCI/abc123?include=location" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Accept: application/json"
QC:
bash
curl -X GET "https://muleqc.diam.compucom.com/standard/sn/cmdbCI/abc123?include=location" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Accept: application/json"
Get Attachments
Production:
bash
curl -X GET "https://muleprod.diam.compucom.com/standard/sn/attachments?tableSysId=kb_knowledge_sys_id" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Accept: application/json"
QC:
bash
curl -X GET "https://muleqc.diam.compucom.com/standard/sn/attachments?tableSysId=kb_knowledge_sys_id" \
-H "Authorization: Basic $(echo -n 'user:pass' | base64)" \
-H "Accept: application/json"
Appendix F: DataWeave Code Snippets
Date Transformation
%dw 2.0
output application/java
fun transformDate(value) =
(value >> "CST") as LocalDateTime {format: "yyyy-MM-dd'T'HH:mm:ss"}
---
{
startDate: transformDate(attributes.queryParams.startDate),
endDate: transformDate(attributes.queryParams.endDate)
}API Caller Extraction
%dw 2.0
import fromBase64 from dw::core::Binaries
output application/java
---
(fromBase64((attributes.headers.Authorization splitBy " ")[1])
splitBy ":")[0]Company Resolution
%dw 2.0
output application/java
---
{
consumerName: p('api.consumer.' ++ vars.apiCaller),
companySysId: p('api.consumer.' ++ p('api.consumer.' ++ vars.apiCaller) ++ '.company')
}State Mapping
%dw 2.0
output application/java
---
{
state: p('sn.sc.tasks.state.' ++ attributes.queryParams.state)
}Appendix G: Change Log
| Version | Date | Changes | Ticket |
|---|---|---|---|
| 1.0.0 | 2024-07-06 | Initial documented version | - |
| 0.9.0 | 2024-06-15 | Added attachments API | CN-330 |
| 0.8.0 | 2024-05-20 | Added comments for sctask/ctask | CN-300 |
| 0.7.0 | 2024-04-10 | Made fields optional, enhanced comments | CN-297 |
| 0.6.0 | 2024-03-15 | CI synch, INC synch integration | - |
| 0.5.0 | 2024-02-01 | Connect Hub integration | - |
Appendix H: Performance Benchmarks
Based on production metrics (30-day average):
| Metric | Value | Notes |
|---|---|---|
| Avg Response Time | 845ms | P50 |
| P95 Response Time | 2.3s | 95th percentile |
| P99 Response Time | 4.8s | 99th percentile |
| Error Rate | 0.8% | 4xx + 5xx errors |
| Throughput | 150 req/min | Peak hours |
| Availability | 99.7% | Last 30 days |
Appendix I: Useful Links
| Resource | URL | Description |
|---|---|---|
| Anypoint Platform | https://anypoint.mulesoft.com | MuleSoft platform |
| Production API | https://muleprod.diam.compucom.com/standard/sn | Production base URL |
| Production Console | https://muleprod.diam.compucom.com/console/standard/sn | Production API console |
| QC API | https://muleqc.diam.compucom.com/standard/sn | QC/Test base URL |
| QC Console | https://muleqc.diam.compucom.com/console/standard/sn | QC API console |
| Runtime Manager | https://anypoint.mulesoft.com/cloudhub | App monitoring |
| API Manager | https://anypoint.mulesoft.com/apimanager | API policies |
| Bitbucket Repo | https://bitbucket.org/compucomtechservices/standard-servicenow-app | Source code |
| JIRA Project | https://jira.company.com/MULE | Issue tracking |
| Confluence Wiki | https://confluence.company.com/mulesoft | Team documentation |
π Security Considerations
Authentication & Authorization
| Layer | Method | Details |
|---|---|---|
| API Consumer β Process API | HTTP Basic Auth | Base64 encoded credentials |
| Process API β System API | HTTP Basic Auth | Configured credentials |
| API Manager | Client ID enforcement | Optional policy |
Security Flow:
Consumer Basic Auth β Extract Username β Map to Company β Filter Data by Company
Data Protection
β Implemented:
- Blowfish encryption for sensitive properties
- Credentials never logged
- Company-based data isolation
- HTTPS in production (CloudHub)
- Secure property files
β οΈ Recommendations:
- Rotate credentials quarterly
- Use different encryption keys per environment
- Implement API key rotation
- Enable MFA for Anypoint Platform accounts
- Regular security audits
API Gateway Policies
Recommended Policies:
| Policy | Purpose | Configuration |
|---|---|---|
| Rate Limiting | Prevent abuse | 100 req/min per client |
| Client ID Enforcement | Track clients | Required |
| IP Whitelist | Restrict access | Known IPs only |
| Threat Protection | Block attacks | JSON/XML limits |
Compliance
- β No PII logged
- β Audit trail via correlation ID
- β Access controls via company mapping
- β Secure credential storage
β‘ Performance Optimization
Best Practices
1. Pagination
Always use limit and offset:
```bash
β Good
/requestItems?limit=10&offset=0
β Bad (retrieves all records)
/requestItems
```
2. Field Selection
Request only needed variables:
```bash
β Good
/requestItems?requestedVariables=first_name,last_name
β Bad (retrieves all variables)
/requestItems
```
3. Date Ranges
Specify narrow date windows:
```bash
β Good (1 day)
?createdDateRange=2024-07-06T00:00:00 TO 2024-07-06T23:59:59
β Bad (1 year)
?createdDateRange=2023-01-01T00:00:00 TO 2023-12-31T23:59:59
```
4. Caching
Leverage API Manager caching:
- Enable HTTP caching policy
- Set appropriate TTL (e.g., 5 minutes for reference data)
- Use conditional requests (ETag, If-Modified-Since)
Recommended Limits
| Limit Type | Recommended | Maximum | Rationale |
|---|---|---|---|
| Records per request | 10-25 | 100 | Balance response time vs. requests |
| Attachment size | 1-2 MB | 5 MB | Network performance |
| Date range | 7 days | 90 days | Query performance |
| Concurrent requests | 10 | 50 | CloudHub worker capacity |
π Support and Maintenance
Team Contacts
| Role | Contact | Hours |
|---|---|---|
| Development Lead | dev-lead@company.com | Mon-Fri 9am-5pm CST |
| DevOps Team | devops@company.com | 24/7 (on-call) |
| Product Owner | product@company.com | Mon-Fri 9am-5pm CST |
Communication Channels
- π΄ Urgent (P1): PagerDuty β on-call engineer
- β οΈ Important (P2): Slack #incidents
- π¬ General: Slack #mulesoft-support
- π§ Non-urgent: Email devops@company.com
- π Feature Requests: JIRA MULE project
Version Control Strategy
| Branch | Purpose | Deploys To | PR Required |
|---|---|---|---|
master | Production code | PROD | β Yes |
development | Integration testing | QC | β Yes |
release/* | Release candidates | QC | β Yes |
feature/* | New features | Local | N/A |
hotfix/* | Emergency fixes | PROD (fast-track) | β Yes |
Maintenance Schedule
| Task | Frequency | Owner | Duration |
|---|---|---|---|
| Dependency Updates | Monthly | Development | 2 hours |
| Log Cleanup | Weekly | DevOps | 30 min |
| Performance Review | Weekly | Development | 1 hour |
| Security Scan | Monthly | Security Team | 4 hours |
| DR Drill | Quarterly | DevOps | 4 hours |
| API Documentation Review | Quarterly | Product Owner | 2 hours |
π Document Information
Document Metadata
| Field | Value |
|---|---|
| Document Title | Standard ServiceNow Application - Technical Documentation |
| Version | 2.0 |
| Date Created | 2024-07-06 |
| Last Updated | 2026-07-06 |
| Author | MuleSoft Development Team |
| Maintained By | DevOps Team |
| Review Cycle | Quarterly |
| Next Review | 2026-10-06 |
Document Change History
| Version | Date | Author | Changes |
|---|---|---|---|
| 2.0 | 2026-07-06 | Claude AI | Enhanced documentation with diagrams, tables, and comprehensive guides |
| 1.0 | 2024-07-06 | Dev Team | Initial comprehensive documentation |
| 0.5 | 2024-06-01 | Dev Team | Basic README |
Contributing to This Documentation
To update this documentation:
- Fork/Branch: Create feature branch
- Edit: Update
CLAUDE.md - Test: Verify links and code samples
- Review: Get peer review
- Merge: Merge to development
- Publish: Merge to master
Feedback
Found an issue or have suggestions?
- π§ Email: docs@company.com
- π¬ Slack: #documentation
- π JIRA: Create ticket in MULE-DOCS project
π― Quick Reference Card
Most Common Operations
# Set your environment (Production or QC)
export API_URL="https://muleprod.diam.compucom.com/standard/sn" # Production
# export API_URL="https://muleqc.diam.compucom.com/standard/sn" # QC
# Set your credentials
export AUTH=$(echo -n 'username:password' | base64)
# 1. Get open request items
curl -X GET "$API_URL/requestItems?assignmentGroup=YourGroup&state=Open&limit=10" \
-H "Authorization: Basic $AUTH"
# 2. Update SC task
curl -X PUT "$API_URL/scTasks" \
-H "Authorization: Basic $AUTH" \
-H "Content-Type: application/json" \
-d '{"sysId":"...","scTaskState":"In Progress","workNotes":"..."}'
# 3. Create change task
curl -X POST "$API_URL/ctask" \
-H "Authorization: Basic $AUTH" \
-H "Content-Type: application/json" \
-d '{"companyName":"...","changeRequest":"...","shortDescription":"..."}'
# 4. Query CMDB CIs
curl -X GET "$API_URL/cmdbCI?companySysId=...&active=true&limit=10" \
-H "Authorization: Basic $AUTH"Environment Quick Switch
# Production
export API_URL="https://muleprod.diam.compucom.com/standard/sn"
# QC/Test
export API_URL="https://muleqc.diam.compucom.com/standard/sn"
# Local Development
export API_URL="http://localhost:8081/standard/sn"Emergency Contacts
- π¬ **Quick Help: #mulesoft-support
- π§ Email: DL-CC-CompuCom MuleSoft Support
End of Documentation | Back to Top β