Enum & # 8220; n'a pas de constructeur par défaut sans argument & # 8221; avec Jaxb et cxf

StackOverflow https://stackoverflow.com/questions/1429509

  •  07-07-2019
  •  | 
  •  

Question

Un client rencontre un problème d’exécution de java2ws sur certains de ses codes, qui utilise & amp; étend les classes utilisées par mes services Web SOAP. Encore confus? :)

J'expose un service Web SOAP (JBoss5, Java 6). Quelqu'un utilise ce service Web avec Axis1 et en crée un jar avec les types de données et les stubs client. Ils définissent ensuite leur propre type, ce qui étend l’un de mes types. Mon type contient une énumération.

class MyParent {
 private MyEnumType myEnum;

 // getters, settters for myEnum;
 }

 class TheirChild extends MyParent {
 ...
 }

Quand ils exécutent java2ws sur leur code (ce qui étend ma classe), ils obtiennent

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

L'énumération que j'ai définie est ci-dessous. Voici comment cela se présente après avoir été consommé, mais c’est ainsi que je le définis sur le serveur d’applications:


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

J'ai vu des choses en ligne et d'autres publications telles que ( celle-ci ) en ce qui concerne l'incapacité de Jaxb à gérer des listes ou des choses de ce genre, mais je suis perplexe à propos de mon enum. Je suis à peu près sûr que vous ne pouvez pas avoir de constructeur par défaut pour une énumération (enfin, au moins un constructeur public sans argument, Java me hurle dessus quand j'essaie), je ne suis donc pas sûr de ce qui rend cette erreur possible. Des idées?

De même, les "2 chefs d'accusation IllegalAnnotationsExceptions". C'est peut-être parce que mon code a en fait deux énumérations écrites de la même manière, mais je les ai laissées de cet exemple par souci de brièveté.

Était-ce utile?

La solution

Le constructeur no-arg pour JAXB ne doit pas nécessairement être public , il peut être privé :

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

MyEnumType(String v) {
    value = v;
}

Vous ne pouvez pas conserver la valeur membre final de cette façon, cependant.

Autres conseils

Je suis certain que vous pouvez avoir un constructeur par défaut pour une énumération. En fait, ce que vous avez quand vous ne définissez pas explicitement un constructeur (comme le vôtre avec un paramètre String).

Vous pouvez également avoir plusieurs constructeurs, un no-args et d'autres.

Dans l'exemple précis que vous donnez, il serait simple d'éviter le paramètre String. La méthode name () fournie a exactement la valeur qui vous est fournie. Le code serait même plus simple:

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

Si vous avez vraiment des paramètres complexes à définir pour chaque valeur, et que vous ne pouvez pas avoir de constructeurs spécifiques à cause d'une bibliothèque, vous pouvez également stocker vos valeurs variables dans une carte EnumMap et lire ceci au besoin.

quand vous faites de-java-to-wsdl, apache vérifie d'abord si c'est une classe énumérée ou non, et seulement si cette vérification échoue, elle recherche le constructeur. Vous pouvez le voir dans org.apache.axis.wsdl.fromJava.Types :: isBeanCompatible. Tout homme normal pensera que s’il écrit

public enum MyEnum{} 

ça suffira. Mais les développeurs Apache ne le pensent pas (IDK pourquoi, peut-être pour des raisons de compatibilité). Ils font cette méthode - org.apache.axis.utils.JavaUtils :: isEnumClassSub.

Si vous décomiliez cette classe, vous verrez que votre enum

  1. DOIT implémenter une chaîne publique getValue () {return name ();}
  2. DOIT implémenter MyEnum fromString (String v) {return valueOf (v);} public
  3. NE PEUT PAS contenir un vide public setValue () {}
  4. DOIT implémenter String toString (), mais chaque objet l'implémente.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top