4

I noticed ObjectFactory class generated by jaxb compiler xjc. I read something about the purpose of it.

I am wondering what is a proper way to create jaxb objects as for my purposes I don't need this class at all. Should I always use the ObjectFactory even for trivial cases or can I construct the objects via normal constructor (what definitely works ok)?

Edit: added example:

I need to create instance of IpAddress

This is factory method:

  public IpAddress createIpAddress() {
        return new IpAddress();
    }

Is it better IpAddress ia = new IpAddress()

or

IpAddress ia = objectFactory.createIpdAddress()
ps-aux
  • 11,627
  • 25
  • 81
  • 128

2 Answers2

2

There is no difference between the instance created if you use the ObjectFactory to create the instance of the domain object or just use the zero arg constructor in JAXB 2 (JSR-222). In JAXB 1 (JSR-031) instead of POJOs there JAXB impls created interfaces with vendor specific impl classes, back then ObjectFactory was required to create instances.

There are times when the domain object needs to be wrapped in an instance of JAXBElement, ObjectFactory contains useful methods for doing this (see: http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html).

ObjectFactory is ultimately required by JAXB for the metadata it contains. JAXB will traverse transitive dependencies when processing a class. Having the create methods on the ObjectFactory gives a single class that JAXB can use to process metadata for the whole model.


UPDATE

Ok. So best-practice-wise what would be the proper approach? (see my example pls)

It really depends. Personally I prefer to use the constructors. I have an example below that demonstrates the two approaches.

XML Schema

Below is the XML Schema I have used to create the Java model.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" >
    <xs:element name="root" type="root"/>
    <xs:complexType name="root">
        <xs:sequence>
            <xs:element name="foo">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="bar" type="xs:string"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Demo Code

import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

public class Demo {

    public static void main(String[] args) {
        // Using Constructors
        Root.Foo foo1 = new Root.Foo();
        foo1.setBar("Hello");
        Root root1 = new Root();
        root1.setFoo(foo1);
        JAXBElement<Root> jaxbElement1 = new JAXBElement<Root>(new QName("root"), Root.class, root1);


        // Using ObjectFactory
        ObjectFactory objectFactory = new ObjectFactory();
        Root.Foo foo2 = objectFactory.createRootFoo();
        foo2.setBar("World");
        Root root2 = objectFactory.createRoot();
        root2.setFoo(foo2);
        JAXBElement<Root> jaxbElement2 = objectFactory.createRoot(root2);
    }

}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
0

ObjectFactory is used by JAXB to identify classes to be bound, eg

    JAXBContext ctx = JAXBContext.newInstance("test"); <-- test is package
    Marshaller m = ctx.createMarshaller();
    m.marshal(new X(), System.out);  <-- X is test package

throws

javax.xml.bind.JAXBException: "test" doesnt contain ObjectFactory.class or jaxb.index

but

JAXBContext ctx = JAXBContext.newInstance(X.class);
...

works OK because we loaded X to JAXBCOntext explicitly

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275