standard-servicenow-app icon

standard-servicenow-app

(0 reviews)

Standard ServiceNow Application

Process Layer API for ServiceNow Integration | Version 1.0.0-SNAPSHOT | Mule 4.7.2


πŸ“‹ Table of Contents


πŸ—οΈ Architecture Overview

API-Led Connectivity Pattern

Technology Stack

ComponentTechnologyVersionPurpose
RuntimeMule ESB4.7.2Application runtime
Build ToolMaven3.6.1Dependency management
API SpecRAML1.0API definition
TransformDataWeave2.0Data transformation
ScriptingGroovyvia mule-scripting-module 2.1.1Timezone calculations
SecurityBlowfish-Property encryption
JavaJDK1.8Runtime environment
Domainmule4-compucom-domain-proj1.0.0-SNAPSHOTShared 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 failures

Key Architectural Decisions

DecisionRationaleImpact
Process Layer PatternDecouples consumers from ServiceNow implementationEasy to swap backend, consumer contracts stable
Shared DomainCommon HTTP listener configurationConsistent ports/protocols, reduced duplication
RAML-First DesignAPI specification drives implementationAuto-generated routing, built-in validation
Timezone ConversionGroovy script for daylight savingsAccurate CST/ServiceNow time handling
Centralized Error HandlerSingle point for error formattingConsistent error responses across all endpoints
Basic Auth ExtractionAPI caller trackingAudit 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 exclusions

Flow Organization Pattern

Flow TypeNaming ConventionExamplePurpose
GET Operations{resource}-GET-Flowrequest-items-GET-FlowFetch/query operations
POST Operationscreate-{resource}Flowcreate-ctask-processFlowCreate new records
PUT Operationsupdate-{resource}Flowupdate-cmdbCI-FlowUpdate existing records
DELETE Operationsdelete-{resource}Flowdelete-cmdbCiRelationshipFlowDelete records
Sub-flows{purpose}-Sub_Flowcmdb-ci-location-Sub_FlowReusable logic
Process Flows{action}-processFlowupdate-ctask-processFlowMulti-step orchestration

🌐 API Reference

Base URLs

EnvironmentBase PathAPI Console
Productionhttps://muleprod.diam.compucom.com/standard/snhttps://muleprod.diam.compucom.com/console/standard/sn
QC/Testhttps://muleqc.diam.compucom.com/standard/snhttps://muleqc.diam.compucom.com/console/standard/sn
Localhttp://localhost:8081/standard/snhttp://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
ParameterTypeRequiredDescriptionExample
companystring❌Company name filterCompuCom Systems, Inc.
numberstring❌Specific request item numberRITM1149733
assignmentGroupstringβœ…Assignment group nameCMPC - InfoSec Access Control
requestedVariablesstring❌Comma-separated variable names to includerequested_user,first_name,last_name
createdDateRangestring❌Date range in CST timezone2022-11-01T08:58:00 TO 2022-11-01T18:58:00
stateenum❌State filter: Open or ClosedOpen
limitinteger❌Max records (max: 100)10
offsetinteger❌Pagination offset0
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
ParameterTypeRequiredDescriptionExample
companystring❌Company filterCompuCom Systems, Inc.
numberstring❌SC Task numberTASK330062
assignmentGroupstringβœ…Assignment groupCMPC - InfoSec Access Control
requestedVariablesstring❌Variables to includeemployee_user_id,employee_last_name
createdDateRangestring❌Date range (CST)2022-11-01T08:58:00 TO 2022-11-01T18:58:00
stateenum❌Open or ClosedOpen
requestItemNumberstring❌Parent request itemRITM76264
limitinteger❌Max 10010
offsetinteger❌Pagination0
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
RuleDescription
βœ… sysId RequiredMust provide valid ServiceNow sys_id
⚠️ Attachment LimitMaximum 5 attachments per request
⚠️ Attachment SizeMax 5MB per attachment (6,666,669 base64 chars)
βœ… State EnumMust 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
ParameterTypeRequiredDescriptionExample
activeboolean❌Filter by active statustrue
companySysIdstring❌Company system ID50d2dc8ba84ba1b501f315337464c19c1
locationSysIdstring❌Location system ID8897f60b1be5c250bcaba977b04bcb2f
lastModifiedDateRangestring❌Modified date range2021-04-20T23:55:00TO2021-04-21T05:00:00
limitinteger❌Max 10010
offsetinteger❌Pagination0
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
ParameterTypeDescription
cmdbCIsysIdstringServiceNow sys_id of the CI
Query Parameters
ParameterTypeDescriptionExample
includestringInclude related resourceslocation
Include Pattern

