L'élément MOXy XPath unmarshalling est nul

Aug 18 2020

Im essayant de démarshall les éléments camunda: property dans une liste en utilisant XPath pour ignorer les éléments wrapper inutiles. Malheureusement, ma propertyList est toujours nulle. Cela se trouve dans la classe de tâches. Toute aide serait grandement appréciée.

Edit # 1: J'ai suivi les liens suivants qui étaient censés m'aider avec mon problème malheureusement sans succès. http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.htmlqui est le guide officiel. Apparemment, il y a des défis avec le fichier maven pom.xml. Je soupçonne que le problème réside dans le fichier pom. J'ai suivi ce guidehttps://www.javacodegeeks.com/2012/07/eclipselink-moxy-as-jaxb-provider.html mais n'a toujours pas réussi à le faire fonctionner.

fichier pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>BPMN-Marshaller</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <repositories><repository>
        <id>EclipseLink Repo</id>
        <url>http://download.eclipse.org/rt/eclipselink/maven.repo</url>
        <name>EclipseLink Repo</name>
    </repository></repositories>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>org.eclipse.persistence.moxy</artifactId>
            <version>3.0.0-M1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.5.3</version>
        </dependency>
        <!-- Runtime, com.sun.xml.bind module -->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.2</version>
        </dependency>
        <dependency>
            <groupId>jakarta.xml.bind</groupId>
            <artifactId>jakarta.xml.bind-api</artifactId>
            <version>2.3.2</version>
        </dependency>
    </dependencies>

</project>

