2012-10-11 2 views
1

Comment est-il possible de créer des sous-classes de classes générées par xjc d'une exception personnalisée, de sorte que vous puissiez réellement les lancer et traiter par le JAXBContext? Souvent, les services Web renvoient des failles définies qui devraient vraiment faire exception, mais comme elles ne le sont pas, vous devez les emballer sans nécessité.Jaxb Xjc: make généré des sous-types de classes de Exception?

Répondre

1

Ouais, j'ai finalement trouvé quelque chose! Le Inheritance plugin est capable de rendre les classes générées héritées des classes ou implémenter des interfaces supplémentaires.

Vous devez inclure quelque chose comme

<bindings node="//xsd:complexType[@name='WhateverException']"> 
    <inheritance:extends>foo.bar.WhateverException</inheritance:extends> 
    </bindings> 

dans le fichier de liaison et passer outre getStackTrace() pour revenir nulle telle qu'elle ne soit pas rangea.

Malheureusement, vous pourriez rencontrer des problèmes avec certaines implémentations JAXB (voir Blaise Doughan's answer) - Je n'ai pas encore trouvé de solution pour cela. Vous pouvez donc utiliser une solution qui n'est pas tout à fait non-portative ou placer les objets JAXB dans des exceptions.

2

Même si vous pouviez créer un modèle JAXB (JSR-222) qui s'étendait de Exception, vous ne pourriez pas créer un JAXBContext à partir de celui-ci. Je recommande d'envelopper le Exception dans un modèle de domaine compatible avec JAXB.

Java Model (Foo)

Ci-dessous est une simple classe Java qui étend Exception.

package forum12840627; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Foo extends Exception { 

} 

Démo

Le code de démonstration ci-dessous pour tente crée un JAXBContext sur le modèle Java.

package forum12840627; 

import javax.xml.bind.JAXBContext; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Foo.class); 
    } 

} 

Sortie

est Ci-dessous l'exception de retour en cours d'exécution du code de démonstration. Le problème est que Exception n'est pas une classe JAXB valide et que les implémentations JAXB intègrent les super classes lors du traitement du modèle Java. (Remarque: Dans votre propre modèle de domaine, vous pouvez annoter super classe avec @XmlTransient pour les empêcher d'être traitées: http://blog.bdoughan.com/2011/06/ignoring-inheritance-with-xmltransient.html)

Exception in thread "main" com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions 
java.lang.StackTraceElement does not have a no-arg default constructor. 
    this problem is related to the following location: 
     at java.lang.StackTraceElement 
     at public java.lang.StackTraceElement[] java.lang.Throwable.getStackTrace() 
     at java.lang.Throwable 
     at java.lang.Exception 
     at forum12840627.Foo 

    at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:102) 
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:472) 
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:302) 
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1140) 
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:154) 
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:121) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202) 
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:363) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522) 
    at forum12840627.Demo.main(Demo.java:8) 

MISE À JOUR # 1

Si vous utilisez EclipseLink JAXB (MOXy) en tant que fournisseur JAXB, vous ne verrez pas cette exception car les classes des packages javax.* et java.* ne sont pas traitées en tant que classes de domaine. MOXy est le fournisseur JAXB par défaut dans l'environnement WebLogic 12c ou peut être configuré à l'aide d'un fichier jaxb.properties.

Pour plus d'informations

MISE À JOUR # 2

Les dernières versions de la référence JAXB implémentation semblent gérer ce cas d'utilisation maintenant ainsi que MOXy. Mes problèmes de portabilité d'origine ne sont peut-être pas vraiment un problème.

+0

Merci pour la réponse! Vous avez raison avec JDK6 ordinaire. Curieusement dans notre projet JAXBContext.newInstance ne vomit pas (probablement à cause de certaines bibliothèques XML que nous incluons.) Donc, dans notre configuration, vous pouvez juste surcharger getStackTrace() pour retourner null et ensuite vous pouvez réussir à marshaler et unmarshall l'exception. (Peut-être que l'on pourrait aussi écrire un XmlAdapter pour StacktraceElement pour éviter ce problème sur le JDK6 ordinaire.) La question est donc encore de savoir comment faire de la sous-classe xjc un type d'exception personnalisé. –

+0

@hstoerr - Vous utilisez peut-être MOXy comme fournisseur JAXB (voir ma mise à jour). –

+0

Pour mon fournisseur JAXB actuel, cela fonctionne quand même, mais j'hésite à utiliser une solution non portable. Voyez-vous un moyen de configurer un XmlAdapter à StacktraceElement (qui devrait juste être ignoré) ou quelque chose d'autre pour éviter ce problème sur le JDK6 ordinaire? Je n'ai pas réussi ça. :-( –

Questions connexes