2010-08-13 2 views
1

je le code suivant:IllegalAnnotationsException SetMultimap est une interface et JAXB ne peut pas gérer les interfaces

private SetMultimap<String, Dynamic> dynamicFields = TreeMultimap.create(Ordering.natural(), new Comparator<Dynamic>() { 
    @Override 
    public int compare(Dynamic o1, Dynamic o2) { 
    return o1.getTitle().compareTo(o2.getTitle()); 
    } 
}); 

qui me donne l'exception suivante.

IllegalAnnotationsException SetMultimap is an interface, and JAXB can't handle interfaces 

Ma question est, comment se fait cela ne fonctionne pas, mais cela ne:

List<Dynamic> test = new ArrayList<Dynamic>(); 

Et comment puis-je fixer le SetMultimap pour que JAXB est heureux?

+0

D'où vient JAXB dans ce domaine? – skaffman

+0

Est-ce pertinent pour la question? –

+0

Oui, c'est pertinent. Il n'y a pas de contexte sur la façon dont JAXB trouve cette interface. – skaffman

Répondre

1

La différence entre la liste/ArrayList et SetMultimap est que l'on est une collection Java, et l'autre est une structure de données en dehors de la hiérarchie de collection Java normale. Cela signifie que JAXB le considère comme une classe normale.

La spécification JAXB ne prend pas en charge les interfaces. Vous utilisez probablement l'implémentation Metro JAXB qui ne supporte pas les interfaces. Certaines implémentations JAXB telles que MOXy peut prendre en charge les interfaces, mais certaines implémentations JAX-WS dépendent d'un impl JAXB particulier, et son remplacement par des implémentations JAXB est pas toujours possible:

Votre le mieux est d'utiliser une annotation au niveau du paramètre pour convertir SetMultimap en une classe pouvant être gérée par JAXB:

1

Vous devez ajouter des annotations à dire JAXB les types d'exécution possibles de la référence, comme ceci:

@XmlElements({ 
@XmlElement(type = TreeMultimap.class, name = "treeMultimap"), 
@XmlElement(type = MultiHashMap.class, name = "hashMultimap") 
}) 
private SetMultimap<String, Dynamic> dynamicFields = TreeMultimap.create(Ordering.natural(), new Comparator<Dynamic>() { 
    @Override 
    public int compare(Dynamic o1, Dynamic o2) { 
    return o1.getTitle().compareTo(o2.getTitle()); 
    } 
}); 

Avec le code ci-dessus, vous pouvez également remplacer le champ par une instance de MultiHashMap si vous souhaitez . Vous devez ajouter un @XmlElement pour chaque type d'exécution possible. Si vous ne jamais utiliser le multimap de hachage, un @XmlElement avec TreeMultimap.class suffit:

@XmlElement(type = TreeMultimap.class, name = "treeMultimap") 
private SetMultimap<String, Dynamic> dynamicFields = TreeMultimap.create(Ordering.natural(), new Comparator<Dynamic>() { 
    @Override 
    public int compare(Dynamic o1, Dynamic o2) { 
    return o1.getTitle().compareTo(o2.getTitle()); 
    } 
}); 
+0

Cela n'a pas fonctionné. J'ai une exception: 'com.google.common.collect.TreeMultimap n'a pas de constructeur par défaut sans argument. TreeMultimap n'a en effet aucun constructeur par défaut sans argument. Peut-être que ça ne marche pas. –

+0

JAXB est un peu féroce dans le sens où il s'attend à ce que chaque objet ait un constructeur par défaut et des membres mutables. Pas très sympa IMO. Cependant, il existe plusieurs façons de contourner ce problème. Dans votre cas, j'irais faire un cours en usine. Utilisez @XmlType (factoryClass = MyFactory.class ...) pour déclarer une fabrique pour TreeMultimap, soit au niveau du package (si possible, n'avez pas essayé), soit sous-classe TreeMultimap. –

+0

Ce serait génial si nous avions une version de travail dans SO. :) Alors que je respecte profondément Kohsuke Kawaguchi, une star, j'ai toujours pensé qu'il s'ennuyait à mi-chemin de JAXB et qu'il était plutôt inachevé. –

Questions connexes