42

This is my XML file:

<fields>
    <field mappedField="Num">
    </field>
    
    <field mappedField="Type">      
    </field>    
</fields>

I created 2 classes to parse it (Fields.java and Field.java):

@XmlRootElement(name = "fields")
public class Fields {

    @XmlElement(name = "field")
    List<Field> fields = new ArrayList<Field>();
        //getter, setter
}

and

public class Field {

    @XmlAttribute(name = "mappedField")
    String mappedField;
    //getter,setter
}

But I get this exception:

[INFO] com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
[INFO]  at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:66) ~[na:1.6.0_07]
[INFO]  at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:422) ~[na:1.6.0_07]
[INFO]  at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:270) ~[na:1.6.0_07]

I can't understand why this exception rises. Exception is here:

JAXBContext context = JAXBContext.newInstance(Fields.class);

I use JDK 1.6_0.0.7. Thanks.

WelcomeTo
  • 19,843
  • 53
  • 170
  • 286
  • 1
    Could you try and replace your attribute name? It could be that the `field` keyword is actually reserved. – npinti May 29 '12 at 08:52
  • 1
    @MyTitle your code will work fine if you just remove the setter methods in both your classes as your xml is taking care of setting values to the attributes. If you say you need the getter & setter methods in your classes, then add the line "@XmlAccessorType(XmlAccessType.FIELD)" above your class name and after the "@XmlRootElement" annotation and it works fine. – Suresh Dec 20 '17 at 07:34

12 Answers12

65

The exception is due to your JAXB (JSR-222) implementation believing that there are two things mapped with the same name (a field and a property). There are a couple of options for your use case:

OPTION #1 - Annotate the Field with @XmlAccessorType(XmlAccessType.FIELD)

If you want to annotation the field then you should specify @XmlAccessorType(XmlAccessType.FIELD)

Fields.java:

package forum10795793;

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement(name = "fields")
@XmlAccessorType(XmlAccessType.FIELD)
public class Fields {

    @XmlElement(name = "field")
    List<Field> fields = new ArrayList<Field>();

    public List<Field> getFields() {
        return fields;
    }

    public void setFields(List<Field> fields) {
        this.fields = fields;
    }

}

Field.java:

package forum10795793;

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Field {

    @XmlAttribute(name = "mappedField")
    String mappedField;

    public String getMappedField() {
        return mappedField;
    }

    public void setMappedField(String mappedField) {
        this.mappedField = mappedField;
    }

}

OPTION #2 - Annotate the Properties

The default accessor type is XmlAccessType.PUBLIC. This means that by default JAXB implementations will map public fields and accessors to XML. Using the default setting you should annotate the public accessors where you want to override the default mapping behaviour.

Fields.java:

package forum10795793;

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement(name = "fields")
public class Fields {

    List<Field> fields = new ArrayList<Field>();

    @XmlElement(name = "field")
    public List<Field> getFields() {
        return fields;
    }

    public void setFields(List<Field> fields) {
        this.fields = fields;
    }

}

Field.java:

package forum10795793;

import javax.xml.bind.annotation.*;

public class Field {

    String mappedField;

    @XmlAttribute(name = "mappedField")
    public String getMappedField() {
        return mappedField;
    }

    public void setMappedField(String mappedField) {
        this.mappedField = mappedField;
    }

}

For More Information

informatik01
  • 16,038
  • 10
  • 74
  • 104
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • 3
    This helped, but the actual problem for me was that although the field was annotated correctly, it was missing from the propOrder property that had been defined in the class level @XmlType annotation. – Pytry Jul 20 '15 at 19:05
  • If there are other classes in the same JAR that are not referenced by the code, will they also have to be annotated? I have a JAXB SOAP service giving the same error and have annotated the classes getting returned without success, but there are many other classes in the same JAR. – Sean Jan 22 '16 at 08:33
29

I can't understand why this JAXB IllegalAnnotationException is thrown

I also was getting the ### counts of IllegalAnnotationExceptions exception and it seemed to be due to an improper dependency hierarchy in my Spring wiring.

I figured it out by putting a breakpoint in the JAXB code when it does the throw. For me this was at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(). Then I dumped the list variable which gives something like:

[org.mortbay.jetty.Handler is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
    at org.mortbay.jetty.Handler
    at public org.mortbay.jetty.Handler[] org.mortbay.jetty.handler.HandlerCollection.getHandlers()
    at org.mortbay.jetty.handler.HandlerCollection
    at org.mortbay.jetty.handler.ContextHandlerCollection
    at com.mprew.ec2.commons.server.LocalContextHandlerCollection
    at private com.mprew.ec2.commons.server.LocalContextHandlerCollection com.mprew.ec2.commons.services.jaxws_asm.SetLocalContextHandlerCollection.arg0
    at com.mprew.ec2.commons.services.jaxws_asm.SetLocalContextHandlerCollection,
org.mortbay.jetty.Handler does not have a no-arg default constructor.]
....

