XXL-JOB Debug
When to Use
Use when the user asks to create, update, start, stop, trigger, inspect logs of, kill, or delete an XXL-JOB task; when a task needs to run on a specific executor node (especially the local IntelliJ/JVM); or when debugging why an XXL-JOB job did not run as expected.
Purpose
Execute and debug XXL-JOB tasks through the scheduling-center/executor APIs.
Core flow:
Request
↓
Resolve Task / Executor / Token
↓
Perform Operation
↓
Verify Result
↓
Collect Logs
Use rigorous-code-analysis for source-code analysis, modification, testing, and root-cause investigation.
1. Operation Model
Parse natural language into:
action: create | update | start | stop | trigger | log | kill | delete
jobId:
appName:
handler:
executorParam:
targetExecutor:
taskConfig:
Examples:
“执行 123”
→ trigger
“任务 123 在我本地执行”
→ trigger + targetExecutor=local
“新增一个每分钟执行的任务到 xxx 执行器”
→ create
“把 123 的 cron 改成每天 2 点”
→ update
“停止 123”
→ stop
“删除刚才创建的任务”
→ delete
Do not invent jobId, AppName, JobHandler, executor address, or token.
2. Resolve XXL-JOB Connection
Determine:
Admin URL
AccessToken
AppName
Typical executor configuration:
xxl.job.admin.addresses=
xxl.job.executor.appname=
xxl.job.executor.accessToken=
xxl.job.executor.address=
xxl.job.executor.ip=
xxl.job.executor.port=
Older deployments may use different Token property layouts. Inspect the actual project configuration and XXL-JOB version instead of assuming a fixed property name.
AccessToken must match the credentials expected by the target XXL-JOB API. Current XXL-JOB development has also changed token configuration toward executor-level isolation, so prefer the running project's actual configuration over old documentation examples.
Never print the full token.
3. Resolve Executor
For a target AppName, obtain registered executor nodes.
Prefer:
XXL-JOB Executor Management
↓
registered executor addresses
Then verify against:
xxl_job_registry
xxl.job.executor.address
xxl.job.executor.ip
xxl.job.executor.port
The registry uses the executor AppName and executor address to represent registered nodes.
When the user says:
“本地”
“我的 IDEA”
“当前这个 JVM”
select the executor corresponding to the local JVM, not an arbitrary node.
4. Verify Executor
Before executor-specific operations:
POST {EXECUTOR_URL}/beat
Headers:
XXL-JOB-ACCESS-TOKEN: {TOKEN}
XXL-JOB-APPNAME: {APPNAME}
Require a successful response before continuing.
The executor API defines /beat as the heartbeat endpoint.
5. Create Task
Use:
POST {ADMIN_URL}/api/addJob
Headers:
XXL-JOB-ACCESS-TOKEN: {TOKEN}
XXL-JOB-APPNAME: {APPNAME}
Content-Type: application/json
Request:
{
"jobGroup": 1,
"name": "测试任务",
"author": "admin",
"alarmEmail": "",
"scheduleType": "CRON",
"scheduleConf": "0 0/1 * * * ?",
"misfireStrategy": "DO_NOTHING",
"executorRouteStrategy": "FIRST",
"executorHandler": "demoJobHandler",
"executorParam": "",
"executorBlockStrategy": "SERIAL_EXECUTION",
"executorTimeout": 0,
"executorFailRetryCount": 0,
"glueType": "BEAN",
"glueSource": "",
"glueRemark": ""
}
Required task fields:
jobGroup
name
author
scheduleType
scheduleConf
executorRouteStrategy
executorHandler (BEAN)
executorBlockStrategy
glueType
Important configurable values:
scheduleType
NONE
CRON
FIX_RATE
misfireStrategy
DO_NOTHING
FIRE_ONCE_NOW
executorRouteStrategy
FIRST
LAST
ROUND
RANDOM
CONSISTENT_HASH
LEAST_FREQUENTLY_USED
LEAST_RECENTLY_USED
FAILOVER
BUSYOVER
SHARDING_BROADCAST
executorBlockStrategy
SERIAL_EXECUTION
DISCARD_LATER
COVER_EARLY
glueType
BEAN
GLUE_GROOVY
GLUE_SHELL
GLUE_PYTHON
GLUE_NODEJS
GLUE_POWERSHELL
GLUE_PHP
The task fields and route/block/glue options are defined in the uploaded XXL-JOB documentation.
When creating a debugging task, prefer:
simple Cron
BEAN mode
known JobHandler
safe executorParam
Do not create a persistent production-like schedule unless requested.
Capture the returned jobId.
6. Update Task
Use:
POST {ADMIN_URL}/api/updateJob
Request:
{
"id": 123,
"name": "测试任务",
"author": "admin",
"alarmEmail": "",
"scheduleType": "CRON",
"scheduleConf": "0 0/5 * * * ?",
"misfireStrategy": "DO_NOTHING",
"executorRouteStrategy": "FIRST",
"executorHandler": "demoJobHandler",
"executorParam": "test",
"executorBlockStrategy": "SERIAL_EXECUTION",
"executorTimeout": 0,
"executorFailRetryCount": 0,
"glueType": "BEAN",
"glueSource": "",
"glueRemark": ""
}
The update operation requires the existing jobId.
When updating, change only fields required by the request.
7. Start / Stop Task
Start:
POST {ADMIN_URL}/api/startJob
{
"id": 123
}
Stop:
POST {ADMIN_URL}/api/stopJob
{
"id": 123
}
startJob enables subsequent scheduling; stopJob disables subsequent scheduling. Neither should be treated as terminating an already-running execution.
8. Trigger One Execution
Use:
POST {ADMIN_URL}/api/triggerJob
Request:
{
"id": 123,
"executorParam": "debug",
"addressList": "http://127.0.0.1:9999/"
}
Default
When executor selection does not matter:
{
"id": 123,
"executorParam": "debug",
"addressList": ""
}
The scheduler resolves registered executors.
Local debugging
When the user requests a specific node:
{
"id": 123,
"executorParam": "debug",
"addressList": "http://127.0.0.1:9999/"
}
addressList is the preferred mechanism for one-shot targeting and does not require changing the task's persistent routing strategy.
9. Local IntelliJ Debug Flow
For:
“在我本地 IDEA 执行任务 123”
perform:
resolve Job 123
↓
resolve AppName
↓
resolve local executor
↓
/beat
↓
/api/triggerJob
↓
addressList = local executor
↓
capture logId
↓
/log
↓
result
Before triggering, the user should be able to place a breakpoint in:
@XxlJob("handlerName")
public void execute() {
...
}
Verify:
@XxlJob value
==
executorHandler
10. Executor Direct Trigger
Use executor /trigger only when the user explicitly wants executor-local testing and the executor/task metadata is already known.
POST {EXECUTOR_URL}/trigger
Payload:
{
"jobId": 123,
"executorHandler": "demoJobHandler",
"executorParams": "debug",
"executorBlockStrategy": "SERIAL_EXECUTION",
"executorTimeout": 0,
"logId": 0,
"logDateTime": 0,
"glueType": "BEAN",
"glueSource": "",
"glueUpdatetime": 0,
"broadcastIndex": 0,
"broadcastTotal": 0
}
Prefer /api/triggerJob when the scheduler-side execution path is part of the test.
The executor API provides /trigger specifically for triggering a task on the executor.
11. Get Execution Log
After obtaining:
logId
logDateTime
call:
POST {EXECUTOR_URL}/log
Request:
{
"logId": 12345,
"logDateTime": 1586629003729,
"fromLineNum": 0
}
Response:
{
"code": 200,
"content": {
"fromLineNum": 0,
"toLineNum": 100,
"logContent": "...",
"isEnd": true
}
}
For rolling logs:
fromLineNum
→ next fromLineNum
→ ...
→ isEnd=true
The executor API defines fromLineNum and isEnd for rolling log retrieval.
12. Determine Actual Result
Always distinguish:
Trigger accepted
≠
Executor started
≠
Task completed
≠
Task succeeded
Determine:
triggerResult:
executionStatus:
jobResult:
log:
Possible states:
TRIGGER_FAILED
RUNNING
SUCCESS
FAILED
UNKNOWN
Use execution logs and executor/scheduler results as evidence.
13. Busy Check
When a task may already be running:
POST {EXECUTOR_URL}/idleBeat
{
"jobId": 123
}
Use this before retriggering a long-running or serial task.
The executor API defines /idleBeat for checking whether a specified task is busy.
14. Kill Running Task
For a running local/debug task:
POST {EXECUTOR_URL}/kill
{
"jobId": 123
}
Use only for:
explicit user request
or
clearly isolated local debugging
The kill API terminates the executor-side task.
15. Delete Task
Use:
POST {ADMIN_URL}/api/removeJob
{
"id": 123
}
Delete temporary debug tasks after testing when requested or when they were created solely for the debugging workflow.
Do not delete an existing task merely because the debug run failed.
The management API defines removeJob for deleting a specified task.
16. Common Debug Workflows
A. Existing task → local execution
resolve task
→ resolve local executor
→ /beat
→ triggerJob(addressList=local)
→ log
→ result
B. Create temporary debug task
resolve executor
→ create task
→ capture jobId
→ start task
→ trigger once
→ log
→ result
→ delete task
C. Modify existing task for debugging
resolve job
→ update executorParam / schedule configuration
→ trigger once
→ inspect log
→ restore original configuration when necessary
Prefer avoiding persistent changes when triggerJob.executorParam can solve the test.
D. Debug a stuck task
resolve executor
→ idleBeat
→ log
→ determine running state
→ kill if appropriate
17. Task Creation Parameter Rules
When creating a task, explicitly resolve:
executor
task name
author
schedule type
schedule configuration
route strategy
handler
executor param
block strategy
timeout
retry count
glue type
For normal Bean debugging:
scheduleType = NONE or CRON
glueType = BEAN
executorHandler = actual @XxlJob value
For one-shot debugging, prefer:
scheduleType = NONE
and invoke:
triggerJob
instead of creating a recurring schedule unnecessarily.
The task management API supports NONE, CRON, and FIX_RATE scheduling.
18. Error Classification
Classify failures by operation:
Configuration
→ cannot resolve Admin / Token / AppName
Executor
→ /beat failed
Task
→ invalid Job ID / Handler / task configuration
Trigger
→ triggerJob failed
Execution
→ handler/business code failed
Log
→ log retrieval failed
Termination
→ kill failed
Once evidence shows that the problem is in business code, hand off to:
rigorous-code-analysis
19. Output
Trigger
Job:
AppName:
Executor:
Handler:
Param:
LogId:
Status:
Result:
Create
Task created
JobId:
Executor:
Handler:
Schedule:
Status:
Update
Task updated
JobId:
Changed:
Status:
Failure
XXL-JOB operation failed
Action:
JobId:
Executor:
Stage:
Error:
Evidence:
Keep output focused on the operation and evidence.
20. Core Execution Protocol
1. Parse request
2. Resolve Admin URL / AccessToken / AppName
3. Resolve Job / Handler
4. Resolve executor
5. /beat
6. Execute requested API
7. Capture JobId / LogId
8. /log when applicable
9. Determine actual result
10. Hand off code problems to rigorous-code-analysis
For local debugging:
Task
↓
Local Executor
↓
/beat
↓
triggerJob + addressList
↓
IntelliJ breakpoint
↓
logId
↓
/log
↓
result
