0
# Error Handling and Validation
1
2
JAXB XJC provides comprehensive error reporting and validation capabilities through a flexible error handling system that supports different integration patterns and customization levels.
3
4
## Capabilities
5
6
### Error Receiver System
7
8
Base error handling infrastructure for both command-line and programmatic usage.
9
10
```java { .api }
11
/**
12
* Abstract base class for handling compilation errors, warnings, and info messages
13
*/
14
public abstract class ErrorReceiver {
15
/**
16
* Handle compilation errors that prevent successful generation
17
* @param exception SAXParseException containing error details and location
18
*/
19
public abstract void error(SAXParseException exception);
20
21
/**
22
* Handle compilation warnings that don't prevent generation
23
* @param exception SAXParseException containing warning details and location
24
*/
25
public abstract void warning(SAXParseException exception);
26
27
/**
28
* Handle informational messages about compilation process
29
* @param exception SAXParseException containing info details and location
30
*/
31
public abstract void info(SAXParseException exception);
32
33
/**
34
* Check if compilation should be aborted
35
* Called periodically during long-running operations
36
* @throws AbortException if compilation should be terminated
37
*/
38
public void pollAbort() throws AbortException;
39
40
/**
41
* Handle generic exceptions during compilation
42
* @param e Exception that occurred
43
*/
44
public void error(Exception e);
45
46
/**
47
* Handle errors with custom messages
48
* @param msg Error message
49
* @param e Underlying exception, may be null
50
*/
51
public void error(String msg, Exception e);
52
53
/**
54
* Log debug messages if debug mode is enabled
55
* @param msg Debug message
56
*/
57
public final void debug(String msg);
58
}
59
```
60
61
### Programmatic API Error Listener
62
63
Simplified error handling interface for programmatic API usage.
64
65
```java { .api }
66
/**
67
* Error handling interface for programmatic API with structured error reporting
68
*/
69
public interface ErrorListener {
70
/**
71
* Handle compilation errors
72
* @param exception SAXParseException with error details including line/column numbers
73
*/
74
void error(SAXParseException exception);
75
76
/**
77
* Handle compilation warnings
78
* @param exception SAXParseException with warning details including line/column numbers
79
*/
80
void warning(SAXParseException exception);
81
82
/**
83
* Handle informational messages
84
* @param exception SAXParseException with info details including line/column numbers
85
*/
86
void info(SAXParseException exception);
87
}
88
```
89
90
### Error Filtering and Processing
91
92
Advanced error processing utilities for customizing error handling behavior.
93
94
```java { .api }
95
/**
96
* Error receiver that filters and processes errors before delegating
97
*/
98
public class ErrorReceiverFilter extends ErrorReceiver {
99
/**
100
* Delegate error receiver
101
*/
102
protected final ErrorReceiver core;
103
104
/**
105
* Create filter with delegate receiver
106
* @param core ErrorReceiver to delegate filtered messages to
107
*/
108
public ErrorReceiverFilter(ErrorReceiver core);
109
110
// Filtering can be customized in subclasses
111
public void error(SAXParseException exception);
112
public void warning(SAXParseException exception);
113
public void info(SAXParseException exception);
114
public void pollAbort() throws AbortException;
115
}
116
```
117
118
### Console Error Reporting
119
120
Built-in console error reporter for command-line usage.
121
122
```java { .api }
123
/**
124
* Console-based error reporter with formatted output
125
*/
126
public class ConsoleErrorReporter extends ErrorReceiver {
127
/**
128
* Create console reporter writing to specified PrintStream
129
* @param output PrintStream for error output
130
*/
131
public ConsoleErrorReporter(PrintStream output);
132
133
/**
134
* Create console reporter with custom error counter
135
* @param output PrintStream for error output
136
* @param errorCounter Counter for tracking error statistics
137
*/
138
public ConsoleErrorReporter(PrintStream output, ErrorCounter errorCounter);
139
140
public void error(SAXParseException exception);
141
public void warning(SAXParseException exception);
142
public void info(SAXParseException exception);
143
144
/**
145
* Check if any errors have been reported
146
* @return true if errors occurred
147
*/
148
public boolean hadError();
149
}
150
```
151
152
### Exception Types
153
154
Specific exception types for different error conditions.
155
156
```java { .api }
157
/**
158
* Exception thrown when command line arguments are invalid
159
*/
160
public class BadCommandLineException extends Exception {
161
/**
162
* Create exception with message
163
* @param message Error description
164
*/
165
public BadCommandLineException(String message);
166
167
/**
168
* Create exception with message and cause
169
* @param message Error description
170
* @param cause Underlying cause
171
*/
172
public BadCommandLineException(String message, Throwable cause);
173
174
/**
175
* Initialize with options for context
176
* @param opts Options object for additional context
177
*/
178
public void initOptions(Options opts);
179
180
/**
181
* Get associated options
182
* @return Options object or null
183
*/
184
public Options getOptions();
185
}
186
187
/**
188
* Exception thrown to abort compilation
189
*/
190
public class AbortException extends RuntimeException {
191
/**
192
* Create abort exception
193
*/
194
public AbortException();
195
196
/**
197
* Create abort exception with message
198
* @param message Exception message
199
*/
200
public AbortException(String message);
201
}
202
```
203
204
### Error Handling Examples
205
206
**Basic Error Listener Implementation:**
207
208
```java
209
import com.sun.tools.xjc.api.ErrorListener;
210
import org.xml.sax.SAXParseException;
211
import java.util.ArrayList;
212
import java.util.List;
213
214
public class CollectingErrorListener implements ErrorListener {
215
private final List<SAXParseException> errors = new ArrayList<>();
216
private final List<SAXParseException> warnings = new ArrayList<>();
217
private final List<SAXParseException> infos = new ArrayList<>();
218
219
@Override
220
public void error(SAXParseException exception) {
221
errors.add(exception);
222
System.err.printf("ERROR [%s:%d:%d] %s%n",
223
exception.getSystemId(),
224
exception.getLineNumber(),
225
exception.getColumnNumber(),
226
exception.getMessage());
227
}
228
229
@Override
230
public void warning(SAXParseException exception) {
231
warnings.add(exception);
232
System.err.printf("WARNING [%s:%d:%d] %s%n",
233
exception.getSystemId(),
234
exception.getLineNumber(),
235
exception.getColumnNumber(),
236
exception.getMessage());
237
}
238
239
@Override
240
public void info(SAXParseException exception) {
241
infos.add(exception);
242
System.out.printf("INFO: %s%n", exception.getMessage());
243
}
244
245
public boolean hasErrors() {
246
return !errors.isEmpty();
247
}
248
249
public List<SAXParseException> getErrors() {
250
return new ArrayList<>(errors);
251
}
252
253
public List<SAXParseException> getWarnings() {
254
return new ArrayList<>(warnings);
255
}
256
}
257
```
258
259
**Custom Error Receiver with Filtering:**
260
261
```java
262
import com.sun.tools.xjc.util.ErrorReceiverFilter;
263
import com.sun.tools.xjc.ErrorReceiver;
264
import org.xml.sax.SAXParseException;
265
266
public class FilteringErrorReceiver extends ErrorReceiverFilter {
267
private final Set<String> suppressedWarnings;
268
private int errorCount = 0;
269
private int warningCount = 0;
270
271
public FilteringErrorReceiver(ErrorReceiver core, Set<String> suppressedWarnings) {
272
super(core);
273
this.suppressedWarnings = suppressedWarnings;
274
}
275
276
@Override
277
public void error(SAXParseException exception) {
278
errorCount++;
279
super.error(exception);
280
}
281
282
@Override
283
public void warning(SAXParseException exception) {
284
// Filter out suppressed warnings
285
String message = exception.getMessage().toLowerCase();
286
boolean suppressed = suppressedWarnings.stream()
287
.anyMatch(pattern -> message.contains(pattern.toLowerCase()));
288
289
if (!suppressed) {
290
warningCount++;
291
super.warning(exception);
292
}
293
}
294
295
@Override
296
public void info(SAXParseException exception) {
297
// Only show info messages in verbose mode
298
if (System.getProperty("xjc.verbose") != null) {
299
super.info(exception);
300
}
301
}
302
303
public int getErrorCount() { return errorCount; }
304
public int getWarningCount() { return warningCount; }
305
}
306
```
307
308
**Integration with Logging Frameworks:**
309
310
```java
311
import com.sun.tools.xjc.api.ErrorListener;
312
import org.slf4j.Logger;
313
import org.slf4j.LoggerFactory;
314
import org.xml.sax.SAXParseException;
315
316
public class LoggingErrorListener implements ErrorListener {
317
private static final Logger logger = LoggerFactory.getLogger(LoggingErrorListener.class);
318
319
@Override
320
public void error(SAXParseException exception) {
321
logger.error("XJC compilation error at {}:{}:{} - {}",
322
exception.getSystemId(),
323
exception.getLineNumber(),
324
exception.getColumnNumber(),
325
exception.getMessage(),
326
exception);
327
}
328
329
@Override
330
public void warning(SAXParseException exception) {
331
logger.warn("XJC compilation warning at {}:{}:{} - {}",
332
exception.getSystemId(),
333
exception.getLineNumber(),
334
exception.getColumnNumber(),
335
exception.getMessage());
336
}
337
338
@Override
339
public void info(SAXParseException exception) {
340
logger.info("XJC compilation info: {}", exception.getMessage());
341
}
342
}
343
```
344
345
**Build Tool Integration Error Handling:**
346
347
```java
348
import com.sun.tools.xjc.api.ErrorListener;
349
import org.apache.maven.plugin.logging.Log;
350
import org.xml.sax.SAXParseException;
351
352
public class MavenLogErrorListener implements ErrorListener {
353
private final Log log;
354
private boolean hasErrors = false;
355
356
public MavenLogErrorListener(Log log) {
357
this.log = log;
358
}
359
360
@Override
361
public void error(SAXParseException exception) {
362
hasErrors = true;
363
log.error(String.format("XJC Error [%s:%d:%d]: %s",
364
getFileName(exception.getSystemId()),
365
exception.getLineNumber(),
366
exception.getColumnNumber(),
367
exception.getMessage()),
368
exception);
369
}
370
371
@Override
372
public void warning(SAXParseException exception) {
373
log.warn(String.format("XJC Warning [%s:%d:%d]: %s",
374
getFileName(exception.getSystemId()),
375
exception.getLineNumber(),
376
exception.getColumnNumber(),
377
exception.getMessage()));
378
}
379
380
@Override
381
public void info(SAXParseException exception) {
382
if (log.isDebugEnabled()) {
383
log.debug("XJC Info: " + exception.getMessage());
384
}
385
}
386
387
private String getFileName(String systemId) {
388
if (systemId == null) return "unknown";
389
int lastSlash = Math.max(systemId.lastIndexOf('/'), systemId.lastIndexOf('\\'));
390
return lastSlash >= 0 ? systemId.substring(lastSlash + 1) : systemId;
391
}
392
393
public boolean hasErrors() {
394
return hasErrors;
395
}
396
}
397
```
398
399
### Validation and Schema Processing
400
401
**Schema Validation Error Handling:**
402
403
```java
404
import com.sun.tools.xjc.api.*;
405
import org.xml.sax.SAXParseException;
406
import javax.xml.validation.Schema;
407
import javax.xml.validation.SchemaFactory;
408
import javax.xml.XMLConstants;
409
410
public class ValidatingSchemaCompiler {
411
412
public static S2JJAXBModel compileWithValidation(File schemaFile) throws Exception {
413
// Pre-validate schema before compilation
414
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
415
ValidationErrorHandler validationHandler = new ValidationErrorHandler();
416
factory.setErrorHandler(validationHandler);
417
418
try {
419
Schema schema = factory.newSchema(schemaFile);
420
System.out.println("Schema validation successful");
421
} catch (Exception e) {
422
if (validationHandler.hasErrors()) {
423
throw new Exception("Schema validation failed with errors", e);
424
}
425
}
426
427
// Proceed with XJC compilation
428
SchemaCompiler compiler = XJC.createSchemaCompiler();
429
CollectingErrorListener errorListener = new CollectingErrorListener();
430
compiler.setErrorListener(errorListener);
431
432
compiler.parseSchema(new InputSource(new FileInputStream(schemaFile)));
433
S2JJAXBModel model = compiler.bind();
434
435
if (errorListener.hasErrors()) {
436
throw new Exception("XJC compilation failed with errors");
437
}
438
439
return model;
440
}
441
442
private static class ValidationErrorHandler implements org.xml.sax.ErrorHandler {
443
private boolean hasErrors = false;
444
445
@Override
446
public void error(SAXParseException exception) {
447
hasErrors = true;
448
System.err.println("Validation Error: " + exception.getMessage());
449
}
450
451
@Override
452
public void warning(SAXParseException exception) {
453
System.err.println("Validation Warning: " + exception.getMessage());
454
}
455
456
@Override
457
public void fatalError(SAXParseException exception) {
458
hasErrors = true;
459
System.err.println("Validation Fatal Error: " + exception.getMessage());
460
}
461
462
public boolean hasErrors() { return hasErrors; }
463
}
464
}
465
```
466
467
### Error Recovery and Reporting
468
469
**Error Recovery Strategies:**
470
471
```java
472
import com.sun.tools.xjc.Driver;
473
import com.sun.tools.xjc.XJCListener;
474
import org.xml.sax.SAXParseException;
475
476
public class RobustXJCExecution {
477
478
public static boolean executeWithRecovery(String[] args) {
479
RecoveryListener listener = new RecoveryListener();
480
481
try {
482
int result = Driver.run(args, listener);
483
484
if (result != 0) {
485
System.err.println("XJC execution failed with exit code: " + result);
486
listener.printSummary();
487
return false;
488
}
489
490
if (listener.hasWarnings()) {
491
System.out.println("XJC completed with warnings:");
492
listener.printSummary();
493
}
494
495
return true;
496
497
} catch (Exception e) {
498
System.err.println("XJC execution failed with exception: " + e.getMessage());
499
listener.printSummary();
500
return false;
501
}
502
}
503
504
private static class RecoveryListener extends XJCListener {
505
private final List<String> errors = new ArrayList<>();
506
private final List<String> warnings = new ArrayList<>();
507
508
@Override
509
public void error(SAXParseException exception) {
510
errors.add(formatError("ERROR", exception));
511
}
512
513
@Override
514
public void warning(SAXParseException exception) {
515
warnings.add(formatError("WARNING", exception));
516
}
517
518
@Override
519
public void info(SAXParseException exception) {
520
// Log info messages for debugging
521
}
522
523
@Override
524
public void generatedFile(String fileName, int count, int total) {
525
System.out.printf("Generated %s (%d/%d)%n", fileName, count, total);
526
}
527
528
@Override
529
public void message(String msg) {
530
System.out.println(msg);
531
}
532
533
private String formatError(String level, SAXParseException e) {
534
return String.format("%s [%s:%d:%d] %s",
535
level,
536
e.getSystemId() != null ? e.getSystemId() : "unknown",
537
e.getLineNumber(),
538
e.getColumnNumber(),
539
e.getMessage());
540
}
541
542
public boolean hasErrors() { return !errors.isEmpty(); }
543
public boolean hasWarnings() { return !warnings.isEmpty(); }
544
545
public void printSummary() {
546
if (!errors.isEmpty()) {
547
System.err.println("\nErrors:");
548
errors.forEach(System.err::println);
549
}
550
551
if (!warnings.isEmpty()) {
552
System.err.println("\nWarnings:");
553
warnings.forEach(System.err::println);
554
}
555
556
System.err.printf("\nSummary: %d errors, %d warnings%n",
557
errors.size(), warnings.size());
558
}
559
}
560
}
561
```
562
563
This error handling system provides comprehensive error reporting and validation capabilities, enabling robust integration of XJC into various development workflows and build systems.