0
# JAXB Integration
1
2
Groovy XML provides JAXB (Java Architecture for XML Binding) integration through extension methods that simplify marshalling and unmarshalling operations.
3
4
## JaxbGroovyMethods
5
6
Extension methods that add JAXB functionality to standard JAXB classes.
7
8
```groovy { .api }
9
@Deprecated
10
class JaxbGroovyMethods {
11
/**
12
* Marshall an object to a xml String.
13
* @param self a Marshaller which can marshall the type of the given object
14
* @param jaxbElement object to marshall to a String
15
* @return String representing the object as xml
16
*/
17
static <T> String marshal(Marshaller self, T jaxbElement)
18
19
/**
20
* Unmarshall XML String to an object.
21
* @param self an Unmarshaller
22
* @param xml the XML String to unmarshall
23
* @return the unmarshalled object
24
*/
25
static <T> T unmarshal(Unmarshaller self, String xml)
26
27
/**
28
* Create a Marshaller from JAXBContext.
29
* @param self a JAXBContext
30
* @return a new Marshaller instance
31
*/
32
static Marshaller createMarshaller(JAXBContext self)
33
34
/**
35
* Create an Unmarshaller from JAXBContext.
36
* @param self a JAXBContext
37
* @return a new Unmarshaller instance
38
*/
39
static Unmarshaller createUnmarshaller(JAXBContext self)
40
}
41
```
42
43
**Note:** This class is deprecated. Use `org.apache.groovy.jaxb.extensions.JaxbExtensions` for new projects.
44
45
## Usage Examples
46
47
### Basic JAXB Marshalling
48
49
```groovy
50
import javax.xml.bind.JAXBContext
51
import javax.xml.bind.annotation.XmlRootElement
52
53
@XmlRootElement
54
class Person {
55
String name
56
int age
57
String email
58
}
59
60
// Create JAXB context
61
def context = JAXBContext.newInstance(Person)
62
def marshaller = context.createMarshaller()
63
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true)
64
65
// Create and marshal object
66
def person = new Person(name: 'John Doe', age: 30, email: 'john@example.com')
67
def xmlString = marshaller.marshal(person) // Extension method
68
println xmlString
69
```
70
71
### Basic JAXB Unmarshalling
72
73
```groovy
74
def xmlText = '''<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
75
<person>
76
<name>Jane Smith</name>
77
<age>25</age>
78
<email>jane@example.com</email>
79
</person>'''
80
81
def context = JAXBContext.newInstance(Person)
82
def unmarshaller = context.createUnmarshaller()
83
84
def person = unmarshaller.unmarshal(xmlText) // Extension method
85
println "Name: ${person.name}, Age: ${person.age}"
86
```
87
88
### Advanced JAXB Usage
89
90
```groovy
91
import javax.xml.bind.annotation.*
92
93
@XmlRootElement(name = "catalog")
94
@XmlAccessorType(XmlAccessType.FIELD)
95
class BookCatalog {
96
@XmlElement(name = "book")
97
List<Book> books = []
98
}
99
100
@XmlAccessorType(XmlAccessType.FIELD)
101
class Book {
102
@XmlAttribute
103
String id
104
@XmlElement
105
String title
106
@XmlElement
107
String author
108
@XmlElement
109
BigDecimal price
110
}
111
112
// Create complex object structure
113
def catalog = new BookCatalog()
114
catalog.books << new Book(id: '1', title: 'The Great Gatsby',
115
author: 'F. Scott Fitzgerald', price: 12.99)
116
catalog.books << new Book(id: '2', title: '1984',
117
author: 'George Orwell', price: 13.99)
118
119
// Marshal with formatting
120
def context = JAXBContext.newInstance(BookCatalog, Book)
121
def marshaller = context.createMarshaller()
122
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true)
123
124
def catalogXml = marshaller.marshal(catalog)
125
println catalogXml
126
127
// Unmarshal back
128
def unmarshaller = context.createUnmarshaller()
129
def restoredCatalog = unmarshaller.unmarshal(catalogXml)
130
restoredCatalog.books.each { book ->
131
println "Book: ${book.title} by ${book.author} - \$${book.price}"
132
}
133
```
134
135
### JAXB with Namespace Support
136
137
```groovy
138
import javax.xml.bind.annotation.XmlSchema
139
140
@XmlRootElement(name = "document", namespace = "http://example.com/ns")
141
@XmlAccessorType(XmlAccessType.FIELD)
142
class NamespacedDocument {
143
@XmlElement(namespace = "http://example.com/ns")
144
String title
145
146
@XmlElement(namespace = "http://example.com/ns")
147
String content
148
}
149
150
def doc = new NamespacedDocument(
151
title: 'Namespaced Document',
152
content: 'This document uses XML namespaces'
153
)
154
155
def context = JAXBContext.newInstance(NamespacedDocument)
156
def marshaller = context.createMarshaller()
157
marshaller.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true)
158
159
def nsXml = marshaller.marshal(doc)
160
println nsXml // Will include namespace declarations
161
```
162
163
### Integration with Groovy XML Builders
164
165
```groovy
166
// Combine JAXB objects with MarkupBuilder
167
def createHybridDocument = { jaxbObject ->
168
def context = JAXBContext.newInstance(jaxbObject.class)
169
def marshaller = context.createMarshaller()
170
171
// Get JAXB XML as string
172
def jaxbXml = marshaller.marshal(jaxbObject)
173
174
// Parse and integrate with MarkupBuilder
175
def parser = new XmlParser()
176
def jaxbNode = parser.parseText(jaxbXml)
177
178
def writer = new StringWriter()
179
def xml = new MarkupBuilder(writer)
180
181
xml.document {
182
header {
183
title('Combined Document')
184
generated(new Date().toString())
185
}
186
187
// Embed JAXB content
188
jaxbContent {
189
mkp.yieldUnescaped(jaxbXml)
190
}
191
192
footer {
193
note('Generated using JAXB and MarkupBuilder')
194
}
195
}
196
197
return writer.toString()
198
}
199
200
def person = new Person(name: 'Alice Johnson', age: 28, email: 'alice@example.com')
201
def hybridDoc = createHybridDocument(person)
202
println hybridDoc
203
```
204
205
### Error Handling with JAXB
206
207
```groovy
208
import javax.xml.bind.JAXBException
209
import javax.xml.bind.UnmarshalException
210
211
def safeUnmarshal = { xmlString, clazz ->
212
try {
213
def context = JAXBContext.newInstance(clazz)
214
def unmarshaller = context.createUnmarshaller()
215
216
// Enable validation if schema is available
217
// unmarshaller.setSchema(schema)
218
219
return unmarshaller.unmarshal(xmlString)
220
221
} catch (UnmarshalException e) {
222
println "Unmarshalling failed: ${e.message}"
223
return null
224
} catch (JAXBException e) {
225
println "JAXB error: ${e.message}"
226
return null
227
}
228
}
229
230
// Test with invalid XML
231
def invalidXml = '<person><name>John</name><age>not-a-number</age></person>'
232
def result = safeUnmarshal(invalidXml, Person)
233
234
if (result) {
235
println "Successfully unmarshalled: ${result.name}"
236
} else {
237
println "Failed to unmarshal XML"
238
}
239
```
240
241
## Migration to New Extensions
242
243
For new projects, use the updated JAXB extensions:
244
245
```groovy
246
// Instead of deprecated JaxbGroovyMethods
247
import org.apache.groovy.jaxb.extensions.JaxbExtensions
248
249
def context = JAXBContext.newInstance(Person)
250
def marshaller = context.createMarshaller()
251
def person = new Person(name: 'Bob', age: 35, email: 'bob@example.com')
252
253
// Use new extension methods
254
def xmlString = JaxbExtensions.marshal(marshaller, person)
255
println xmlString
256
```
257
258
## Performance Considerations
259
260
```groovy
261
// Reuse JAXBContext instances - they are thread-safe and expensive to create
262
class JaxbHelper {
263
private static final Map<Class, JAXBContext> contexts = [:]
264
265
static JAXBContext getContext(Class clazz) {
266
return contexts.computeIfAbsent(clazz) { c ->
267
JAXBContext.newInstance(c)
268
}
269
}
270
271
static String marshal(Object obj) {
272
def context = getContext(obj.class)
273
def marshaller = context.createMarshaller()
274
return marshaller.marshal(obj)
275
}
276
277
static <T> T unmarshal(String xml, Class<T> clazz) {
278
def context = getContext(clazz)
279
def unmarshaller = context.createUnmarshaller()
280
return unmarshaller.unmarshal(xml)
281
}
282
}
283
284
// Usage with cached contexts
285
def person1 = new Person(name: 'Person 1', age: 30, email: 'p1@example.com')
286
def person2 = new Person(name: 'Person 2', age: 25, email: 'p2@example.com')
287
288
def xml1 = JaxbHelper.marshal(person1) // Creates context
289
def xml2 = JaxbHelper.marshal(person2) // Reuses context
290
291
println xml1
292
println xml2
293
```