10
votes

JAXB SAXPARSEXCEXCEXCEXCEXCEXCEXCEXCEXEXE QU'UNARSHALLING DOCUMENT AVEC PATH PATH DE DTD

J'ai une classe qui shareals XML à partir d'une source tierce (je n'ai aucun contrôle sur le contenu). Voici l'extrait que lesmurs: xxx

connexions est une classe DTD-> xsd-> une classe générée par XJC. Le package com.optimumirlightpath.it.aspenoss.xsd contient toutes ces classes.

Le XML Je reçois contient un chemin relatif dans le doctype. Fondamentalement str.value ci-dessus contient: xxx

Ceci fonctionne avec succès en tant qu'application Java 1.5. Afin d'éviter l'erreur ci-dessus, je devais créer un répertoire ./dtd sur la racine du projet et inclure tous les fichiers DTD (pas sûr pourquoi je devais le faire, mais nous y arriverons). < P> J'ai depuis créé un service Web sur tomcat5.5 qui utilise la classe ci-dessus. Je reçois [org.xml.sax.saxparseException: uri relatif "./dtd/connections.dtd"; ne peut pas être résolu sans URI de document.] sur la ligne de lamairiste. J'ai essayé de créer ./dtd dans chaque dossier relavant (racine de projet, webcontent, Web-Inf, Dir du travail Tomcat, etc.) en vain.

Question n ° 1: Où puis-je localiser ./dtd afin que la classe puisse le trouver lorsqu'elle est exécutée comme Web Tomcat Webservice? Y a-t-il une configuration Tomcat ou service que je dois faire pour que le répertoire reconnu?

Question n ° 2: Pourquoi la classe a-t-elle même besoin du fichier DTD en premier lieu? N'a-t-elle pas toutes les informations dont il a besoin de lamarser dans les annotations de la classe DTD-> XSD->? J'ai lu de nombreux postes sur la validation de la validation, la définition d'entitésResource et d'autres solutions, mais cette classe n'est pas toujours déployée en tant que service Web et je ne veux pas avoir deux trains de code.


0 commentaires

3 Réponses :


2
votes

question n ° 2: pourquoi la classe est-elle même Besoin du fichier DTD en premier lieu?

Ce n'est pas la mise en œuvre JAXB qui recherche la DTD, c'est l'analyseur sous-jacent.

question n ° 1: où puis-je localiser ./dtd afin que la classe puisse le trouver quand elle est courante comme un service Web Tomcat?

Je ne suis pas sûr, mais ci-dessous, je vais démontrer une façon de faire ce travail en utilisant le MOXY JAXB Mise en œuvre (je suis le plomb technique) qui fonctionnera dans plusieurs environnements.

solution proposée

Créez une entitéResolver qui charge la DTD de la classe de classe. De cette façon, vous pouvez emballer la DTD avec votre application et vous saurez toujours où il est indépendamment de l'environnement de déploiement. xxx

puis à l'aide de la mise en œuvre MOXY JAXB que vous pouvez accomplir à la mise en œuvre sous-jacente et définir l'entitéresolver. xxx


3 commentaires

Blaise - TY pour prendre le temps de répondre. Initialement, Jaxbhelper s'est plaint que le motard n'était pas un eclipselink Unmlarshaller. J'ai donc remplacé javax.xml.bind.jaxbcontext avec org.eclipse.persistence.jaxb.jaxbcontext et javax.xml.bind.unmarshaller avec org.eclipse.persistence.jaxb.jaxbunmarshaller. Cependant, l'Eclipselink JaxbContext renvoie un type Javax JaxbContext. Jaxbunmarshaller nécessite un type eclipselink et je me trompe d'exceptions si j'essaie de reposer. Des idées?


Vous devez ajouter un fichier nommé jaxb.properties dans avec vos classes de modèle avec l'entrée suivante: javax.xml.bind.context.factory = org.eclipse.persistence.jaxb. JaxbContextFactory


Je peux essayer cela à un autre moment. J'ai été capable de faire fonctionner la réponse de Jorn, bien qu'elle nécessiterait plus de changements de code. Comme vous le dites, c'est le plus portable. Merci beaucoup !! Lorsque je reçois un 15 représentant, je peux modifier votre réponse aussi.



11
votes

Lorsqu'il est immobile à partir d'un INPURSTREAM ou d'un lecteur, l'analyseur ne connaît pas le système SystemID (URI / EMPLACEMENT) du document, il ne peut donc pas résoudre les chemins relatifs. Il semble que l'analyseur essaie de résoudre les références à l'aide du répertoire de travail actuel, qui fonctionne uniquement lors de l'exécution de la ligne IDE ou de commande. Afin de remplacer ce comportement et de vous résoudre, vous devez implémenter un entitéresolver , comme l'a mentionné Blaise Dumdan.

Après quelques expériences, j'ai trouvé une façon standard de faire cela. Vous devez vous installer à partir d'un saxsource , qui est à son tour construit à partir d'un xmlreader et un entréeSource . Dans cet exemple, la DTD est située à côté de la classe annotée et peut donc être trouvée dans la classe de classe.

main.java xxx

root.java xxx

root.dtd xxx


2 commentaires

Jorn - Ty pour votre réponse. Je suis d'abord essais la suggestion de Blaise car elle nécessite le moindre code change. Mais vous avez tous deux donné des réponses très utiles. Y a-t-il une façon de créer des crédits?


Mon approche fonctionnera, mais l'avantage de l'approche de Jorn est que vous restez la mise en œuvre de Jaxb agnostique qui est la solution la plus portable.



1
votes

Voici une autre variation des réponses déjà donnée à l'aide de l'interface entityResolver code>. Ma situation résolvait des entités XML externes relatives d'un fichier XML à un autre dans une hiérarchie de dossiers. Le paramètre du constructeur ci-dessous est le dossier XML "Working", pas le répertoire de travail du processus.

public class FileEntityResolver implements EntityResolver {
    private static final URI USER_DIR = SystemUtils.getUserDir().toURI();

    private URI root;

    public FileEntityResolver(File root) {
        this.root = root.toURI();
    }

    @Override @SuppressWarnings("resource")
    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        URI systemURI;
        try {
            systemURI = new URI(systemId);
        } catch (URISyntaxException e) {
            return null;
        }

        URI relative = USER_DIR.relativize(systemURI);
        URI resolved = root.resolve(relative);

        File f = new File(resolved);
        FileReader fr = new FileReader(f);
        // SAX will close the file reader for us
        return new InputSource(fr);
    }
}


0 commentaires