0
# Context Management and Logging
1
2
Runtime context access and logging utilities for job execution. Provides thread-safe access to job parameters, logging, and result handling during job execution.
3
4
## Capabilities
5
6
### XxlJobHelper Utility Class
7
8
Static helper methods for accessing job execution context, logging, and handling job results. All methods are thread-safe and work within job execution threads.
9
10
```java { .api }
11
/**
12
* Static utility class for job execution context and logging
13
* All methods are thread-safe and work within job execution context
14
*/
15
public class XxlJobHelper {
16
17
// Context access methods
18
/**
19
* Get current job ID
20
* @return Current job's unique identifier
21
*/
22
public static long getJobId();
23
24
/**
25
* Get job execution parameters passed from admin trigger
26
* @return Parameter string passed to job execution
27
*/
28
public static String getJobParam();
29
30
/**
31
* Get current job log file name
32
* @return Log file name for current job execution
33
*/
34
public static String getJobLogFileName();
35
36
/**
37
* Get shard index for distributed job execution
38
* @return Current shard index (0-based)
39
*/
40
public static int getShardIndex();
41
42
/**
43
* Get total number of shards for distributed job execution
44
* @return Total number of shards
45
*/
46
public static int getShardTotal();
47
48
// Logging methods
49
/**
50
* Log message with pattern formatting (similar to SLF4J)
51
* @param appendLogPattern - Log message pattern with {} placeholders
52
* @param appendLogArguments - Arguments to substitute in pattern
53
* @return true if log was written successfully
54
*/
55
public static boolean log(String appendLogPattern, Object... appendLogArguments);
56
57
/**
58
* Log exception with stack trace
59
* @param e - Exception to log
60
* @return true if log was written successfully
61
*/
62
public static boolean log(Throwable e);
63
64
// Result handling methods
65
/**
66
* Mark job execution as successful
67
* @return true if result was set successfully
68
*/
69
public static boolean handleSuccess();
70
71
/**
72
* Mark job execution as successful with custom message
73
* @param handleMsg - Success message
74
* @return true if result was set successfully
75
*/
76
public static boolean handleSuccess(String handleMsg);
77
78
/**
79
* Mark job execution as failed
80
* @return true if result was set successfully
81
*/
82
public static boolean handleFail();
83
84
/**
85
* Mark job execution as failed with error message
86
* @param handleMsg - Failure message
87
* @return true if result was set successfully
88
*/
89
public static boolean handleFail(String handleMsg);
90
91
/**
92
* Mark job execution as timed out
93
* @return true if result was set successfully
94
*/
95
public static boolean handleTimeout();
96
97
/**
98
* Mark job execution as timed out with custom message
99
* @param handleMsg - Timeout message
100
* @return true if result was set successfully
101
*/
102
public static boolean handleTimeout(String handleMsg);
103
104
/**
105
* Set custom result code and message
106
* @param handleCode - Custom result code (200=success, 500=fail, 502=timeout)
107
* @param handleMsg - Result message
108
* @return true if result was set successfully
109
*/
110
public static boolean handleResult(int handleCode, String handleMsg);
111
}
112
```
113
114
**Usage Examples:**
115
116
```java
117
import com.xxl.job.core.handler.annotation.XxlJob;
118
import com.xxl.job.core.context.XxlJobHelper;
119
120
@Component
121
public class ContextExampleJobHandler {
122
123
@XxlJob("contextExample")
124
public void contextExampleHandler() throws Exception {
125
// Access job context
126
long jobId = XxlJobHelper.getJobId();
127
String param = XxlJobHelper.getJobParam();
128
129
XxlJobHelper.log("Job {} started with param: {}", jobId, param);
130
131
try {
132
// Job logic here
133
processData(param);
134
135
// Log success
136
XxlJobHelper.log("Data processed successfully");
137
XxlJobHelper.handleSuccess("Processed " + dataCount + " records");
138
139
} catch (Exception e) {
140
XxlJobHelper.log("Job failed with exception: {}", e.getMessage());
141
XxlJobHelper.log(e); // Log full stack trace
142
XxlJobHelper.handleFail("Processing failed: " + e.getMessage());
143
}
144
}
145
146
@XxlJob("shardedExample")
147
public void shardedExampleHandler() throws Exception {
148
// Get sharding information
149
int shardIndex = XxlJobHelper.getShardIndex();
150
int shardTotal = XxlJobHelper.getShardTotal();
151
152
XxlJobHelper.log("Processing shard {} of {} shards", shardIndex, shardTotal);
153
154
// Process only data for this shard
155
List<Data> allData = getAllData();
156
List<Data> shardData = new ArrayList<>();
157
158
for (int i = shardIndex; i < allData.size(); i += shardTotal) {
159
shardData.add(allData.get(i));
160
}
161
162
XxlJobHelper.log("Shard {} will process {} items", shardIndex, shardData.size());
163
164
// Process shard data
165
for (Data item : shardData) {
166
processItem(item);
167
}
168
169
XxlJobHelper.handleSuccess("Shard " + shardIndex + " processed " + shardData.size() + " items");
170
}
171
172
@XxlJob("progressExample")
173
public void progressExampleHandler() throws Exception {
174
List<Task> tasks = getTasks();
175
int totalTasks = tasks.size();
176
int completed = 0;
177
178
XxlJobHelper.log("Starting processing of {} tasks", totalTasks);
179
180
for (Task task : tasks) {
181
try {
182
processTask(task);
183
completed++;
184
185
// Log progress every 10%
186
if (completed % Math.max(1, totalTasks / 10) == 0) {
187
int percentage = (completed * 100) / totalTasks;
188
XxlJobHelper.log("Progress: {}/{}% ({}/{})",
189
percentage,completed, totalTasks);
190
}
191
192
} catch (Exception e) {
193
XxlJobHelper.log("Task {} failed: {}", task.getId(), e.getMessage());
194
// Continue processing other tasks
195
}
196
}
197
198
XxlJobHelper.handleSuccess("Completed " + completed + "/" + totalTasks + " tasks");
199
}
200
}
201
```
202
203
### XxlJobContext Class
204
205
Job execution context holder that maintains job state and execution information in thread-local storage.
206
207
```java { .api }
208
/**
209
* Job execution context holder using thread-local storage
210
* Provides access to current job execution state and parameters
211
*/
212
public class XxlJobContext {
213
214
// Result code constants
215
/**
216
* Success result code
217
*/
218
public static final int HANDLE_CODE_SUCCESS = 200;
219
220
/**
221
* Failure result code
222
*/
223
public static final int HANDLE_CODE_FAIL = 500;
224
225
/**
226
* Timeout result code
227
*/
228
public static final int HANDLE_CODE_TIMEOUT = 502;
229
230
// Context management
231
/**
232
* Set job context for current thread
233
* @param xxlJobContext - Context instance to set
234
*/
235
public static void setXxlJobContext(XxlJobContext xxlJobContext);
236
237
/**
238
* Get job context for current thread
239
* @return Current thread's job context or null if not in job execution
240
*/
241
public static XxlJobContext getXxlJobContext();
242
243
// Context data accessors
244
/**
245
* Get current job ID
246
* @return Job identifier
247
*/
248
public long getJobId();
249
250
/**
251
* Get job execution parameters
252
* @return Parameter string
253
*/
254
public String getJobParam();
255
256
/**
257
* Get job log file name
258
* @return Log file name for current execution
259
*/
260
public String getJobLogFileName();
261
262
/**
263
* Get shard index for distributed execution
264
* @return Current shard index
265
*/
266
public int getShardIndex();
267
268
/**
269
* Get total shard count for distributed execution
270
* @return Total number of shards
271
*/
272
public int getShardTotal();
273
274
/**
275
* Get job execution handle code
276
* @return Current result code (200=success, 500=fail, 502=timeout)
277
*/
278
public int getHandleCode();
279
280
/**
281
* Get job execution handle message
282
* @return Current result message
283
*/
284
public String getHandleMsg();
285
}
286
```
287
288
## Context Usage Patterns
289
290
### Parameter Processing
291
292
```java
293
@XxlJob("parameterProcessor")
294
public void parameterProcessorHandler() throws Exception {
295
String param = XxlJobHelper.getJobParam();
296
297
if (param == null || param.trim().isEmpty()) {
298
XxlJobHelper.handleFail("Job parameter is required");
299
return;
300
}
301
302
try {
303
// Parse JSON parameters
304
ObjectMapper mapper = new ObjectMapper();
305
JobParameters params = mapper.readValue(param, JobParameters.class);
306
307
XxlJobHelper.log("Processing with parameters: startDate={}, endDate={}, mode={}",
308
params.getStartDate(), params.getEndDate(), params.getMode());
309
310
// Validate parameters
311
if (params.getStartDate().isAfter(params.getEndDate())) {
312
XxlJobHelper.handleFail("Start date must be before end date");
313
return;
314
}
315
316
// Process with parameters
317
processDateRange(params.getStartDate(), params.getEndDate(), params.getMode());
318
319
XxlJobHelper.handleSuccess("Processed date range successfully");
320
321
} catch (JsonProcessingException e) {
322
XxlJobHelper.log("Invalid JSON parameter: {}", e.getMessage());
323
XxlJobHelper.handleFail("Invalid parameter format: " + e.getMessage());
324
}
325
}
326
```
327
328
### Distributed Job Processing
329
330
```java
331
@XxlJob("distributedProcessor")
332
public void distributedProcessorHandler() throws Exception {
333
int shardIndex = XxlJobHelper.getShardIndex();
334
int shardTotal = XxlJobHelper.getShardTotal();
335
336
XxlJobHelper.log("Shard {}/{} starting processing", shardIndex + 1, shardTotal);
337
338
// Get data for this shard
339
List<Long> allIds = getAllRecordIds();
340
List<Long> shardIds = new ArrayList<>();
341
342
// Distribute IDs across shards
343
for (int i = shardIndex; i < allIds.size(); i += shardTotal) {
344
shardIds.add(allIds.get(i));
345
}
346
347
XxlJobHelper.log("Shard {} will process {} records", shardIndex, shardIds.size());
348
349
int processed = 0;
350
int failed = 0;
351
352
for (Long id : shardIds) {
353
try {
354
processRecord(id);
355
processed++;
356
357
// Log progress periodically
358
if (processed % 100 == 0) {
359
XxlJobHelper.log("Shard {} processed {} records", shardIndex, processed);
360
}
361
362
} catch (Exception e) {
363
failed++;
364
XxlJobHelper.log("Failed to process record {}: {}", id, e.getMessage());
365
}
366
}
367
368
String result = String.format("Shard %d completed: %d processed, %d failed",
369
shardIndex, processed, failed);
370
371
if (failed == 0) {
372
XxlJobHelper.handleSuccess(result);
373
} else {
374
XxlJobHelper.handleFail(result);
375
}
376
}
377
```
378
379
### Long-Running Job with Progress
380
381
```java
382
@XxlJob("longRunningJob")
383
public void longRunningJobHandler() throws Exception {
384
String param = XxlJobHelper.getJobParam();
385
int batchSize = param != null ? Integer.parseInt(param) : 1000;
386
387
XxlJobHelper.log("Starting long-running job with batch size: {}", batchSize);
388
389
long totalRecords = getTotalRecordCount();
390
long processed = 0;
391
long startTime = System.currentTimeMillis();
392
393
XxlJobHelper.log("Total records to process: {}", totalRecords);
394
395
try {
396
while (processed < totalRecords) {
397
long remaining = Math.min(batchSize, totalRecords - processed);
398
399
XxlJobHelper.log("Processing batch: {} records (offset: {})", remaining, processed);
400
401
// Process batch
402
List<Record> batch = getRecordBatch(processed, (int) remaining);
403
for (Record record : batch) {
404
processRecord(record);
405
}
406
407
processed += remaining;
408
409
// Log progress
410
double percentage = (processed * 100.0) / totalRecords;
411
long elapsed = System.currentTimeMillis() - startTime;
412
long estimatedTotal = (long) (elapsed / (percentage / 100.0));
413
long remaining = estimatedTotal - elapsed;
414
415
XxlJobHelper.log("Progress: {}/{} ({:.1f}%) - ETA: {} seconds",
416
processed, totalRecords, percentage, remaining / 1000);
417
}
418
419
long totalTime = System.currentTimeMillis() - startTime;
420
XxlJobHelper.handleSuccess("Processed " + processed + " records in " + totalTime + "ms");
421
422
} catch (Exception e) {
423
XxlJobHelper.log("Job failed after processing {} records: {}", processed, e.getMessage());
424
XxlJobHelper.log(e);
425
XxlJobHelper.handleFail("Failed after processing " + processed + " records");
426
}
427
}
428
```
429
430
### Job Result Handling
431
432
```java
433
@XxlJob("resultHandler")
434
public void resultHandlerHandler() throws Exception {
435
try {
436
String result = performBusinessLogic();
437
438
// Handle different result scenarios
439
if (result.equals("PARTIAL_SUCCESS")) {
440
XxlJobHelper.handleResult(200, "Completed with warnings: " + result);
441
} else if (result.equals("NO_DATA")) {
442
XxlJobHelper.handleResult(200, "No data to process");
443
} else if (result.equals("BUSINESS_ERROR")) {
444
XxlJobHelper.handleResult(500, "Business logic error: " + result);
445
} else {
446
XxlJobHelper.handleSuccess("Processing completed: " + result);
447
}
448
449
} catch (TimeoutException e) {
450
XxlJobHelper.handleTimeout("Operation timed out after " + e.getTimeout() + "ms");
451
} catch (BusinessException e) {
452
XxlJobHelper.handleFail("Business error: " + e.getMessage());
453
} catch (Exception e) {
454
XxlJobHelper.log(e);
455
XxlJobHelper.handleFail("Unexpected error: " + e.getClass().getSimpleName());
456
}
457
}
458
```
459
460
## Logging Best Practices
461
462
### Structured Logging
463
464
```java
465
@XxlJob("structuredLogging")
466
public void structuredLoggingHandler() throws Exception {
467
long jobId = XxlJobHelper.getJobId();
468
String param = XxlJobHelper.getJobParam();
469
470
// Use structured log format
471
XxlJobHelper.log("[JOB_START] jobId={}, param={}, timestamp={}",
472
jobId, param, System.currentTimeMillis());
473
474
try {
475
// Business logic with structured logging
476
XxlJobHelper.log("[PROCESSING] action=data_fetch, status=started");
477
List<Data> data = fetchData();
478
XxlJobHelper.log("[PROCESSING] action=data_fetch, status=completed, count={}", data.size());
479
480
XxlJobHelper.log("[PROCESSING] action=data_transform, status=started");
481
List<Data> transformed = transformData(data);
482
XxlJobHelper.log("[PROCESSING] action=data_transform, status=completed, count={}", transformed.size());
483
484
XxlJobHelper.log("[JOB_END] status=success, processed={}", transformed.size());
485
XxlJobHelper.handleSuccess("Processed " + transformed.size() + " records");
486
487
} catch (Exception e) {
488
XxlJobHelper.log("[JOB_END] status=error, error={}", e.getMessage());
489
XxlJobHelper.log(e);
490
XxlJobHelper.handleFail(e.getMessage());
491
}
492
}
493
```