fichier jaxb.properties dans le même package et dossier que mes classes java (voir l'image ci-jointe avec le nom "Structure du projet")

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

fichier package-info.java

@XmlSchema(namespace="http://www.omg.org/spec/BPMN/20100524/MODEL", elementFormDefault=XmlNsForm.QUALIFIED, xmlns = {@XmlNs(prefix="bpmn", namespaceURI="http://www.omg.org/spec/BPMN/20100524/MODEL")
        ,@XmlNs(prefix = "camunda", namespaceURI = "http://camunda.org/schema/1.0/bpmn")})

package bpmn;

import javax.xml.bind.annotation.*;

extrait de fichier xml

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_13d3a6z" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.1.1">
  <bpmn:process id="Process_1tovjba" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1">
      <bpmn:outgoing>Flow_06i118e</bpmn:outgoing>
    </bpmn:startEvent>
    <bpmn:task id="Activity_1d3friu" name="Task 1">
      <bpmn:extensionElements>
        <camunda:properties>
          <camunda:property name="start_date" value="01-04-2018" />
          <camunda:property name="duration" value="5" />
        </camunda:properties>
      </bpmn:extensionElements>
      <bpmn:incoming>Flow_06i118e</bpmn:incoming>
      <bpmn:outgoing>Flow_0linmbs</bpmn:outgoing>
    </bpmn:task>

Classe de définitions

@XmlRootElement
public class Definitions {

 private String id;
 private Process process;



    public Definitions(){};
    public Definitions(String id, Process process){
        super();
        this.id = id;
        this.process = process;
    }

    @XmlAttribute
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @XmlElement
    public Process getProcess() {
        return process;
    }

    public void setProcess(Process process) {
        this.process = process;
    }

    @Override
    public String toString(){
        return "Definitions [id23=" + id + ", process=23499999999999999" + process + "]";
    }

}

Classe de processus

public class Process {

    private String id;
    private List<Task> taskList;
    private List<SequenceFlow> sequenceFlowList;

    public Process(){};
    public Process(String id, List<Task> taskList, List<SequenceFlow> sequenceFlowList){
        super();
        this.id = id;
        this.taskList = taskList;
        this.sequenceFlowList = sequenceFlowList;
    }

    @XmlAttribute
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @XmlElement(name = "task")
    public List<Task> getTaskList() {
        return taskList;
    }

    public void setTaskList(List<Task> taskList) {
        this.taskList = taskList;
    }

    @XmlElement(name = "sequenceFlow")
    public List<SequenceFlow> getSequenceFlowList() {
        return sequenceFlowList;
    }

    public void setSequenceFlowList(List<SequenceFlow> sequenceFlowList) {
        this.sequenceFlowList = sequenceFlowList;
    }
}

Classe de tâches

public class Task {

    private String id;
    private String name;
    private List<Property> propertyList;

    public Task(){}
    public Task(String id, String name, List<Property> propertyList){
        super();
        this.id = id;
        this.name = name;
        this.propertyList = propertyList;
    }

    @XmlAttribute
    @JsonProperty("text")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlAttribute
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @XmlElement(name = "property")
    @XmlPath("bpmn:extensionElements/camunda:properties/camunda:property")
    public List<Property> getPropertyList() {
        return propertyList;
    }

    public void setPropertyList(List<Property> propertyList) {
        this.propertyList = propertyList;
    }
}

Classe de propriété

public class Property {

    private String name;
    private String value;

    public Property(){}
    public Property(String name, String value) {
        super();
        this.name = name;
        this.value = value;
    }

    @XmlAttribute
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @XmlAttribute
    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Classe principale

public class XMLToObject {
    public static void main(String[] args) {

        try {

            File file = new File("process.bpmn");
            JAXBContext jaxbContext = JAXBContext.newInstance(Definitions.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Definitions definitions = (Definitions) jaxbUnmarshaller.unmarshal(file);
            System.out.println(definitions.getProcess().getTaskList().get(0).getPropertyList());

        } catch (JAXBException e) {
            e.printStackTrace();
        }


    }
}

Structure du projet

Réponses

1 andrewjames Aug 19 2020 at 00:36

J'ai fait les modifications suivantes à votre approche, et je suis en mesure d'accéder aux durationet start_datepropriétés des données de votre fichier XML.

J'utilise OpenJDK 14, d'ailleurs. Mais cette approche fonctionne bien avec la version 8 également.

Le POM que j'utilise a les dépendances suivantes:

        <dependency>
            <groupId>com.sun.activation</groupId>
            <artifactId>javax.activation</artifactId>
            <version>1.2.0</version>
        </dependency>

        <!-- 
             Use 2.3.1 below to prevent "illegal 
             reflective access operation" warnings.
        -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>eclipselink</artifactId>
            <version>2.7.6</version>
        </dependency>

(J'ai sauté la dépendance Jackson juste pour ce test.)

J'ai également ajouté la section suivante à la fin de mon POM, pour gérer le fichier de propriétés:

    <!-- to copy the jaxb.properties file to its class package: -->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
        </resources>
    </build>

Cela garantit que le fichier de propriétés est déployé à l'emplacement correct avec ses fichiers de classe associés.

J'ai ajouté le code pour vérifier quel fournisseur JAXB est utilisé - juste à titre de confirmation positive:

    private void checkProvider() throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(Definitions.class);

        String jaxbContextImpl = jc.getClass().getName();
        if(MOXY_JAXB_CONTEXT.equals(jaxbContextImpl)) {
            System.out.println("EclipseLink MOXy");
        } else if(METRO_JAXB_CONTEXT.equals(jaxbContextImpl)) {
            System.out.println("Metro");
        } else {
            System.out.println("Other");
        }
    }

J'ai modifié le code pour parcourir les données de propriétés, pour imprimer explicitement les valeurs finales des propriétés:

List<Property> props = definitions.getProcess().getTaskList().get(0).getPropertyList();
props.forEach(prop -> {
    System.out.println(prop.getName() + " - " + prop.getValue());
});
//System.out.println(definitions.getProcess().getTaskList().get(0).getPropertyList());

Le résultat obtenu est:

EclipseLink MOXy
start_date - 01-04-2018
duration - 5