我无法理解为什么抛出这个JAXB IllegalAnnotationException

时间:2012-05-29 08:42:28

标签: java exception jaxb

这是我的XML文件:

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

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

我创建了2个类来解析它(Fields.java和Field.java):

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

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

public class Field {

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

但我得到了这个例外。

[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]

我无法理解为什么这个例外会上升。例外情况在这里:

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

我使用的是JDK 1.6_0.0.7。感谢。

12 个答案:

答案 0 :(得分:47)

异常是由于您的JAXB(JSR-222)实现认为有两个事物使用相同的名称(字段和属性)映射。您的用例有几种选择:

选项#1 - 使用@XmlAccessorType(XmlAccessType.FIELD)

为字段添加注释

如果要注释该字段,则应指定@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;
    }

}

选项#2 - 注释属性

默认访问者类型为XmlAccessType.PUBLIC。这意味着默认情况下,JAXB实现会将公共字段和访问器映射到XML。使用默认设置,您应该注释要覆盖默认映射行为的公共访问者。

<强> 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;
    }

}

了解更多信息

答案 1 :(得分:20)

  

我无法理解为什么抛出这个JAXB IllegalAnnotationException

我也得到了### counts of IllegalAnnotationExceptions异常,这似乎是由于我的Spring布线中存在不正确的依赖层次结构。

我通过在JAXB代码中抛出一个断点来解决这个问题。对我而言,这是com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check()。然后我抛弃了list变量,它给出了类似的东西:

[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.]
....

does not have a no-arg default constructor在我看来是误导。也许我不明白异常是在说什么。但它确实表明我的LocalContextHandlerCollection存在问题。我删除了一个依赖循环并清除了错误。

希望这会对其他人有所帮助。

答案 2 :(得分:8)

这是因为,默认情况下,Jaxb在序列化pojo时,会查找属性的公共成员(getter或setter)上的注释。但是,您在字段上提供注释。因此,要么在属性的setter或getter上更改和设置注释,要么将XmlAccessortype设置为field。

选项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
}

选项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
}

有关更多详细信息和深度,请查看以下JDK文档http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlAccessorType.html

答案 3 :(得分:7)

以下之一可能会导致异常:

  1. 在您的Fields类中添加一个空的公共构造函数,JAXB使用 反射加载你的类,这就是抛出异常的原因。
  2. 为列表添加单独的getter和setter。

答案 4 :(得分:1)

我曾经在认为在@XmlTransient注释的类中将@XmlAccessorType(XmlAccessType.NONE)放在我不需要序列化的字段上之后收到此消息。

在这种情况下,删除XmlTransient可以解决问题。我不是JAXB专家,但我怀疑因为AccessType.NONE表示不应该进行自动序列化(即必须对字段进行专门注释才能序列化),这使得XmlTransient非法,因为它的唯一目的是排除来自自动序列化的字段。

答案 5 :(得分:0)

我有同样的问题,我将一个Spring bean作为ResponseBody对象传回。当我交回一个由new创建的对象时,一切都很好。

答案 6 :(得分:0)

我遇到了同样的问题

我的问题

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

为解决问题所做的更改

我将相应的名称更改为名称空间

@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 = {

为什么?

如错误日志中所写,两个类具有相同的名称,因此我们应该使用命名空间,因为 XML命名空间用于在XML文档中提供唯一命名的元素和属性。

答案 7 :(得分:0)

以下所有选项对我有用。

选项1:Class&amp;中FIELD的注释使用getter / setter方法的字段级别

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

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

选项2:类级别没有注释(@XmlAccessorType(XmlAccessType.FIELD)并且只使用getter方法。添加Setter方法会抛出错误,因为在这种情况下我们不包括Annotation。记住,setter不是在XML文件中显式设置值时需要。

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

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

选项3:仅使用getter方法进行注释。请记住,我们也可以在这里使用setter方法,因为在这种情况下我们没有进行任何FIELD级别的注释。

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

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

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

        //setter
    }

希望这能帮到你!

答案 8 :(得分:0)

对我来说,这个错误实际上是由错误地声明为public而不是private的字段引起的。

答案 9 :(得分:0)

就我而言,我能够通过临时捕获异常,根据需要归纳成因(基于IllegalAnnotationException的深度)并对其调用getErrors()来找到问题。

    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());
    }

答案 10 :(得分:0)

发生这种情况是因为您有两个同名的课程。例如,我有两个名为settings和settings2的SOAP Web服务,它们都具有相同的GetEmployee类,这是模棱两可的,证明了该错误。

答案 11 :(得分:0)

JAXB(java.xml.bind)

此答案:

JDK 14

Spring Boot WebFlux 2.3.3.RELEASE

龙目岛1.18.12

为我工作>>>>> 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

我尝试测试每个版本。

身体请求:

<?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;
    }
}

响应:

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

玩编程^ __ ^