java 带有 Jaxb 和 cxf 的枚举“没有无参数默认构造函数”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1429509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 16:31:39  来源:igfitidea点击:

Enum "does not have a no-arg default constructor" with Jaxb and cxf

javajaxbcxf

提问by Dave

A client is having an issue running java2ws on some of their code, which uses & extends classes that are consumed from my SOAP web services. Confused yet? :)

客户端在其某些代码上运行 java2ws 时遇到问题,该代码使用 & 扩展了从我的 SOAP Web 服务使用的类。还迷茫吗?:)

I'm exposing a SOAP web service (JBoss5, Java 6). Someone is consuming that web service with Axis1 and creating a jar out of it with the data types and client stubs. They are then defining their own type, which extends one of my types. My type contains an enumeration.

我公开了一个 SOAP Web 服务(JBoss5、Java 6)。有人正在使用 Axis1 使用该 Web 服务,并使用数据类型和客户端存根创建一个 jar。然后他们定义了他们自己的类型,它扩展了我的一种类型。我的类型包含一个枚举。

class MyParent {
 private MyEnumType myEnum;

 // getters, settters for myEnum;
 }

 class TheirChild extends MyParent {
 ...
 }

When they are running java2ws on their code (which extends my class), they get

当他们在他们的代码(扩展我的类)上运行 java2ws 时,他们得到

Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
net.foo.bar.MyEnuMType does not have a no-arg default constructor.
    this problem is related to the following location:
            at net.foo.bar.MyEnumType
            at public net.foo.bar.MyEnumType net.foo.bar.MyParent.getMyEnum()

The enum I've defined is below. This is now how it comes out after being consumed, but it's how I have it defined on the app server:

我定义的枚举如下。这就是它被消费后的结果,但这是我在应用服务器上定义它的方式:


@XmlType(name = "MyEnumType")
@XmlEnum
public enum MyEnumType {

    Val1("Val1"),
    Val2("Val2")

    private final String value;

    MyEnumType(String v) {
        value = v;
    }

    public String value() {
        return value;
    }

    public static MyEnumType fromValue(String v) {
        if (v == null || v.length() == 0) {
            return null;
        }

        if (v.equals("Val1")) {
            return MyEnumType.Val1;
        } 
        if (v.equals("Val2")) {
            return MyEnumType.Val2;
        }  
        return null;
    }
}

I've seen things online and other posts, like (this one) regarding Jaxb's inability to handle Lists or things like that, but I'm baffled about my enum. I'm pretty sure you can't have a default constructor for an enum (well, at least a public no-arg constructor, Java yells at me when I try), so I'm not sure what makes this error possible. Any ideas?

我在网上和其他帖子中看到过一些东西,比如(这个)关于 Jaxb 无法处理列表或类似的东西,但我对我的枚举感到困惑。我很确定你不能有一个枚举的默认构造函数(好吧,至少是一个公共的无参数构造函数,Java 在我尝试时对我大喊大叫),所以我不确定是什么导致了这个错误。有任何想法吗?

Also, the "2 counts of IllegalAnnotationsExceptions" may be because my code actually has two enums that are written similarly, but I left them out of this example for brevity.

此外,“2 个 IllegalAnnotationsExceptions 计数”可能是因为我的代码实际上有两个类似编写的枚举,但为了简洁起见,我将它们排除在本示例之外。

回答by Fabian Steeg

The no-arg constructor for JAXB doesn't have to be public, it can be private:

JAXB 的无参数构造函数不必是public,它可以是private

private String value;
private MyEnumType() {} // for JAXB

MyEnumType(String v) {
    value = v;
}

You can't keep the valuemember finalthis way, though.

但是,您不能以这种方式保留value成员final

回答by KLE

I am certain you can have a default constructor for an enum. In fact, that what you have when you don't define a constructor explicitely (like yours with a String parameter).

我确信你可以有一个枚举的默认构造函数。事实上,当您没有明确定义构造函数时(就像您的带有 String 参数的构造函数),这就是您所拥有的。

You can also have several constructors, one no-args and others.

您还可以有多个构造函数,一个无参数和其他。



In the precise example you give, it would be simple to avoid the String parameter altogether. The provided name() method has exactly the value you are provided. The code would even be simpler:

在您给出的精确示例中,完全避免 String 参数很简单。提供的 name() 方法与您提供的值完全相同。代码甚至会更简单:

    @XmlType(name = "MyEnumType")
    @XmlEnum
    public enum MyEnumType {

    Val1, Val2;

    public String value() {
      return name();
    }

    public static MyEnumType fromValue(String v) {
      for(MyEnumType type : values()) {
        if (type.value().equals(v)) {
          return type;
        }
      }
      return null;
    }
   }


If you have really some complex parameters to set to each value, and can't have specific constructors because of a library, you could also store your varying values into an EnumMap, and read this as needed.

如果您确实有一些复杂的参数要设置为每个值,并且由于库而不能具有特定的构造函数,您还可以将不同的值存储到 EnumMap 中,并根据需要读取它。

回答by degr

when you do from-java-to-wsdl, apache check at first is it enum class or not, and only if this check fail, it check for constructor. You can see it in org.apache.axis.wsdl.fromJava.Types::isBeanCompatible. Any normal man, will think that if he write

当你做 from-java-to-wsdl 时,apache 首先检查它是否是 enum 类,只有当这个检查失败时,它才会检查构造函数。您可以在 org.apache.axis.wsdl.fromJava.Types::isBeanCompatible 中看到它。任何一个正常人,都会认为如果他写

public enum MyEnum{} 

it will be enough. But Apache developers does not think so (IDK why, may be for some compatibility reasons). They do this method - org.apache.axis.utils.JavaUtils::isEnumClassSub.

就足够了。但 Apache 开发者并不这么认为(IDK 为什么,可能是出于某些兼容性原因)。他们使用这种方法 - org.apache.axis.utils.JavaUtils::isEnumClassSub。

If you will decomile this class, you will see, that your enum

如果你对这个类进行 decomile,你会看到,你的枚举

  1. MUST implement public String getValue() {return name();}
  2. MUST implement public MyEnum fromString(String v){return valueOf(v);}
  3. CAN'T contain public void setValue(){}
  4. MUST implement String toString(), but each object implement it.
  1. 必须实现 public String getValue() {return name();}
  2. 必须实现 public MyEnum fromString(String v){return valueOf(v);}
  3. 不能包含 public void setValue(){}
  4. 必须实现 String toString(),但每个对象都实现它。