JAXB Binding Compiler (XJC) that generates Java classes from XML Schema definitions with both command-line and programmatic APIs
—
JAXB XJC provides comprehensive error reporting and validation capabilities through a flexible error handling system that supports different integration patterns and customization levels.
Base error handling infrastructure for both command-line and programmatic usage.
/**
* Abstract base class for handling compilation errors, warnings, and info messages
*/
public abstract class ErrorReceiver {
/**
* Handle compilation errors that prevent successful generation
* @param exception SAXParseException containing error details and location
*/
public abstract void error(SAXParseException exception);
/**
* Handle compilation warnings that don't prevent generation
* @param exception SAXParseException containing warning details and location
*/
public abstract void warning(SAXParseException exception);
/**
* Handle informational messages about compilation process
* @param exception SAXParseException containing info details and location
*/
public abstract void info(SAXParseException exception);
/**
* Check if compilation should be aborted
* Called periodically during long-running operations
* @throws AbortException if compilation should be terminated
*/
public void pollAbort() throws AbortException;
/**
* Handle generic exceptions during compilation
* @param e Exception that occurred
*/
public void error(Exception e);
/**
* Handle errors with custom messages
* @param msg Error message
* @param e Underlying exception, may be null
*/
public void error(String msg, Exception e);
/**
* Log debug messages if debug mode is enabled
* @param msg Debug message
*/
public final void debug(String msg);
}Simplified error handling interface for programmatic API usage.
/**
* Error handling interface for programmatic API with structured error reporting
*/
public interface ErrorListener {
/**
* Handle compilation errors
* @param exception SAXParseException with error details including line/column numbers
*/
void error(SAXParseException exception);
/**
* Handle compilation warnings
* @param exception SAXParseException with warning details including line/column numbers
*/
void warning(SAXParseException exception);
/**
* Handle informational messages
* @param exception SAXParseException with info details including line/column numbers
*/
void info(SAXParseException exception);
}Advanced error processing utilities for customizing error handling behavior.
/**
* Error receiver that filters and processes errors before delegating
*/
public class ErrorReceiverFilter extends ErrorReceiver {
/**
* Delegate error receiver
*/
protected final ErrorReceiver core;
/**
* Create filter with delegate receiver
* @param core ErrorReceiver to delegate filtered messages to
*/
public ErrorReceiverFilter(ErrorReceiver core);
// Filtering can be customized in subclasses
public void error(SAXParseException exception);
public void warning(SAXParseException exception);
public void info(SAXParseException exception);
public void pollAbort() throws AbortException;
}Built-in console error reporter for command-line usage.
/**
* Console-based error reporter with formatted output
*/
public class ConsoleErrorReporter extends ErrorReceiver {
/**
* Create console reporter writing to specified PrintStream
* @param output PrintStream for error output
*/
public ConsoleErrorReporter(PrintStream output);
/**
* Create console reporter with custom error counter
* @param output PrintStream for error output
* @param errorCounter Counter for tracking error statistics
*/
public ConsoleErrorReporter(PrintStream output, ErrorCounter errorCounter);
public void error(SAXParseException exception);
public void warning(SAXParseException exception);
public void info(SAXParseException exception);
/**
* Check if any errors have been reported
* @return true if errors occurred
*/
public boolean hadError();
}Specific exception types for different error conditions.
/**
* Exception thrown when command line arguments are invalid
*/
public class BadCommandLineException extends Exception {
/**
* Create exception with message
* @param message Error description
*/
public BadCommandLineException(String message);
/**
* Create exception with message and cause
* @param message Error description
* @param cause Underlying cause
*/
public BadCommandLineException(String message, Throwable cause);
/**
* Initialize with options for context
* @param opts Options object for additional context
*/
public void initOptions(Options opts);
/**
* Get associated options
* @return Options object or null
*/
public Options getOptions();
}
/**
* Exception thrown to abort compilation
*/
public class AbortException extends RuntimeException {
/**
* Create abort exception
*/
public AbortException();
/**
* Create abort exception with message
* @param message Exception message
*/
public AbortException(String message);
}Basic Error Listener Implementation:
import com.sun.tools.xjc.api.ErrorListener;
import org.xml.sax.SAXParseException;
import java.util.ArrayList;
import java.util.List;
public class CollectingErrorListener implements ErrorListener {
private final List<SAXParseException> errors = new ArrayList<>();
private final List<SAXParseException> warnings = new ArrayList<>();
private final List<SAXParseException> infos = new ArrayList<>();
@Override
public void error(SAXParseException exception) {
errors.add(exception);
System.err.printf("ERROR [%s:%d:%d] %s%n",
exception.getSystemId(),
exception.getLineNumber(),
exception.getColumnNumber(),
exception.getMessage());
}
@Override
public void warning(SAXParseException exception) {
warnings.add(exception);
System.err.printf("WARNING [%s:%d:%d] %s%n",
exception.getSystemId(),
exception.getLineNumber(),
exception.getColumnNumber(),
exception.getMessage());
}
@Override
public void info(SAXParseException exception) {
infos.add(exception);
System.out.printf("INFO: %s%n", exception.getMessage());
}
public boolean hasErrors() {
return !errors.isEmpty();
}
public List<SAXParseException> getErrors() {
return new ArrayList<>(errors);
}
public List<SAXParseException> getWarnings() {
return new ArrayList<>(warnings);
}
}Custom Error Receiver with Filtering:
import com.sun.tools.xjc.util.ErrorReceiverFilter;
import com.sun.tools.xjc.ErrorReceiver;
import org.xml.sax.SAXParseException;
public class FilteringErrorReceiver extends ErrorReceiverFilter {
private final Set<String> suppressedWarnings;
private int errorCount = 0;
private int warningCount = 0;
public FilteringErrorReceiver(ErrorReceiver core, Set<String> suppressedWarnings) {
super(core);
this.suppressedWarnings = suppressedWarnings;
}
@Override
public void error(SAXParseException exception) {
errorCount++;
super.error(exception);
}
@Override
public void warning(SAXParseException exception) {
// Filter out suppressed warnings
String message = exception.getMessage().toLowerCase();
boolean suppressed = suppressedWarnings.stream()
.anyMatch(pattern -> message.contains(pattern.toLowerCase()));
if (!suppressed) {
warningCount++;
super.warning(exception);
}
}
@Override
public void info(SAXParseException exception) {
// Only show info messages in verbose mode
if (System.getProperty("xjc.verbose") != null) {
super.info(exception);
}
}
public int getErrorCount() { return errorCount; }
public int getWarningCount() { return warningCount; }
}Integration with Logging Frameworks:
import com.sun.tools.xjc.api.ErrorListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXParseException;
public class LoggingErrorListener implements ErrorListener {
private static final Logger logger = LoggerFactory.getLogger(LoggingErrorListener.class);
@Override
public void error(SAXParseException exception) {
logger.error("XJC compilation error at {}:{}:{} - {}",
exception.getSystemId(),
exception.getLineNumber(),
exception.getColumnNumber(),
exception.getMessage(),
exception);
}
@Override
public void warning(SAXParseException exception) {
logger.warn("XJC compilation warning at {}:{}:{} - {}",
exception.getSystemId(),
exception.getLineNumber(),
exception.getColumnNumber(),
exception.getMessage());
}
@Override
public void info(SAXParseException exception) {
logger.info("XJC compilation info: {}", exception.getMessage());
}
}Build Tool Integration Error Handling:
import com.sun.tools.xjc.api.ErrorListener;
import org.apache.maven.plugin.logging.Log;
import org.xml.sax.SAXParseException;
public class MavenLogErrorListener implements ErrorListener {
private final Log log;
private boolean hasErrors = false;
public MavenLogErrorListener(Log log) {
this.log = log;
}
@Override
public void error(SAXParseException exception) {
hasErrors = true;
log.error(String.format("XJC Error [%s:%d:%d]: %s",
getFileName(exception.getSystemId()),
exception.getLineNumber(),
exception.getColumnNumber(),
exception.getMessage()),
exception);
}
@Override
public void warning(SAXParseException exception) {
log.warn(String.format("XJC Warning [%s:%d:%d]: %s",
getFileName(exception.getSystemId()),
exception.getLineNumber(),
exception.getColumnNumber(),
exception.getMessage()));
}
@Override
public void info(SAXParseException exception) {
if (log.isDebugEnabled()) {
log.debug("XJC Info: " + exception.getMessage());
}
}
private String getFileName(String systemId) {
if (systemId == null) return "unknown";
int lastSlash = Math.max(systemId.lastIndexOf('/'), systemId.lastIndexOf('\\'));
return lastSlash >= 0 ? systemId.substring(lastSlash + 1) : systemId;
}
public boolean hasErrors() {
return hasErrors;
}
}Schema Validation Error Handling:
import com.sun.tools.xjc.api.*;
import org.xml.sax.SAXParseException;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.XMLConstants;
public class ValidatingSchemaCompiler {
public static S2JJAXBModel compileWithValidation(File schemaFile) throws Exception {
// Pre-validate schema before compilation
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
ValidationErrorHandler validationHandler = new ValidationErrorHandler();
factory.setErrorHandler(validationHandler);
try {
Schema schema = factory.newSchema(schemaFile);
System.out.println("Schema validation successful");
} catch (Exception e) {
if (validationHandler.hasErrors()) {
throw new Exception("Schema validation failed with errors", e);
}
}
// Proceed with XJC compilation
SchemaCompiler compiler = XJC.createSchemaCompiler();
CollectingErrorListener errorListener = new CollectingErrorListener();
compiler.setErrorListener(errorListener);
compiler.parseSchema(new InputSource(new FileInputStream(schemaFile)));
S2JJAXBModel model = compiler.bind();
if (errorListener.hasErrors()) {
throw new Exception("XJC compilation failed with errors");
}
return model;
}
private static class ValidationErrorHandler implements org.xml.sax.ErrorHandler {
private boolean hasErrors = false;
@Override
public void error(SAXParseException exception) {
hasErrors = true;
System.err.println("Validation Error: " + exception.getMessage());
}
@Override
public void warning(SAXParseException exception) {
System.err.println("Validation Warning: " + exception.getMessage());
}
@Override
public void fatalError(SAXParseException exception) {
hasErrors = true;
System.err.println("Validation Fatal Error: " + exception.getMessage());
}
public boolean hasErrors() { return hasErrors; }
}
}Error Recovery Strategies:
import com.sun.tools.xjc.Driver;
import com.sun.tools.xjc.XJCListener;
import org.xml.sax.SAXParseException;
public class RobustXJCExecution {
public static boolean executeWithRecovery(String[] args) {
RecoveryListener listener = new RecoveryListener();
try {
int result = Driver.run(args, listener);
if (result != 0) {
System.err.println("XJC execution failed with exit code: " + result);
listener.printSummary();
return false;
}
if (listener.hasWarnings()) {
System.out.println("XJC completed with warnings:");
listener.printSummary();
}
return true;
} catch (Exception e) {
System.err.println("XJC execution failed with exception: " + e.getMessage());
listener.printSummary();
return false;
}
}
private static class RecoveryListener extends XJCListener {
private final List<String> errors = new ArrayList<>();
private final List<String> warnings = new ArrayList<>();
@Override
public void error(SAXParseException exception) {
errors.add(formatError("ERROR", exception));
}
@Override
public void warning(SAXParseException exception) {
warnings.add(formatError("WARNING", exception));
}
@Override
public void info(SAXParseException exception) {
// Log info messages for debugging
}
@Override
public void generatedFile(String fileName, int count, int total) {
System.out.printf("Generated %s (%d/%d)%n", fileName, count, total);
}
@Override
public void message(String msg) {
System.out.println(msg);
}
private String formatError(String level, SAXParseException e) {
return String.format("%s [%s:%d:%d] %s",
level,
e.getSystemId() != null ? e.getSystemId() : "unknown",
e.getLineNumber(),
e.getColumnNumber(),
e.getMessage());
}
public boolean hasErrors() { return !errors.isEmpty(); }
public boolean hasWarnings() { return !warnings.isEmpty(); }
public void printSummary() {
if (!errors.isEmpty()) {
System.err.println("\nErrors:");
errors.forEach(System.err::println);
}
if (!warnings.isEmpty()) {
System.err.println("\nWarnings:");
warnings.forEach(System.err::println);
}
System.err.printf("\nSummary: %d errors, %d warnings%n",
errors.size(), warnings.size());
}
}
}This error handling system provides comprehensive error reporting and validation capabilities, enabling robust integration of XJC into various development workflows and build systems.
Install with Tessl CLI
npx tessl i tessl/maven-org-glassfish-jaxb--jaxb-xjc