JAXB AnnotationsException: 3 counts of IllegalAnnotationExceptions

Lokesh Gupta

This exception occurs when you are using JAXB to marshal a Java object (collection type) to xml format. The stack trace looks like this in case of Lists.

Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "employees"
	this problem is related to the following location:
		at public java.util.List com.howtodoinjava.jaxb.examples.list.Employees.getEmployees()
		at com.howtodoinjava.jaxb.examples.list.Employees
	this problem is related to the following location:
		at private java.util.List com.howtodoinjava.jaxb.examples.list.Employees.employees
		at com.howtodoinjava.jaxb.examples.list.Employees

	at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(Unknown Source)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(Unknown Source)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(Unknown Source)
	at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(Unknown Source)
	..... more

OR in the case of Maps.

Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions
java.util.Map is an interface, and JAXB can't handle interfaces.
	this problem is related to the following location:
		at java.util.Map
		at private java.util.Map com.howtodoinjava.jaxb.examples.map.EmployeeMap.employeeMap
		at com.howtodoinjava.jaxb.examples.map.EmployeeMap
java.util.Map does not have a no-arg default constructor.
	this problem is related to the following location:
		at java.util.Map
		at private java.util.Map com.howtodoinjava.jaxb.examples.map.EmployeeMap.employeeMap
		at com.howtodoinjava.jaxb.examples.map.EmployeeMap
Class has two properties of the same name "employeeMap"
	this problem is related to the following location:
		at public java.util.Map com.howtodoinjava.jaxb.examples.map.EmployeeMap.getEmployeeMap()
		at com.howtodoinjava.jaxb.examples.map.EmployeeMap
	this problem is related to the following location:
		at private java.util.Map com.howtodoinjava.jaxb.examples.map.EmployeeMap.employeeMap
		at com.howtodoinjava.jaxb.examples.map.EmployeeMap
	......more
Random exceptions
Random exceptions

1. Reason

The above exception occurs mostly because of the absence of @XmlAccessType annotation or invalid use of @XmlAccessType with @XxmlElement annotation. The correct usage is such that one Java field should have only one effective JAXB annotation which represents its metadata.

By default, JAXB includes all public fields and getters for marshalling. So if you have a field, and it’s getter method that this will get included two times. This is an error and needs to be solved with the correct usage of annotations.

2. Solution: Use @XmlAccessType Annotation

2.1. @XmlAccessorType (XmlAccessType.FIELD)

If you are using XmlAccessType.FIELD; then only all public fields (non-static) will be automatically included for marshalling. No getter will be considered. So, if will remove the duplicate problem. e.g. In below code, both employees and size fields will be included.

Note that “@XmlElement(name=”employee”)” is optional; I have used it to rename the xml nodes in output xml. If you remove it; there will not be any marshalling error or exception.

@XmlRootElement(name = "employees")
@XmlAccessorType (XmlAccessType.FIELD)
public class Employees
{
	@XmlElement(name="employee")
	private List<Employee> employees = null;

	private Integer size;

	public List<Employee> getEmployees() {
		return employees;
	}
	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}
	public Integer getSize() {
		return size;
	}
	public void setSize(Integer size) {
		this.size = size;
	}
}

2.2. @XmlAccessorType (XmlAccessType.NONE)

If you are using “XmlAccessType.NONE” then it means you must annotate all fields that you want to marshal in output XML. Any field left will not be included in the JAXB context. So essentially, @XmlElement annotation is required on both “employees” and “size” fields. If any of both fields are not annotated with @XmlElement, that will not be marshalled.

@XmlRootElement(name = "employees")
@XmlAccessorType (XmlAccessType.NONE)
public class Employees
{
	@XmlElement(name="employee")
	private List<Employee> employees = null;

	@XmlElement(name="size")
	private Integer size;

	public List<Employee> getEmployees() {
		return employees;
	}
	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}
	public Integer getSize() {
		return size;
	}
	public void setSize(Integer size) {
		this.size = size;
	}
}

Happy Learning !!

Comments

Subscribe
Notify of
guest
15 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode