Enum "не имеет конструктора по умолчанию без аргументов" с Jaxb и cxf - PullRequest
2 голосов
/ 16 сентября 2009

У клиента есть проблема с запуском java2ws для некоторого их кода, который использует и расширяет классы, которые используются моими веб-сервисами SOAP. Смущены еще? :)

Я раскрываю веб-сервис SOAP (JBoss5, Java 6). Кто-то использует этот веб-сервис с Axis1 и создает из него банку с типами данных и клиентскими заглушками. Затем они определяют свой собственный тип, который расширяет один из моих типов. Мой тип содержит перечисление.

class MyParent {
 private MyEnumType myEnum;

 // getters, settters for myEnum;
 }

 class TheirChild extends MyParent {
 ...
 }

Когда они запускают 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()

Определенное мной перечисление ниже. Вот как это получается после потребления, но так я определил его на сервере приложений:


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

Я видел вещи в Интернете и другие посты, например ( этот ) о неспособности Jaxb обрабатывать списки или тому подобное, но я озадачен своим перечислением. Я почти уверен, что у вас не может быть конструктора по умолчанию для перечисления (ну, по крайней мере, общедоступного конструктора без аргументов, Java кричит на меня, когда я пытаюсь), поэтому я не уверен, что делает эту ошибку возможной. Есть идеи?

Кроме того, «2 счета в IllegalAnnotationsExceptions» могут быть связаны с тем, что мой код на самом деле имеет два перечисления, которые написаны одинаково, но я для краткости оставил их в этом примере.

Ответы [ 3 ]

9 голосов
/ 16 сентября 2009

Конструктор без аргументов для JAXB не обязательно должен быть public, это может быть private:

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

MyEnumType(String v) {
    value = v;
}

Вы не можете сохранить value член final таким образом.

2 голосов
/ 16 сентября 2009

Я уверен, что вы можете иметь конструктор по умолчанию для перечисления. На самом деле, это то, что у вас есть, когда вы явно не определяете конструктор (как у вас с параметром String).

Вы также можете иметь несколько конструкторов, один без аргументов и другие.


В приведенном вами точном примере было бы просто вообще избежать параметра 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;
    }
   }

Если у вас действительно есть какие-то сложные параметры для каждого значения, и у вас нет конкретных конструкторов из-за библиотеки, вы также можете сохранить свои переменные значения в EnumMap и прочитать их при необходимости.

0 голосов
/ 09 июня 2015

когда вы делаете from-java-to-wsdl, сначала проверяется apache, является ли он перечислимым классом или нет, и только в случае неудачной проверки он проверяет конструктор. Вы можете увидеть это в org.apache.axis.wsdl.fromJava.Types :: isBeanCompatible. Любой нормальный мужчина, подумает, что если он напишет

public enum MyEnum{} 

этого будет достаточно. Но разработчики Apache так не считают (IDK почему, возможно, по некоторым причинам совместимости). Они делают этот метод - org.apache.axis.utils.JavaUtils :: isEnumClassSub.

Если вы разложите этот класс, вы увидите, что ваше перечисление

  1. НЕОБХОДИМО реализовать public String getValue () {return name ();}
  2. ДОЛЖЕН реализовывать общедоступный MyEnum fromString (String v) {return valueOf (v);}
  3. НЕ МОЖЕТ содержать публичный void setValue () {}
  4. ДОЛЖЕН реализовывать String toString (), но каждый объект реализует его.
...