0
# Build Tool Integration
1
2
JAXB XJC provides comprehensive integration capabilities for build systems including Ant tasks, Maven plugins, and Gradle integration through both dedicated tasks and programmatic APIs.
3
4
## Capabilities
5
6
### Ant Task Integration
7
8
XJC provides dedicated Ant tasks for integrating schema compilation into Ant-based build processes.
9
10
```java { .api }
11
/**
12
* Modern XJC Ant task with full feature support
13
*/
14
public class XJC2Task extends Task {
15
/**
16
* Set schema file or directory to compile
17
* @param schema File or directory containing schemas
18
*/
19
public void setSchema(File schema);
20
21
/**
22
* Set target directory for generated sources
23
* @param destdir Target directory
24
*/
25
public void setDestdir(File destdir);
26
27
/**
28
* Set target package name for generated classes
29
* @param packageName Package name
30
*/
31
public void setPackage(String packageName);
32
33
/**
34
* Set binding customization file
35
* @param binding Binding file
36
*/
37
public void setBinding(File binding);
38
39
/**
40
* Set catalog file for entity resolution
41
* @param catalog Catalog file
42
*/
43
public void setCatalog(File catalog);
44
45
/**
46
* Enable or disable package level annotations
47
* @param packageLevelAnnotations true to enable
48
*/
49
public void setPackageLevelAnnotations(boolean packageLevelAnnotations);
50
51
/**
52
* Set character encoding for generated files
53
* @param encoding Character encoding
54
*/
55
public void setEncoding(String encoding);
56
57
/**
58
* Enable read-only mode
59
* @param readOnly true for read-only
60
*/
61
public void setReadOnly(boolean readOnly);
62
63
/**
64
* Set header comment for generated files
65
* @param header Header comment
66
*/
67
public void setHeader(String header);
68
69
/**
70
* Enable extension mode
71
* @param extension true to enable extensions
72
*/
73
public void setExtension(boolean extension);
74
75
/**
76
* Execute the task
77
* @throws BuildException if compilation fails
78
*/
79
public void execute() throws BuildException;
80
}
81
82
/**
83
* Legacy XJC Ant task for compatibility
84
*/
85
public class XJCTask extends Task {
86
// Similar interface to XJC2Task but with legacy behavior
87
public void setSchema(String schema);
88
public void setDestdir(File destdir);
89
public void setPackage(String packageName);
90
public void execute() throws BuildException;
91
}
92
93
/**
94
* Base class for XJC Ant tasks
95
*/
96
public class XJCBase {
97
/**
98
* Common configuration and execution logic for XJC Ant tasks
99
*/
100
protected void configureOptions(Options options);
101
protected void executeXJC(Options options) throws BuildException;
102
}
103
```
104
105
**Ant Task Usage Examples:**
106
107
```xml
108
<!-- Basic XJC task -->
109
<taskdef name="xjc" classname="com.sun.tools.xjc.XJC2Task">
110
<classpath>
111
<fileset dir="lib" includes="jaxb-xjc-*.jar"/>
112
</classpath>
113
</taskdef>
114
115
<!-- Simple schema compilation -->
116
<xjc schema="src/main/resources/schema.xsd"
117
destdir="target/generated-sources"
118
package="com.example.generated"/>
119
120
<!-- Advanced configuration -->
121
<xjc destdir="target/generated-sources" package="com.example.api">
122
<schema dir="src/main/resources/schemas" includes="**/*.xsd"/>
123
<binding dir="src/main/resources/bindings" includes="**/*.xjb"/>
124
<classpath>
125
<fileset dir="lib" includes="*.jar"/>
126
</classpath>
127
<arg value="-Xfluent-api"/>
128
<arg value="-verbose"/>
129
</xjc>
130
131
<!-- Multiple schemas with dependencies -->
132
<xjc destdir="target/generated-sources"
133
package="com.example.common"
134
extension="true">
135
<schema file="common.xsd"/>
136
<produces dir="target/generated-sources/com/example/common" includes="**/*.java"/>
137
<depends file="common.xsd"/>
138
</xjc>
139
140
<xjc destdir="target/generated-sources"
141
package="com.example.specific"
142
extension="true">
143
<schema file="specific.xsd"/>
144
<classpath>
145
<pathelement path="target/generated-sources"/>
146
</classpath>
147
<arg value="-episode"/>
148
<arg value="target/common.episode"/>
149
</xjc>
150
```
151
152
### Maven Plugin Integration
153
154
Integration patterns for Maven-based builds using the JAXB Maven plugin.
155
156
**Maven Plugin Configuration Examples:**
157
158
```xml
159
<!-- Basic Maven configuration -->
160
<plugin>
161
<groupId>org.jvnet.jaxb2.maven2</groupId>
162
<artifactId>maven-jaxb2-plugin</artifactId>
163
<version>0.14.0</version>
164
<configuration>
165
<schemaDirectory>src/main/resources/schemas</schemaDirectory>
166
<generatePackage>com.example.generated</generatePackage>
167
<generateDirectory>target/generated-sources/xjc</generateDirectory>
168
</configuration>
169
<executions>
170
<execution>
171
<goals>
172
<goal>generate</goal>
173
</goals>
174
</execution>
175
</executions>
176
<dependencies>
177
<dependency>
178
<groupId>org.glassfish.jaxb</groupId>
179
<artifactId>jaxb-xjc</artifactId>
180
<version>4.0.5</version>
181
</dependency>
182
</dependencies>
183
</plugin>
184
185
<!-- Advanced Maven configuration with plugins -->
186
<plugin>
187
<groupId>org.jvnet.jaxb2.maven2</groupId>
188
<artifactId>maven-jaxb2-plugin</artifactId>
189
<version>0.14.0</version>
190
<configuration>
191
<schemaDirectory>src/main/resources/schemas</schemaDirectory>
192
<bindingDirectory>src/main/resources/bindings</bindingDirectory>
193
<generatePackage>com.example.api</generatePackage>
194
<generateDirectory>target/generated-sources/xjc</generateDirectory>
195
<extension>true</extension>
196
<args>
197
<arg>-Xfluent-api</arg>
198
<arg>-Xtostring</arg>
199
<arg>-XautoNameResolution</arg>
200
</args>
201
<plugins>
202
<plugin>
203
<groupId>com.example</groupId>
204
<artifactId>xjc-fluent-plugin</artifactId>
205
<version>1.0.0</version>
206
</plugin>
207
</plugins>
208
</configuration>
209
</plugin>
210
```
211
212
### Gradle Integration
213
214
Gradle integration using the JAXB plugin and custom task definitions.
215
216
**Gradle Plugin Usage:**
217
218
```groovy
219
// Apply JAXB plugin
220
plugins {
221
id 'java'
222
id 'org.unbroken-dome.xjc' version '2.0.0'
223
}
224
225
// Configure XJC
226
xjc {
227
srcDirName = 'src/main/schemas'
228
bindingFiles = fileTree(dir: 'src/main/bindings', include: '**/*.xjb')
229
targetPackage = 'com.example.generated'
230
outputDir = file('build/generated-sources/xjc')
231
}
232
233
// Dependencies
234
dependencies {
235
implementation 'org.glassfish.jaxb:jaxb-runtime:4.0.5'
236
xjc 'org.glassfish.jaxb:jaxb-xjc:4.0.5'
237
}
238
239
// Custom XJC task
240
task generateFromCustomSchema(type: org.unbroken_dome.gradle.plugins.xjc.XjcGenerate) {
241
source = fileTree(dir: 'custom-schemas', include: '**/*.xsd')
242
bindingFiles = fileTree(dir: 'custom-bindings', include: '**/*.xjb')
243
targetPackage = 'com.example.custom'
244
outputDirectory = file('build/generated-sources/custom')
245
options {
246
extension = true
247
header = false
248
verbose = true
249
}
250
}
251
```
252
253
### Programmatic Build Integration
254
255
Custom build integration using the programmatic API for specialized build requirements.
256
257
```java { .api }
258
/**
259
* Custom build integration utility
260
*/
261
public class BuildIntegration {
262
/**
263
* Execute XJC compilation with build-specific configuration
264
* @param config Build configuration
265
* @return true if compilation successful
266
*/
267
public static boolean executeXJC(BuildConfiguration config);
268
269
/**
270
* Generate code with custom post-processing
271
* @param schemas Schema files to compile
272
* @param outputDir Output directory
273
* @param packageName Target package
274
* @param postProcessor Custom post-processor
275
* @return Generated code model
276
*/
277
public static JCodeModel generateWithPostProcessing(
278
List<File> schemas,
279
File outputDir,
280
String packageName,
281
CodePostProcessor postProcessor);
282
}
283
284
/**
285
* Configuration for build integration
286
*/
287
public class BuildConfiguration {
288
private List<File> schemaFiles;
289
private List<File> bindingFiles;
290
private File outputDirectory;
291
private String targetPackage;
292
private List<String> plugins;
293
private Map<String, String> properties;
294
private ErrorListener errorListener;
295
296
// Configuration methods
297
public void addSchemaFile(File schema);
298
public void addBindingFile(File binding);
299
public void setOutputDirectory(File dir);
300
public void setTargetPackage(String packageName);
301
public void addPlugin(String pluginName);
302
public void setProperty(String key, String value);
303
public void setErrorListener(ErrorListener listener);
304
}
305
```
306
307
**Custom Build Integration Example:**
308
309
```java
310
import com.sun.tools.xjc.api.*;
311
import com.sun.codemodel.*;
312
import java.io.File;
313
import java.util.List;
314
import java.util.ArrayList;
315
316
public class CustomBuildIntegration {
317
318
public static class BuildResult {
319
private final boolean success;
320
private final List<String> generatedFiles;
321
private final List<String> errors;
322
private final List<String> warnings;
323
324
public BuildResult(boolean success, List<String> generatedFiles,
325
List<String> errors, List<String> warnings) {
326
this.success = success;
327
this.generatedFiles = new ArrayList<>(generatedFiles);
328
this.errors = new ArrayList<>(errors);
329
this.warnings = new ArrayList<>(warnings);
330
}
331
332
public boolean isSuccess() { return success; }
333
public List<String> getGeneratedFiles() { return generatedFiles; }
334
public List<String> getErrors() { return errors; }
335
public List<String> getWarnings() { return warnings; }
336
}
337
338
public static BuildResult compileSchemas(
339
List<File> schemaFiles,
340
File outputDir,
341
String packageName,
342
List<String> pluginArgs) {
343
344
List<String> generatedFiles = new ArrayList<>();
345
List<String> errors = new ArrayList<>();
346
List<String> warnings = new ArrayList<>();
347
348
try {
349
// Create compiler
350
SchemaCompiler compiler = XJC.createSchemaCompiler();
351
352
// Configure error handling
353
compiler.setErrorListener(new ErrorListener() {
354
@Override
355
public void error(SAXParseException exception) {
356
errors.add(formatError("ERROR", exception));
357
}
358
359
@Override
360
public void warning(SAXParseException exception) {
361
warnings.add(formatError("WARNING", exception));
362
}
363
364
@Override
365
public void info(SAXParseException exception) {
366
// Log info messages
367
}
368
});
369
370
// Configure compiler
371
compiler.setDefaultPackageName(packageName);
372
373
// Parse schemas
374
for (File schemaFile : schemaFiles) {
375
InputSource source = new InputSource(new FileInputStream(schemaFile));
376
source.setSystemId(schemaFile.toURI().toString());
377
compiler.parseSchema(source);
378
}
379
380
// Compile
381
S2JJAXBModel model = compiler.bind();
382
if (model == null) {
383
errors.add("Schema compilation failed");
384
return new BuildResult(false, generatedFiles, errors, warnings);
385
}
386
387
// Generate code
388
JCodeModel codeModel = model.generateCode(null, null);
389
390
// Custom code writer that tracks generated files
391
FileCodeWriter writer = new FileCodeWriter(outputDir) {
392
@Override
393
public Writer openSource(JPackage pkg, String fileName) throws IOException {
394
generatedFiles.add(pkg.name().replace('.', '/') + "/" + fileName);
395
return super.openSource(pkg, fileName);
396
}
397
};
398
399
codeModel.build(writer);
400
401
return new BuildResult(true, generatedFiles, errors, warnings);
402
403
} catch (Exception e) {
404
errors.add("Build failed: " + e.getMessage());
405
return new BuildResult(false, generatedFiles, errors, warnings);
406
}
407
}
408
409
private static String formatError(String level, SAXParseException e) {
410
return String.format("%s [%s:%d:%d] %s",
411
level,
412
e.getSystemId() != null ? e.getSystemId() : "unknown",
413
e.getLineNumber(),
414
e.getColumnNumber(),
415
e.getMessage());
416
}
417
}
418
```
419
420
### Multi-Module Build Support
421
422
Support for complex multi-module builds with shared schemas and episode files.
423
424
**Episode-Based Multi-Module Build:**
425
426
```java
427
import com.sun.tools.xjc.Driver;
428
import java.io.File;
429
import java.util.Arrays;
430
431
public class MultiModuleBuildSupport {
432
433
public static void buildCommonModule(File schemaDir, File outputDir, File episodeFile)
434
throws Exception {
435
String[] args = {
436
"-d", outputDir.getAbsolutePath(),
437
"-p", "com.example.common",
438
"-episode", episodeFile.getAbsolutePath(),
439
new File(schemaDir, "common.xsd").getAbsolutePath()
440
};
441
442
int result = Driver.run(args, System.out, System.err);
443
if (result != 0) {
444
throw new Exception("Common module compilation failed");
445
}
446
}
447
448
public static void buildSpecificModule(File schemaDir, File outputDir,
449
File episodeFile, File commonClasspath)
450
throws Exception {
451
String[] args = {
452
"-d", outputDir.getAbsolutePath(),
453
"-p", "com.example.specific",
454
"-classpath", commonClasspath.getAbsolutePath(),
455
episodeFile.getAbsolutePath(),
456
new File(schemaDir, "specific.xsd").getAbsolutePath()
457
};
458
459
int result = Driver.run(args, System.out, System.err);
460
if (result != 0) {
461
throw new Exception("Specific module compilation failed");
462
}
463
}
464
}
465
```
466
467
### Incremental Build Support
468
469
Support for incremental builds to optimize build performance.
470
471
```java
472
import java.io.File;
473
import java.nio.file.Files;
474
import java.nio.file.attribute.FileTime;
475
import java.util.List;
476
import java.util.stream.Collectors;
477
478
public class IncrementalBuildSupport {
479
480
public static boolean needsRecompilation(List<File> schemaFiles,
481
List<File> bindingFiles,
482
File outputDir) {
483
// Check if output directory exists
484
if (!outputDir.exists() || !outputDir.isDirectory()) {
485
return true;
486
}
487
488
// Find newest input file
489
FileTime newestInput = schemaFiles.stream()
490
.flatMap(f -> Stream.concat(
491
Stream.of(f),
492
bindingFiles.stream()
493
))
494
.map(f -> {
495
try {
496
return Files.getLastModifiedTime(f.toPath());
497
} catch (IOException e) {
498
return FileTime.fromMillis(0);
499
}
500
})
501
.max(FileTime::compareTo)
502
.orElse(FileTime.fromMillis(0));
503
504
// Find oldest output file
505
try {
506
FileTime oldestOutput = Files.walk(outputDir.toPath())
507
.filter(Files::isRegularFile)
508
.filter(p -> p.toString().endsWith(".java"))
509
.map(p -> {
510
try {
511
return Files.getLastModifiedTime(p);
512
} catch (IOException e) {
513
return FileTime.fromMillis(Long.MAX_VALUE);
514
}
515
})
516
.min(FileTime::compareTo)
517
.orElse(FileTime.fromMillis(Long.MAX_VALUE));
518
519
return newestInput.compareTo(oldestOutput) > 0;
520
521
} catch (IOException e) {
522
return true; // Error reading output, force recompilation
523
}
524
}
525
526
public static void cleanOutputDirectory(File outputDir, String packageName) {
527
File packageDir = new File(outputDir, packageName.replace('.', '/'));
528
if (packageDir.exists()) {
529
try {
530
Files.walk(packageDir.toPath())
531
.sorted(Comparator.reverseOrder())
532
.map(Path::toFile)
533
.forEach(File::delete);
534
} catch (IOException e) {
535
System.err.println("Warning: Could not clean output directory: " + e.getMessage());
536
}
537
}
538
}
539
}
540
```
541
542
### Build Performance Optimization
543
544
Optimization techniques for large-scale builds.
545
546
```java
547
public class BuildOptimization {
548
549
/**
550
* Parallel schema compilation for independent schema groups
551
*/
552
public static void compileInParallel(List<SchemaGroup> schemaGroups,
553
int maxThreads) {
554
ExecutorService executor = Executors.newFixedThreadPool(maxThreads);
555
List<Future<BuildResult>> futures = new ArrayList<>();
556
557
for (SchemaGroup group : schemaGroups) {
558
Future<BuildResult> future = executor.submit(() -> {
559
return CustomBuildIntegration.compileSchemas(
560
group.getSchemaFiles(),
561
group.getOutputDir(),
562
group.getPackageName(),
563
group.getPluginArgs()
564
);
565
});
566
futures.add(future);
567
}
568
569
// Wait for all compilations to complete
570
for (Future<BuildResult> future : futures) {
571
try {
572
BuildResult result = future.get();
573
if (!result.isSuccess()) {
574
System.err.println("Compilation failed: " + result.getErrors());
575
}
576
} catch (Exception e) {
577
System.err.println("Compilation error: " + e.getMessage());
578
}
579
}
580
581
executor.shutdown();
582
}
583
584
/**
585
* Memory-efficient compilation for large schemas
586
*/
587
public static void compileWithMemoryOptimization(List<File> schemaFiles,
588
File outputDir,
589
String packageName) {
590
// Process schemas in batches to manage memory usage
591
int batchSize = 10;
592
for (int i = 0; i < schemaFiles.size(); i += batchSize) {
593
int endIndex = Math.min(i + batchSize, schemaFiles.size());
594
List<File> batch = schemaFiles.subList(i, endIndex);
595
596
try {
597
CustomBuildIntegration.compileSchemas(batch, outputDir,
598
packageName + ".batch" + (i / batchSize), Collections.emptyList());
599
600
// Force garbage collection between batches
601
System.gc();
602
603
} catch (Exception e) {
604
System.err.println("Batch compilation failed: " + e.getMessage());
605
}
606
}
607
}
608
}
609
```
610
611
This build integration system provides comprehensive support for integrating JAXB XJC into various build systems and workflows, with optimizations for performance and maintainability in large-scale projects.