Why is ObjectFactory not used when disassembling?

I have defined the following ObjectFactory:

@XmlRegistry
public class ObjectFactory {

    public Dogs createDogs() {
        return new Dogs();
    }

    @XmlElementDecl(name = "dog")
    public Dog createDog(DogType value) {
        return new Dog(value);
    }

    @XmlElementDecl(name = "fido", substitutionHeadName = "dog", substitutionHeadNamespace = "")
    public Dog createFido(DogType value) {
        return new Dog("fido", value);
    }

    @XmlElementDecl(name = "barks", substitutionHeadName = "dog", substitutionHeadNamespace = "")
    public Dog createBarks(DogType value) {
        return new Dog("barks", value);
    }
}

(the Dogsclass is trivial, Dogand DogTypesee below or here .)

I am parsing the following XML:

<listOfDogs>
    <dogs>
        <dog>
            <name>henry</name>
            <sound>bark</sound>
        </dog>
        <fido>
            <sound>woof</sound>
        </fido>
        <barks>
            <sound>miau</sound>
        </barks>
    </dogs>
</listOfDogs>

I sincerely expect that JAXB would call my methods createFido(...)and createBarks(...)in unmarshalling time. But this does not happen. The constructor Dogis called directly through reflection, the corresponding methods are create...not used.

My question is:

Why is ObjectFactorynot called during unmarshalling?

Shouldn't it be? Or ist just a mannequin for storing ads @XmlRegistry/ @XmlElementDecl?

I also checked this question:

What is the role of ObjectFactory during JAXB-Unmarshalling?

@XmlType.factoryClass factoryMethod. , DogType . , . - , -, .


, .

:

@XmlRootElement(name = "listOfDogs")
public class Dogs {

    private List<JAXBElement<DogType>> dogs = new LinkedList<JAXBElement<DogType>>();

    @XmlElementWrapper(name = "dogs")
    @XmlElementRef(name = "dog")
    public List<JAXBElement<DogType>> getDogs() {
        return this.dogs;
    }

    @Override
    public String toString() {
        return "Dogs [dogs=" + dogs + "]";
    }
}

Dog, DogType:

public class Dog extends JAXBElement<DogType> {

    public static final QName NAME = new QName("dog");

    private static final long serialVersionUID = 1L;

    public Dog(DogType value) {
        super(NAME, DogType.class, value);
    }

    public Dog(String dogName, DogType value) {
        super(NAME, DogType.class, value);
    }

    @Override
    public QName getName() {
        final DogType value = getValue();
        if (value != null && value.getName() != null) {
            return new QName(value.getName());
        } else {
            return super.getName();
        }
    }
}

DogType:

public class DogType {

    private String name;
    private String sound;

    public String getName() {
        return name;
    }

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

    public String getSound() {
        return sound;
    }

    public void setSound(String sound) {
        this.sound = sound;
    }
}

:

public class DogTest {

    @Test
    public void unmarshallsDogs() throws JAXBException {
        final JAXBContext context = JAXBContext
                .newInstance(ObjectFactory.class);
        final Dogs dogs = (Dogs) context.createUnmarshaller().unmarshal(
                getClass().getResource("dogs.xml"));
        Assert.assertEquals(3, dogs.getDogs().size());
        // Does not work
//      Assert.assertEquals("henry", dogs.getDogs().get(0).getValue()
//              .getName());
        Assert.assertEquals("bark", dogs.getDogs().get(0).getValue().getSound());
        // Does not work
//      Assert.assertEquals("fido", dogs.getDogs().get(1).getValue()
//              .getName());
        Assert.assertEquals("woof", dogs.getDogs().get(1).getValue().getSound());
        // Does not work
//      Assert.assertEquals("barks", dogs.getDogs().get(2).getValue()
//              .getName());
        Assert.assertEquals("miau", dogs.getDogs().get(2).getValue().getSound());
    }
}

GitHub .

+4
1

, factory @XmlType, JAXB:

@XmlRootElement(name = "listOfDogs")
@XmlType(factoryClass=ObjectFactory.class, factoryMethod="createDogs") // not generated
public class Dogs {

? , @XmlRegistry/@XmlElementDecl ?

-, , .

ObjectFactory - JAXB 1.0. JAXB 1.0 , , , . ObjectFactory .

JAXB 2.0 POJO, . JAXB 1.0 , ObjectFactory, . ObjectFactory, :

  • JAXB 1.0 .
  • @XmlElementDecl. @XmlRegistry - , , @XmlElementDecl, ObjectFactory.

XmlAdapter, , ObjectFactory.

XmlAdapter (DogAdapter)

XmlAdapter.

import javax.xml.bind.*;
import javax.xml.bind.annotation.adapters.*;

public class DogAdapter extends XmlAdapter<JAXBElement<DogType>, JAXBElement<DogType>> {

    @Override
    public JAXBElement<DogType> unmarshal(JAXBElement<DogType> v) throws Exception {
        return new Dog(v.getName().getLocalPart(), v.getValue());
    }

    @Override
    public JAXBElement<DogType> marshal(JAXBElement<DogType> v) throws Exception {
        return v;
    }

}

XmlAdapter @XmlJavaTypeAdapter.

import java.util.*;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement(name = "listOfDogs")
public class Dogs {

    private List<JAXBElement<DogType>> dogs = new LinkedList<JAXBElement<DogType>>();

    @XmlElementWrapper(name = "dogs")
    @XmlElementRef(name = "dog")
    @XmlJavaTypeAdapter(DogAdapter.class)
    public List<JAXBElement<DogType>> getDogs() {
        return this.dogs;
    }

    @Override
    public String toString() {
        return "Dogs [dogs=" + dogs + "]";
    }

}

ObjectFactory

ObjectFactory , @XmlElementDecl:

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    public Dogs createDogs() {
        return new Dogs();
    }

    @XmlElementDecl(name = "dog")
    public JAXBElement<DogType> createDog(DogType value) {
        return new Dog(value);
    }

    @XmlElementDecl(name = "fido", substitutionHeadName = "dog", substitutionHeadNamespace = "")
    public JAXBElement<DogType> createFido(DogType value) {
        return new JAXBElement<DogType>(new QName("fido"), DogType.class, value);
    }

    @XmlElementDecl(name = "barks", substitutionHeadName = "dog", substitutionHeadNamespace = "")
    public JAXBElement<DogType> createBarks(DogType value) {
        return new JAXBElement<DogType>(new QName("barks"), DogType.class, value);
    }

}

UPDATE

, , . spec, create * ObjectFactory ?

JAXB 2 , , , XML-. , , . , , no-arg factory.

8.7.1.2 JAXB 2.2 (JSR-222):

no-arg factory, {factoryClass(), factoryMethod()}, @XmlJavaTypeAdapter.

+5

All Articles