0
# Support Utilities
1
2
Spring OXM provides several support classes and utilities that simplify common marshalling operations, provide base implementations for custom marshallers, and integrate with Spring's resource handling and transformation framework.
3
4
## Base Classes
5
6
### AbstractMarshaller
7
8
Abstract base class that provides common functionality for marshaller implementations. It handles various XML processing formats and provides template methods for subclasses.
9
10
```java { .api }
11
public abstract class AbstractMarshaller implements Marshaller, Unmarshaller {
12
13
// Configuration methods
14
public void setSupportDtd(boolean supportDtd);
15
public boolean isSupportDtd();
16
public void setProcessExternalEntities(boolean processExternalEntities);
17
public boolean isProcessExternalEntities();
18
19
// Template methods for subclasses to implement - DOM
20
protected abstract void marshalDomNode(Object graph, Node node) throws XmlMappingException;
21
protected abstract Object unmarshalDomNode(Node node) throws XmlMappingException;
22
23
// Template methods for subclasses to implement - StAX
24
protected abstract void marshalXmlEventWriter(Object graph, XMLEventWriter eventWriter) throws XmlMappingException;
25
protected abstract void marshalXmlStreamWriter(Object graph, XMLStreamWriter streamWriter) throws XmlMappingException;
26
protected abstract Object unmarshalXmlEventReader(XMLEventReader eventReader) throws XmlMappingException;
27
protected abstract Object unmarshalXmlStreamReader(XMLStreamReader streamReader) throws XmlMappingException;
28
29
// Template methods for subclasses to implement - SAX
30
protected abstract void marshalSaxHandlers(Object graph, ContentHandler contentHandler,
31
LexicalHandler lexicalHandler) throws XmlMappingException;
32
protected abstract Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
33
throws XmlMappingException, IOException;
34
35
// Template methods for subclasses to implement - Streams
36
protected abstract void marshalOutputStream(Object graph, OutputStream outputStream)
37
throws XmlMappingException, IOException;
38
protected abstract void marshalWriter(Object graph, Writer writer)
39
throws XmlMappingException, IOException;
40
protected abstract Object unmarshalInputStream(InputStream inputStream)
41
throws XmlMappingException, IOException;
42
protected abstract Object unmarshalReader(Reader reader)
43
throws XmlMappingException, IOException;
44
45
// Utility methods provided by base class
46
protected Document buildDocument();
47
protected XMLReader createXmlReader() throws SAXException, ParserConfigurationException;
48
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory)
49
throws ParserConfigurationException;
50
protected DocumentBuilderFactory createDocumentBuilderFactory() throws ParserConfigurationException;
51
protected SAXParserFactory createSaxParserFactory() throws ParserConfigurationException, SAXException;
52
protected String getDefaultEncoding();
53
}
54
```
55
56
### Usage of AbstractMarshaller
57
58
```java
59
import org.springframework.oxm.support.AbstractMarshaller;
60
import org.springframework.oxm.XmlMappingException;
61
import org.w3c.dom.Node;
62
import org.xml.sax.ContentHandler;
63
import org.xml.sax.InputSource;
64
import org.xml.sax.XMLReader;
65
import java.io.*;
66
67
public class CustomMarshaller extends AbstractMarshaller {
68
69
@Override
70
public boolean supports(Class<?> clazz) {
71
return MyCustomClass.class.isAssignableFrom(clazz);
72
}
73
74
@Override
75
protected void marshalDomNode(Object graph, Node node) throws XmlMappingException {
76
// Implement DOM-based marshalling
77
MyCustomClass obj = (MyCustomClass) graph;
78
// ... marshal to DOM node
79
}
80
81
@Override
82
protected void marshalSaxHandlers(Object graph, ContentHandler contentHandler,
83
LexicalHandler lexicalHandler) throws XmlMappingException {
84
// Implement SAX-based marshalling
85
MyCustomClass obj = (MyCustomClass) graph;
86
// ... marshal using SAX handlers
87
}
88
89
@Override
90
protected void marshalOutputStream(Object graph, OutputStream outputStream)
91
throws XmlMappingException, IOException {
92
// Implement stream-based marshalling
93
MyCustomClass obj = (MyCustomClass) graph;
94
// ... marshal to output stream
95
}
96
97
@Override
98
protected void marshalWriter(Object graph, Writer writer)
99
throws XmlMappingException, IOException {
100
// Implement writer-based marshalling
101
MyCustomClass obj = (MyCustomClass) graph;
102
// ... marshal to writer
103
}
104
105
@Override
106
protected Object unmarshalDomNode(Node node) throws XmlMappingException {
107
// Implement DOM-based unmarshalling
108
// ... unmarshal from DOM node
109
return new MyCustomClass();
110
}
111
112
@Override
113
protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource)
114
throws XmlMappingException, IOException {
115
// Implement SAX-based unmarshalling
116
// ... unmarshal using SAX reader
117
return new MyCustomClass();
118
}
119
120
@Override
121
protected Object unmarshalInputStream(InputStream inputStream)
122
throws XmlMappingException, IOException {
123
// Implement stream-based unmarshalling
124
// ... unmarshal from input stream
125
return new MyCustomClass();
126
}
127
128
@Override
129
protected Object unmarshalReader(Reader reader)
130
throws XmlMappingException, IOException {
131
// Implement reader-based unmarshalling
132
// ... unmarshal from reader
133
return new MyCustomClass();
134
}
135
}
136
```
137
138
## Utility Classes
139
140
### MarshallingSource
141
142
A TrAX Source implementation that uses a Marshaller to provide XML content for transformation operations.
143
144
```java { .api }
145
public class MarshallingSource extends SAXSource {
146
/**
147
* Create a new MarshallingSource with the given marshaller and content.
148
* @param marshaller the marshaller to use
149
* @param content the object to be marshalled
150
*/
151
public MarshallingSource(Marshaller marshaller, Object content);
152
153
/**
154
* Return the Marshaller used by this MarshallingSource.
155
*/
156
public Marshaller getMarshaller();
157
158
/**
159
* Return the object to be marshalled.
160
*/
161
public Object getContent();
162
163
// Note: setInputSource and setXMLReader throw UnsupportedOperationException
164
}
165
```
166
167
### Usage of MarshallingSource
168
169
```java
170
import org.springframework.oxm.support.MarshallingSource;
171
import org.springframework.oxm.Marshaller;
172
import javax.xml.transform.Transformer;
173
import javax.xml.transform.TransformerFactory;
174
import javax.xml.transform.stream.StreamResult;
175
import java.io.StringWriter;
176
177
// Use MarshallingSource with XSLT transformation
178
Marshaller marshaller = // ... get marshaller
179
Customer customer = new Customer("John", "Doe");
180
181
// Create MarshallingSource
182
MarshallingSource source = new MarshallingSource(marshaller, customer);
183
184
// Transform using XSLT
185
TransformerFactory factory = TransformerFactory.newInstance();
186
Transformer transformer = factory.newTransformer(
187
new StreamSource(new FileInputStream("transform.xsl"))
188
);
189
190
StringWriter result = new StringWriter();
191
transformer.transform(source, new StreamResult(result));
192
String transformedXml = result.toString();
193
```
194
195
### SaxResourceUtils
196
197
Utility class for working with SAX and Spring's Resource abstraction.
198
199
```java { .api }
200
public abstract class SaxResourceUtils {
201
/**
202
* Create a SAX InputSource from the given resource.
203
* Sets the system identifier to the resource's URL, if available.
204
* @param resource the resource
205
* @return the input source created from the resource
206
* @throws IOException if an I/O exception occurs
207
*/
208
public static InputSource createInputSource(Resource resource) throws IOException;
209
210
211
// Note: getSystemId(Resource) is a private method and not part of the public API
212
}
213
```
214
215
### Usage of SaxResourceUtils
216
217
```java
218
import org.springframework.oxm.support.SaxResourceUtils;
219
import org.springframework.core.io.Resource;
220
import org.springframework.core.io.ClassPathResource;
221
import org.xml.sax.InputSource;
222
import javax.xml.transform.sax.SAXSource;
223
224
// Create InputSource from Spring Resource
225
Resource xmlResource = new ClassPathResource("data.xml");
226
InputSource inputSource = SaxResourceUtils.createInputSource(xmlResource);
227
228
// Use with SAX-based processing
229
SAXSource saxSource = new SAXSource(inputSource);
230
231
// The system ID is automatically set for proper error reporting and entity resolution
232
// Note: System ID retrieval is handled internally by createInputSource()
233
```
234
235
## Integration Examples
236
237
### Using Support Classes Together
238
239
```java
240
import org.springframework.oxm.support.AbstractMarshaller;
241
import org.springframework.oxm.support.MarshallingSource;
242
import org.springframework.oxm.support.SaxResourceUtils;
243
import org.springframework.core.io.ClassPathResource;
244
import javax.xml.transform.Transformer;
245
import javax.xml.transform.TransformerFactory;
246
import javax.xml.transform.stream.StreamResult;
247
import java.io.StringWriter;
248
249
public class IntegratedExample {
250
251
public void demonstrateIntegration() throws Exception {
252
// Custom marshaller extending AbstractMarshaller
253
CustomMarshaller marshaller = new CustomMarshaller();
254
255
// Object to marshal
256
MyCustomClass object = new MyCustomClass();
257
258
// Create MarshallingSource for transformation
259
MarshallingSource source = new MarshallingSource(marshaller, object);
260
261
// Load XSLT stylesheet using SaxResourceUtils
262
Resource xsltResource = new ClassPathResource("transform.xsl");
263
InputSource xsltInput = SaxResourceUtils.createInputSource(xsltResource);
264
265
// Transform the marshalled XML
266
TransformerFactory factory = TransformerFactory.newInstance();
267
Transformer transformer = factory.newTransformer(new SAXSource(xsltInput));
268
269
StringWriter result = new StringWriter();
270
transformer.transform(source, new StreamResult(result));
271
272
String transformedXml = result.toString();
273
System.out.println("Transformed XML: " + transformedXml);
274
}
275
}
276
```
277
278
### Spring Configuration Integration
279
280
```java
281
import org.springframework.context.annotation.Bean;
282
import org.springframework.context.annotation.Configuration;
283
import org.springframework.oxm.support.MarshallingSource;
284
import org.springframework.oxm.Marshaller;
285
286
@Configuration
287
public class MarshallingConfig {
288
289
@Bean
290
public Marshaller customMarshaller() {
291
return new CustomMarshaller();
292
}
293
294
// Bean factory method for creating MarshallingSource
295
public MarshallingSource createMarshallingSource(Object content) {
296
return new MarshallingSource(customMarshaller(), content);
297
}
298
}
299
```
300
301
### Error Handling with Support Classes
302
303
```java
304
import org.springframework.oxm.support.MarshallingSource;
305
import org.springframework.oxm.XmlMappingException;
306
import javax.xml.transform.TransformerException;
307
308
public void handleErrors() {
309
try {
310
Marshaller marshaller = // ... get marshaller
311
Object content = // ... get content
312
313
MarshallingSource source = new MarshallingSource(marshaller, content);
314
315
// Use the source...
316
317
} catch (IllegalArgumentException e) {
318
System.err.println("Invalid marshaller or content: " + e.getMessage());
319
} catch (UnsupportedOperationException e) {
320
System.err.println("Attempted unsupported operation on MarshallingSource: " + e.getMessage());
321
}
322
323
// Handle transformation errors
324
try {
325
// ... transformation code
326
} catch (TransformerException e) {
327
System.err.println("Transformation failed: " + e.getMessage());
328
Throwable cause = e.getCause();
329
if (cause instanceof XmlMappingException) {
330
System.err.println("Underlying marshalling error: " + cause.getMessage());
331
}
332
}
333
}
334
```
335
336
## Advanced Usage Patterns
337
338
### Custom Resource Handling
339
340
```java
341
import org.springframework.oxm.support.SaxResourceUtils;
342
import org.springframework.core.io.Resource;
343
import org.xml.sax.EntityResolver;
344
import org.xml.sax.InputSource;
345
import java.io.IOException;
346
347
public class CustomEntityResolver implements EntityResolver {
348
349
@Override
350
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
351
// Custom entity resolution using Spring resources
352
if (systemId != null && systemId.startsWith("classpath:")) {
353
String resourcePath = systemId.substring("classpath:".length());
354
Resource resource = new ClassPathResource(resourcePath);
355
356
if (resource.exists()) {
357
return SaxResourceUtils.createInputSource(resource);
358
}
359
}
360
361
return null; // Use default resolution
362
}
363
}
364
```
365
366
### Performance Optimization
367
368
```java
369
import org.springframework.oxm.support.AbstractMarshaller;
370
import javax.xml.parsers.DocumentBuilderFactory;
371
import javax.xml.parsers.SAXParserFactory;
372
373
public class OptimizedMarshaller extends AbstractMarshaller {
374
375
// Override factory creation methods for performance tuning
376
@Override
377
protected DocumentBuilderFactory createDocumentBuilderFactory()
378
throws ParserConfigurationException {
379
DocumentBuilderFactory factory = super.createDocumentBuilderFactory();
380
381
// Performance optimizations
382
factory.setNamespaceAware(true);
383
factory.setValidating(false);
384
385
// Security settings
386
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
387
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
388
389
return factory;
390
}
391
392
@Override
393
protected SAXParserFactory createSaxParserFactory()
394
throws ParserConfigurationException, SAXException {
395
SAXParserFactory factory = super.createSaxParserFactory();
396
397
// Performance and security settings
398
factory.setNamespaceAware(true);
399
factory.setValidating(false);
400
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
401
402
return factory;
403
}
404
405
// ... implement abstract methods
406
}
407
```
408
409
## Required Imports
410
411
```java
412
import org.springframework.oxm.support.AbstractMarshaller;
413
import org.springframework.oxm.support.MarshallingSource;
414
import org.springframework.oxm.support.SaxResourceUtils;
415
import org.springframework.oxm.Marshaller;
416
import org.springframework.oxm.Unmarshaller;
417
import org.springframework.oxm.XmlMappingException;
418
import org.springframework.core.io.Resource;
419
import org.springframework.core.io.ClassPathResource;
420
421
import javax.xml.transform.Source;
422
import javax.xml.transform.Result;
423
import javax.xml.transform.Transformer;
424
import javax.xml.transform.TransformerFactory;
425
import javax.xml.transform.sax.SAXSource;
426
import javax.xml.transform.stream.StreamResult;
427
import javax.xml.parsers.DocumentBuilder;
428
import javax.xml.parsers.DocumentBuilderFactory;
429
import javax.xml.parsers.SAXParserFactory;
430
import javax.xml.parsers.ParserConfigurationException;
431
432
import org.w3c.dom.Node;
433
import org.xml.sax.ContentHandler;
434
import org.xml.sax.InputSource;
435
import org.xml.sax.XMLReader;
436
import org.xml.sax.ext.LexicalHandler;
437
import org.xml.sax.EntityResolver;
438
import org.xml.sax.SAXException;
439
440
import java.io.*;
441
```
442
443
## Best Practices
444
445
1. **Extend AbstractMarshaller**: Use AbstractMarshaller as base for custom implementations to get common functionality
446
2. **Resource Management**: Use SaxResourceUtils for consistent resource handling with proper system ID setup
447
3. **Transformation Integration**: Use MarshallingSource for seamless integration with XSLT transformations
448
4. **Security Configuration**: Override factory creation methods in AbstractMarshaller to configure security settings
449
5. **Performance Tuning**: Configure parser factories appropriately for your use case
450
6. **Error Handling**: Properly handle and wrap exceptions from underlying XML processing
451
7. **Memory Management**: Be aware of memory usage when processing large XML documents