Enum не имеет конструктора по умолчанию без аргументов с Jaxb и cxf

У клиента возникла проблема с запуском 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» могут быть связаны с тем, что мой код на самом деле имеет два перечисления, которые написаны одинаково, но для краткости я исключил их из этого примера.


person Dave    schedule 15.09.2009    source источник
comment
это странное сочетание технологий... java2ws - это Apache CXF, верно? Это основано на Java5. Axis1 является древним и предшествует Java5. Что тут происходит?   -  person skaffman    schedule 16.09.2009
comment
Клиент потреблял и использовал наш WSDL для проекта 1. Приходит проект 2 (для них), и они взяли некоторые из наших объектов (которые они получили с помощью оси1 wsdl2java), обернули их и пытаются экспортировать через CXF для кого-то. еще. Таким образом, первая часть (использование нашего WSDL и его использование), кажется, работает, но попытка java2ws-объектов, которые пришли из потребления оси1, по-видимому, довольно рискованна.   -  person Dave    schedule 16.09.2009


Ответы (3)


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

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

MyEnumType(String v) {
    value = v;
}

Однако вы не можете удержать value члена final таким образом.

person Fabian Steeg    schedule 15.09.2009
comment
Если это делается в типе XML на стороне сервера, будет ли он распространяться вниз, когда он был использован wsconsumed, или его нужно отредактировать в сгенерированном файле .java (выходные данные wsdl2java)? - person Dave; 16.09.2009
comment
Я не совсем уверен в вашей настройке, но, насколько я понимаю, WSDL генерируется из перечисления с использованием JAXB в какой-то момент, поэтому, насколько я понимаю, это должно работать, когда это делается в вашем определении перечисления на стороне сервера. - person Fabian Steeg; 16.09.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 и прочитать это по мере необходимости.

person KLE    schedule 15.09.2009

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

public enum MyEnum{} 

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

Если вы декомпилируете этот класс, то увидите, что ваш enum

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