When include=location is specified:

  1. Fetches CI details
  2. Checks if locationSysId exists
  3. Fetches full location details
  4. 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:#e8f5e9
CMDB CI Class Mappings

From cmdb-ci-mapping.properties:

Device TypeServiceNow CI Class
Switchcmdb_ci_ip_switch
Firewallcmdb_ci_ip_router
Routercmdb_ci_ip_router
Windowscmdb_ci_server
Linuxcmdb_ci_server
VMwarecmdb_ci_server
VMWAREHOSTcmdb_ci_server
Servercmdb_ci_server
WLAN APcmdb_ci_ip_router
SANcmdb_ci_msd
Storagecmdb_ci_msd

πŸ–₯️ CMDB CI Server

Resource: /cmdbCIServer
Flow: create-cmdbCiServer.xml
Purpose: Specialized operations for CMDB Server class items

Endpoints
MethodEndpointPurposeRequest Example
GET/cmdbCIServerQuery serversSee examples below
POST/cmdbCIServerCreate servercreate_cmdb_ci_server
PUT/cmdbCIServerUpdate serverupdate_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
ParameterTypeRequiredDescriptionExample
childstring❌Child CI nameserver01.domain.com
parentstring❌Parent CI namevmware-host-01
parentCompanySysIdstring❌Parent's company50d2dc8ba84ba1b5...
childNameLIKEstring❌Pattern match child name%server%
siteIdstring❌Site ID filterSITE-001
limitinteger❌Max 10010
offsetinteger❌Pagination0
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
ParameterTypeRequiredDescriptionExample
companyNamestringβœ…Company nameCompuCom Systems, Inc.
numberstring❌CTASK numberCTASK317807
changeRequeststring❌Parent change requestCHG215578
statestring❌Task stateOpen
workflowStateenum❌New | In Progress | Complete | Cancelled / RejectedComplete
assignedTostring❌Assignee emailscott.ward@compucom.com
cmdbCIstring❌Related CI nameCMPC APPL Mulesoft
limitinteger❌Max 10010
offsetinteger❌Pagination0
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:#ffcdd2
Validation 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
  1. Lookup CTASK by number and companyName
  2. If found β†’ Update with provided fields
  3. 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
ParameterTypeRequiredDescriptionExample
companyIdinteger❌Company ID232566
companyNamestring❌Company nameCompuCom Systems, Inc.
parentLocationIdinteger❌Parent location ID5578
lastModifiedDateRangestring❌Modified date range2023-11-08T21:05:15TO2023-11-08T21:10:15
limitinteger❌Max 10010
offsetinteger❌Pagination0
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
ParameterTypeRequiredDescriptionExample
tableSysIdstringβœ…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 TypeValueNotes
Max Size5 MBPer attachment
Base64 Limit6,666,669 charsFormula: x = (n * 3/4) - y
Max Attachments5Per 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

FileEnvironmentLocationPurpose
prod.propertiesProductionsrc/main/resources/properties/Production configuration
qc.propertiesQC/Testsrc/main/resources/properties/QC environment configuration
cmdb-ci-mapping.propertiesAllsrc/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 NameServiceNow CodeProperty Key
Open1sn.request.items.state.Open
Closed3sn.request.items.state.Closed
SC Tasks States
State NameServiceNow CodeProperty Key
Open1sn.sc.tasks.state.Open
Closed3sn.sc.tasks.state.Closed
New1sn.u.sc.task.state.new
Active2sn.u.sc.task.state.active
Work Started3sn.u.sc.task.state.work.started
Awaiting Customer Info4sn.u.sc.task.state.awaiting.customer.info
Closed6sn.u.sc.task.state.closed
In Progress9sn.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=435d8af91b00e15423e3ddf1cd4bcbf3

