Master JAXB in Spring Boot 3: From XML Binding to Validation

This article explains how to use JAXB with Spring Boot 3 for XML binding, custom adapters, schema generation, validation, and seamless integration, providing step‑by‑step code examples and best‑practice tips for handling XML in Java backend applications.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Master JAXB in Spring Boot 3: From XML Binding to Validation

1. Introduction

Processing XML API responses is common in legacy systems, government platforms, and finance. While Spring Boot’s default Jackson XML can quickly convert XML and Java objects, it has limitations in complex scenarios. JAXB, a JDK native technology (requires a dependency after JDK 11), integrates deeply with XML Schema, automatically generates strong‑typed Java classes and supports data validation.

2. Practical Cases

2.1 Add Dependencies

<dependency>
  <groupId>jakarta.xml.bind</groupId>
  <artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
</dependency>

2.2 Common JAXB Annotations

@XmlRootElement – defines the XML root element.

@XmlType – controls the order of fields in the generated XML.

@XmlElement – maps a Java field or property to an XML element.

@XmlAttribute – maps a field to an XML attribute.

@XmlTransient – excludes a field from XML serialization.

@XmlAccessorType – sets the access strategy (FIELD, PROPERTY, NONE).

2.3 Object to XML (Marshalling)

Define a POJO with JAXB annotations:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "user")
@XmlType(propOrder = {"id", "name", "age", "birthday"})
public class User {
  @XmlAttribute(name = "id")
  private Long id;
  @XmlElement(name = "name")
  private String name;
  @XmlElement(name = "age")
  private Integer age;
  @XmlElement(name = "birthday")
  private Date birthday;
}

Marshalling example:

JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
User user = new User(1L, "Spring Boot3实战案例200讲", 33, new Date());
StringWriter writer = new StringWriter();
marshaller.marshal(user, writer);
String xmlString = writer.toString();
System.out.println(xmlString);

Output:

Marshalling output
Marshalling output

2.4 Custom Adapter for LocalDate

JAXB does not support Java 8 date types by default. Create an adapter:

public class LocalDateAdapter extends XmlAdapter<String, LocalDate> {
  private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
  @Override
  public LocalDate unmarshal(String v) throws Exception { return LocalDate.parse(v, FORMATTER); }
  @Override
  public String marshal(LocalDate v) throws Exception { return v.format(FORMATTER); }
}

Apply the adapter to the field:

@XmlJavaTypeAdapter(LocalDateAdapter.class)
@XmlElement(name = "birthday")
private LocalDate birthday;

Running the marshaller now produces a correctly formatted date.

Marshalling with LocalDate
Marshalling with LocalDate

2.5 XML to Object (Unmarshalling)

String xmlString = """
<user id=\"1\">
  <name>Spring Boot3实战案例200讲</name>
  <age>33</age>
  <birthday>2025-08-08</birthday>
</user>
""";
JAXBContext context = JAXBContext.newInstance(User.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
StringReader reader = new StringReader(xmlString);
User user = (User) unmarshaller.unmarshal(reader);
System.err.println(user);

Output:

User [id=1, name=Spring Boot3实战案例200讲, age=33, birthday=2025-08-09]

2.6 Generate Schema & Validate XML

Generate XSD from the annotated class:

JAXBContext context = JAXBContext.newInstance(User.class);
context.generateSchema(new SchemaOutputResolver() {
  @Override
  public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
    return new StreamResult(new File("user.xsd"));
  }
});

Validate XML against the generated schema:

SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = schemaFactory.newSchema(new File("user.xsd"));
unmarshaller.setSchema(schema);
// use xmlString with a wrong element name to see validation error
Validation error example
Validation error example

2.7 Integrate with Spring Boot

Spring Boot automatically registers Jaxb2RootElementHttpMessageConverter. Expose XML via a controller:

@GetMapping(value = "/query", produces = "application/xml")
public ResponseEntity<?> query() {
  return ResponseEntity.ok(new User(1L, "Spring Boot3实战案例200讲", 33, LocalDate.now()));
}

@PostMapping("/save")
public ResponseEntity<?> save(@RequestBody User user) {
  return ResponseEntity.ok(user);
}

For custom validation, extend the converter and set the schema in customizeUnmarshaller:

@Component
public class PackJaxb2RootElementHttpMessageConverter extends Jaxb2RootElementHttpMessageConverter {
  @Override
  protected void customizeUnmarshaller(Unmarshaller unmarshaller) {
    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    try {
      Schema schema = sf.newSchema(new File("user.xsd"));
      unmarshaller.setSchema(schema);
    } catch (SAXException e) {
      throw new RuntimeException("XSD parsing failed", e);
    }
  }
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSpring BootXMLdata bindingJAXB
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.