Install
openclaw skills install @jrd77/xxl-job-debugopenclaw skills install @jrd77/xxl-job-debugUse 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.
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.
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.
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.
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.
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.
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:
NONE
CRON
FIX_RATE
DO_NOTHING
FIRE_ONCE_NOW
FIRST
LAST
ROUND
RANDOM
CONSISTENT_HASH
LEAST_FREQUENTLY_USED
LEAST_RECENTLY_USED
FAILOVER
BUSYOVER
SHARDING_BROADCAST
SERIAL_EXECUTION
DISCARD_LATER
COVER_EARLY
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.
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.
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.Use:
POST {ADMIN_URL}/api/triggerJob
Request:
{
"id": 123,
"executorParam": "debug",
"addressList": "http://127.0.0.1:9999/"
}
When executor selection does not matter:
{
"id": 123,
"executorParam": "debug",
"addressList": ""
}
The scheduler resolves registered executors.
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.
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
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.
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.
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.
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.
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.
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.
resolve task
→ resolve local executor
→ /beat
→ triggerJob(addressList=local)
→ log
→ result
resolve executor
→ create task
→ capture jobId
→ start task
→ trigger once
→ log
→ result
→ delete task
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.
resolve executor
→ idleBeat
→ log
→ determine running state
→ kill if appropriate
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.
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
Job:
AppName:
Executor:
Handler:
Param:
LogId:
Status:
Result:
Task created
JobId:
Executor:
Handler:
Schedule:
Status:
Task updated
JobId:
Changed:
Status:
XXL-JOB operation failed
Action:
JobId:
Executor:
Stage:
Error:
Evidence:
Keep output focused on the operation and evidence.
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