Resolution 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
SettingValuePurpose
Encryption AlgorithmBlowfishProperty encryption
Encryption KeyMule@123Master key (change in production!)
Secure Properties Fileproperties/${mule.env}.propertiesEncrypted 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: Response

Implementation 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?OffsetServiceNow Time
2022-07-15T10:00:00βœ… Yes (Summer)-5h2022-07-15T05:00:00
2022-12-15T10:00:00❌ No (Winter)-6h2022-12-15T04:00:00
2023-03-12T03:00:00⚠️ Transition-5h2023-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" />
PropertyValuePurpose
namestandard-servicenow-app-configReferenced by main flow
apistandard-servicenow-app.ramlRAML specification file
outboundHeadersMapNameoutboundHeadersVariable for response headers
httpStatusVarNamehttpStatusVariable 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:

SettingValue SourceExample
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:

  1. HTTP Listener receives requests at /standard/sn/*
  2. Transform Message sets:

    • vars.apiTracking - Captures API start time and request details
    • vars.apiCaller - Extracts username from Basic Auth header
  3. APIKit Router routes to appropriate flow based on RAML

  4. Logger logs completion time
  5. Error Handler catches and formats errors
Timezone Handling

The application handles timezone conversions from user input (CST) to ServiceNow's internal timezone:

  • Uses check-daylight Groovy 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:#ef9a9a
Error Type Handling Matrix
Error TypeHTTP StatusHandlerResponse Format
APIKIT:BAD_REQUEST400DW TransformStandard or CTI-specific
APIKIT:NOT_FOUND404DW TransformStandard error
APIKIT:METHOD_NOT_ALLOWED405DW TransformStandard error
APIKIT:NOT_ACCEPTABLE406DW TransformStandard error
APIKIT:UNSUPPORTED_MEDIA_TYPE415DW TransformStandard error
APIKIT:NOT_IMPLEMENTED501DW TransformStandard error
HTTP:TIMEOUT500GenericTimeout error
HTTP:CONNECTIVITY500GenericConnectivity error
ANY500GenericInternal 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]ms

Example 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 Output
2. PUT/POST Pattern
Input Logger β†’ Validate/Lookup β†’ Transform Request β†’
HTTP Request β†’ Transform Response
3. 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 β†’ Error

Special Features

1. CMDB CI Include Pattern

When fetching a single CMDB CI by sys_id, supports include=location parameter:

  • Fetches CI details
  • If include contains "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)) - y where 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:#c8e6c9

CloudHub Configuration

From pom.xml β†’ <armDeployment> section:

SettingValueDescription
Application Namestandard-servicenow-appApp identifier in CloudHub
Mule Version4.7.1Runtime version
Anypoint URIhttps://anypoint.mulesoft.comPlatform URL
Target TypeclusterDeployment target type
Business Group568df9ca-3029-4a74-b8fa-fb4f73a377c2Organization ID
Auth Typeclient_credentialsOAuth 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 Deployed
Branch: 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=$targetPROD

Required Pipeline Variables

Configure in Bitbucket β†’ Repository Settings β†’ Pipelines β†’ Variables:

VariableTypeDescriptionExample
clientIdSecuredAnypoint Connected App Client IDa1b2c3d4e5f6...
clientSecretSecuredAnypoint Connected App SecretX1Y2Z3...
environmentQCPlainQC environment nameQC or Test
targetQCPlainQC cluster nameqc-cluster-01
environmentPRODPlainProduction environment nameProduction
targetPRODPlainProduction cluster nameprod-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.jar
Deploy to CloudHub via Maven
mvn clean deploy -DmuleDeploy \
  -DclientId=YOUR_CLIENT_ID \
  -DclientSecret=YOUR_CLIENT_SECRET \
  -Denvironment=QC \
  -Dtarget=qc-cluster-01
Deploy via Runtime Manager UI
  1. Build the JAR:mvn clean package
  2. Login to Anypoint Platform:

    • Navigate to Runtime Manager
    • Click "Deploy Application"
  3. 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)
  4. Properties:

    • Set mule.env to prod or qc
    • Configure other environment-specific properties
  5. 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: Running in 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:

  1. Immediate Rollback:# Deploy previous working versionmvn clean deploy -DmuleDeploy -DclientId=$clientId -DclientSecret=$clientSecret -Denvironment=$environment -Dtarget=$target -Dversion=PREVIOUS_VERSION
  2. Via Runtime Manager:

    • Navigate to application
    • Click "Manage Application"
    • Select "Redeploy" with previous JAR version
  3. 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
EnvironmentPath
CloudHub/opt/mule/logs/standard-servicenow-app/
On-Premise${mule.home}/logs/standard-servicenow-app/
Local Studioworkspace/.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
└─ Date

Key Performance Indicators (KPIs)

Response Time Metrics
MetricTargetWarningCriticalDescription
API Response Time< 2s2-5s> 5sTotal time from request to response
System API Call Time< 1.5s1.5-4s> 4sTime waiting for System API
Transform Time< 100ms100-500ms> 500msDataWeave execution time

Log Entry Example:

Time taken to complete GET:/standard/sn/requestItems is : 1245ms

Error Rate Metrics
Error TypeTargetWarningCritical
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:

  1. Top Clients - By vars.apiCaller
  2. Most Used Endpoints - /requestItems, /scTasks, etc.
  3. Peak Usage Times - Hourly/daily patterns
  4. Geographic Distribution - Request origins
  5. 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-123
Accessing 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 incident

Health 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.0

output 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+
βœ“ Git
2. 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 application
3. 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 needed
4. 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 response
Step 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.xml

Generated 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=2
Step 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
ElementConventionExample
Flow{resource}-{operation}-Flowrequest-items-GET-Flow
Sub-flow{purpose}-Sub_Flowvalidate-dates-Sub_Flow
VariablecamelCaseoriginalPayload, apiCaller
Propertydot.separated.lowercasesn.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 CaseInputExpected OutputStatus
βœ… Valid requestAll required params200 + data
⚠️ Missing required paramNo assignmentGroup400 error
⚠️ Invalid formatBad date format400 error
⚠️ System API timeoutN/A500 timeout error
βœ… Paginationlimit=10, offset=010 records
βœ… Max limitlimit=100Max 100 records
⚠️ Over max limitlimit=150400 error
βœ… Date rangeValid rangeFiltered results
⚠️ Invalid timezoneWrong TZ format400/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
IssueSymptomFix
Domain not foundListener config errorInstall domain: mvn clean install in domain project
Secure property errorDecryption failedCheck secure.key matches encryption key
Timezone offset wrongData 1 hour offVerify daylight savings logic
Null pointerNPE in DataWeaveAdd null checks with default or if
TimeoutHTTP:TIMEOUTIncrease sn.system.app.response.timeout
Debug DataWeave in Studio
  1. Set breakpoint in Transform Message
  2. Run in Debug mode
  3. Inspect variables in Debug perspective
  4. 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:#ffcdd2

Common 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:

CauseSymptomFix
Domain not deployedFailed to deploy domainDeploy domain project first
Port conflictAddress already in useCheck other apps using same port
Out of memoryOutOfMemoryErrorIncrease worker size or restart
Configuration errorFailed to startCheck properties file syntax

Resolution Steps:

  1. Stop application in Runtime Manager
  2. Check logs for specific error
  3. Fix configuration issue
  4. Redeploy application
  5. 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:

ScenarioSolutionConfiguration
System API consistently slowIncrease timeoutsn.system.app.response.timeout=120000
Large result setsAdd paginationEnforce limit parameter
DataWeave performanceOptimize transformsReview DW code
Network issuesCheck connectivityTest 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]
  1. Update Properties:servicenow.system.api.password=![YOUR_ENCRYPTED_VALUE]
  2. 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:

  1. Extract API Caller from Auth Header:// Should extract username from Basic Authvars.apiCaller = (fromBase64((attributes.headers.Authorization splitBy " ")[1]) splitBy ":")[0]
  2. Verify Mapping Exists:# Check properties fileapi.consumer.{extracted_username}=consumer_nameapi.consumer.{consumer_name}.company=sys_id
  3. 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 -c
Performance 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

SeverityResponse TimeEscalate ToContact
P1 - Critical15 minutesOn-call EngineerPagerDuty
P2 - High1 hourTeam LeadSlack #incidents
P3 - Medium4 hoursDevelopment TeamSlack #dev-support
P4 - LowNext business dayBacklogJIRA 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

ResourceMethodEndpointPurposeAuth Required
Request ItemsGET/requestItemsQuery request itemsβœ…
SC TasksGET/scTasksQuery SC tasksβœ…
SC TasksPUT/scTasksUpdate SC taskβœ…
SC TasksPUT/scTasks/commentsAdd commentsβœ…
CMDB CIGET/cmdbCIQuery CIsβœ…
CMDB CIGET/cmdbCI/{sysId}Get specific CIβœ…
CMDB CIPUT/cmdbCIUpdate CIβœ…
CMDB CI ServerGET/cmdbCIServerQuery serversβœ…
CMDB CI ServerPOST/cmdbCIServerCreate serverβœ…
CMDB CI ServerPUT/cmdbCIServerUpdate serverβœ…
CI RelationshipGET/cmdbCiRelationshipQuery relationshipsβœ…
CI RelationshipPOST/cmdbCiRelationshipCreate relationshipβœ…
CI RelationshipDELETE/cmdbCiRelationshipDelete relationshipβœ…
Change TaskGET/ctaskQuery change tasksβœ…
Change TaskPOST/ctaskCreate change taskβœ…
Change TaskPUT/ctaskUpdate change taskβœ…
Change TaskPUT/ctask/commentsAdd commentsβœ…
LocationGET/locationQuery locationsβœ…
LocationPOST/locationCreate locationβœ…
LocationPUT/locationUpdate locationβœ…
AttachmentsGET/attachmentsGet attachmentsβœ…

Appendix B: Environment Variables

VariableEnvironmentDefaultDescription
mule.envAllprodEnvironment selector
secure.keyAllMule@123Encryption key
sn.system.app.hostAlllocalhostSystem API host
sn.system.app.portAll8081System API port
sn.system.app.base.pathAll/api/systemSystem API base path
sn.system.app.response.timeoutAll90000Timeout (ms)
api.idAll18583435API Manager ID

Appendix C: State Code Reference

Request Items
1 = Open
2 = Work in Progress
3 = Closed
4 = Closed Incomplete
5 = Closed Skipped
SC Tasks
1 = New (Open)
2 = Active
3 = Work Started
4 = Awaiting Customer Info
6 = Closed
9 = In Progress

Appendix D: Error Code Reference

HTTP CodeError TypeMeaningTypical Cause
400APIKIT:BAD_REQUESTInvalid requestMissing param, wrong format
401HTTP:UNAUTHORIZEDAuth failedWrong credentials
404APIKIT:NOT_FOUNDEndpoint not foundWrong URL
405APIKIT:METHOD_NOT_ALLOWEDWrong HTTP methodUsed POST instead of GET
406APIKIT:NOT_ACCEPTABLEAccept header issueWrong Accept header
415APIKIT:UNSUPPORTED_MEDIA_TYPEWrong Content-TypeMissing/wrong Content-Type
500HTTP:TIMEOUTRequest timeoutSystem API slow/down
500ANYServer errorApplication error
501APIKIT:NOT_IMPLEMENTEDNot implementedEndpoint defined but not implemented
503HTTP:CONNECTIVITYConnectivity issueSystem 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

VersionDateChangesTicket
1.0.02024-07-06Initial documented version-
0.9.02024-06-15Added attachments APICN-330
0.8.02024-05-20Added comments for sctask/ctaskCN-300
0.7.02024-04-10Made fields optional, enhanced commentsCN-297
0.6.02024-03-15CI synch, INC synch integration-
0.5.02024-02-01Connect Hub integration-

Appendix H: Performance Benchmarks

Based on production metrics (30-day average):

MetricValueNotes
Avg Response Time845msP50
P95 Response Time2.3s95th percentile
P99 Response Time4.8s99th percentile
Error Rate0.8%4xx + 5xx errors
Throughput150 req/minPeak hours
Availability99.7%Last 30 days
ResourceURLDescription
Anypoint Platformhttps://anypoint.mulesoft.comMuleSoft platform
Production APIhttps://muleprod.diam.compucom.com/standard/snProduction base URL
Production Consolehttps://muleprod.diam.compucom.com/console/standard/snProduction API console
QC APIhttps://muleqc.diam.compucom.com/standard/snQC/Test base URL
QC Consolehttps://muleqc.diam.compucom.com/console/standard/snQC API console
Runtime Managerhttps://anypoint.mulesoft.com/cloudhubApp monitoring
API Managerhttps://anypoint.mulesoft.com/apimanagerAPI policies
Bitbucket Repohttps://bitbucket.org/compucomtechservices/standard-servicenow-appSource code
JIRA Projecthttps://jira.company.com/MULEIssue tracking
Confluence Wikihttps://confluence.company.com/mulesoftTeam documentation

πŸ”’ Security Considerations

Authentication & Authorization

LayerMethodDetails
API Consumer β†’ Process APIHTTP Basic AuthBase64 encoded credentials
Process API β†’ System APIHTTP Basic AuthConfigured credentials
API ManagerClient ID enforcementOptional 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:

PolicyPurposeConfiguration
Rate LimitingPrevent abuse100 req/min per client
Client ID EnforcementTrack clientsRequired
IP WhitelistRestrict accessKnown IPs only
Threat ProtectionBlock attacksJSON/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)
Limit TypeRecommendedMaximumRationale
Records per request10-25100Balance response time vs. requests
Attachment size1-2 MB5 MBNetwork performance
Date range7 days90 daysQuery performance
Concurrent requests1050CloudHub worker capacity

πŸ“ž Support and Maintenance

Team Contacts

RoleContactHours
Development Leaddev-lead@company.comMon-Fri 9am-5pm CST
DevOps Teamdevops@company.com24/7 (on-call)
Product Ownerproduct@company.comMon-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

BranchPurposeDeploys ToPR Required
masterProduction codePRODβœ… Yes
developmentIntegration testingQCβœ… Yes
release/*Release candidatesQCβœ… Yes
feature/*New featuresLocalN/A
hotfix/*Emergency fixesPROD (fast-track)βœ… Yes

Maintenance Schedule

TaskFrequencyOwnerDuration
Dependency UpdatesMonthlyDevelopment2 hours
Log CleanupWeeklyDevOps30 min
Performance ReviewWeeklyDevelopment1 hour
Security ScanMonthlySecurity Team4 hours
DR DrillQuarterlyDevOps4 hours
API Documentation ReviewQuarterlyProduct Owner2 hours

πŸ“ Document Information

Document Metadata

FieldValue
Document TitleStandard ServiceNow Application - Technical Documentation
Version2.0
Date Created2024-07-06
Last Updated2026-07-06
AuthorMuleSoft Development Team
Maintained ByDevOps Team
Review CycleQuarterly
Next Review2026-10-06

Document Change History

VersionDateAuthorChanges
2.02026-07-06Claude AIEnhanced documentation with diagrams, tables, and comprehensive guides
1.02024-07-06Dev TeamInitial comprehensive documentation
0.52024-06-01Dev TeamBasic README

Contributing to This Documentation

To update this documentation:

  1. Fork/Branch: Create feature branch
  2. Edit: Update CLAUDE.md
  3. Test: Verify links and code samples
  4. Review: Get peer review
  5. Merge: Merge to development
  6. 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 ↑


Reviews