The does not have a no-arg default constructor seemed to me to be misleading. Maybe I wasn't understanding what the exception was saying. But it did indicate that there was a problem with my LocalContextHandlerCollection. I removed a dependency loop and the error cleared.

Hopefully this will be helpful to others.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • 1
    Thank you! this is the only thing that helped me when the same code was throwing an `IllegalAnnotationsException` in different environments. Turns out, [versions of Java/JAXB mattered](http://stackoverflow.com/questions/19642792/what-might-cause-jaxbelement-does-not-have-a-no-arg-default-constructor). The "does not have a no-arg default constructor" was indeed the problem for me, though. Adding one fixed it! – insanity Aug 01 '16 at 07:27
  • 2
    Your answer resolved my issue. I wasn't expecting a `no-arg default constructor` caused the issue. Thanks! – Kamal Chandraprakash Oct 26 '17 at 05:53
  • 2
    The stacktrace was missing key info. Setting a breakpoint found the problem. – Ben Thurley Feb 16 '18 at 13:03
11

One of the following may cause the exception:

  1. Add an empty public constructor to your Fields class, JAXB uses reflection to load your classes, that's why the exception is thrown.
  2. Add separate getter and setter for your list.
GingerHead
  • 8,130
  • 15
  • 59
  • 93
11

This is because, by default, Jaxb when serializes a pojo, looks for the annotations over the public members(getters or setters) of the properties. But, you are providing annotations on fields. so, either change and set the annotations on setters or getters of properties, or sets the XmlAccessortype to field.

Option 1::

@XmlRootElement(name = "fields")
@XmlAccessorType(XmlAccessType.FIELD)
public class Fields {

        @XmlElement(name = "field")
        List<Field> fields = new ArrayList<Field>();
        //getter, setter
}

@XmlAccessorType(XmlAccessType.FIELD)
public class Field {

       @XmlAttribute(name = "mappedField")
       String mappedField;
       //getter,setter
}

Option 2::

@XmlRootElement(name = "fields")
public class Fields {

        List<Field> fields = new ArrayList<Field>();

        @XmlElement(name = "field")
        public List<Field> getFields() {

        }

        //setter
}

@XmlAccessorType(XmlAccessType.FIELD)
public class Field {

       String mappedField;

       @XmlAttribute(name = "mappedField")
       public String getMappedField() {

       }

        //setter
}

For more detail and depth, check the following JDK documentation http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlAccessorType.html

Love Hasija
  • 2,528
  • 2
  • 27
  • 26
2

I once received this message after thinking that putting @XmlTransient on a field I didn't need to serialize, in a class that was annotated with @XmlAccessorType(XmlAccessType.NONE).

In that case, removing XmlTransient resolved the issue. I am not a JAXB expert, but I suspect that because AccessType.NONE indicates that no auto-serialization should be done (i.e. fields must be specifically annotated to serialize them) that makes XmlTransient illegal since its sole purpose is to exclude a field from auto-serialization.

DVA
  • 331
  • 2
  • 13
2

for me this error was actually caused by a field falsely declared as public instead of private.

bluscreen
  • 41
  • 3
0

I had this same issue, I was passing a spring bean back as a ResponseBody object. When I handed back an object created by new, all was good.

BillFromHawaii
  • 334
  • 1
  • 7
0

I was having the same issue

My Issue

Caused by: java.security.PrivilegedActionException: com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions

Two classes have the same XML type name "{urn:cpq_tns_Kat_getgroupsearch}Kat_getgroupsearch". Use @XmlType.name and @XmlType.namespace to assign different names to them.
this problem is related to the following location:
at katrequest.cpq_tns_kat_getgroupsearch.KatGetgroupsearch
at public javax.xml.bind.JAXBElement katrequest.cpq_tns_kat_getgroupsearch.ObjectFactory.createKatGetgroupsearch(katrequest.cpq_tns_kat_getgroupsearch.KatGetgroupsearch)
at katrequest.cpq_tns_kat_getgroupsearch.ObjectFactory
this problem is related to the following location:
at cpq_tns_kat_getgroupsearch.KatGetgroupsearch

Two classes have the same XML type name "{urn:cpq_tns_Kat_getgroupsearch}Kat_getgroupsearchResponse0". Use @XmlType.name and @XmlType.namespace to assign different names to them.
this problem is related to the following location:
at katrequest.cpq_tns_kat_getgroupsearch.KatGetgroupsearchResponse0
at public javax.xml.bind.JAXBElement katrequest.cpq_tns_kat_getgroupsearch.ObjectFactory.createKatGetgroupsearchResponse0(katrequest.cpq_tns_kat_getgroupsearch.KatGetgroupsearchResponse0)
at katrequest.cpq_tns_kat_getgroupsearch.ObjectFactory
this problem is related to the following location:
at cpq_tns_kat_getgroupsearch.KatGetgroupsearchResponse0

Changed made to solve it are below

I change the respective name to namespace

@XmlAccessorType(XmlAccessType.FIELD) @XmlType(**name** =
    "Kat_getgroupsearch", propOrder = {

    @XmlAccessorType(XmlAccessType.FIELD) @XmlType(namespace =
    "Kat_getgroupsearch", propOrder = {


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(**name** = "Kat_getgroupsearchResponse0", propOrder = {

   @XmlAccessorType(XmlAccessType.FIELD)
   @XmlType(namespace = "Kat_getgroupsearchResponse0", propOrder = {

why?

As written in error log two classes have same name so we should use namespace because XML namespaces are used for providing uniquely named elements and attributes in an XML document.

0

All below options worked for me.

Option 1: Annotation for FIELD at class & field level with getter/setter methods

 @XmlRootElement(name = "fields")
 @XmlAccessorType(XmlAccessType.FIELD)
    public class Fields {

        @XmlElement(name = "field")
        List<Field> fields = new ArrayList<Field>();
            //getter, setter
    }

Option 2: No Annotation for FIELD at class level(@XmlAccessorType(XmlAccessType.FIELD) and with only getter method. Adding Setter method will throw the error as we are not including the Annotation in this case. Remember, setter is not required when you explicitly set the values in your XML file.

@XmlRootElement(name = "fields")
    public class Fields {

        @XmlElement(name = "field")
        List<Field> fields = new ArrayList<Field>();
            //getter
    }

Option 3: Annotation at getter method alone. Remember we can also use the setter method here as we are not doing any FIELD level annotation in this case.

@XmlRootElement(name = "fields")
    public class Fields {

        List<Field> fields = new ArrayList<Field>();

        @XmlElement(name = "field")
        //getter

        //setter
    }

Hope this helps you!

Suresh
  • 1,491
  • 2
  • 22
  • 27
0

In my case, I was able to find the problem by temporarily catching the exception, descending into causes as needed (based on how deep the IllegalAnnotationException was), and calling getErrors() on it.

    try {
        // in my case, this was what gave me an exception
        endpoint.publish("/MyWebServicePort");
    // I got a WebServiceException caused by another exception, which was caused by the IllegalAnnotationsException
    } catch (WebServiceException e) {
        // Incidentally, I need to call getCause().getCause() on it, and cast to IllegalAnnotationsException before calling getErrors()
        System.err.println(((com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException)e.getCause().getCause()).getErrors());
    }
snydergd
  • 503
  • 7
  • 11
0

This is happening be cause you have 2 classes with same name. For, example, I have 2 SOAP web-services named settings and settings2 both have the same class GetEmployee and this is ambiguous proving the error.

Arefe
  • 11,321
  • 18
  • 114
  • 168
0

JAXB (java.xml.bind)

This answer:

JDK 14

Spring Boot WebFlux 2.3.3.RELEASE

Lombok 1.18.12

Work for me >>>>> JDK 14

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.3.3</version>
</dependency>
<dependency>
    <groupId>org.glassfish.jaxb</groupId>
    <artifactId>jaxb-runtime</artifactId>
    <version>3.0.0-M4</version>
</dependency>

So Dependencies(jaxb-api, jaxb-impl, jaxb-runtime)

I try to test every version.

Body Request:

<?xml version="1.0" encoding="UTF-8"?>
<service generator="zend" version="1.0">
    <send>
        <message>OK</message>
        <status>success</status>
    </send>
</service> 

DTO:

import lombok.Getter;
import lombok.Setter;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;

public class SmsSend {
    
    @Getter
    @Setter
    @XmlRootElement(name = "service")
    public static class ReplyMethodSend {
        private List<ReplyValue> send = new ArrayList<>();
    }

    @Getter
    @Setter
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class ReplyValue {
        private String message;
        private String status;
    }
}

Response:

{
    "send": [
        {
        "message": "OK",
        "status": "success"
        }
    ]
}

Have fun with programming ^__^

bamossza
  • 3,676
  • 1
  • 29
  • 28