Rana
Rana

Reputation: 505

Can we decide the jaxb class at runtime during unmarshalling?

Is there any way to decide at runtime which java class I would like to Unmarshall the XML into?

I tried in this way Unmarshall code -

public Object unmarshallXml(String xmlReq, String className)
{
    String myClass = className+".class";
    Object instances = null;
       try {
        JAXBContext jc = JAXBContext.newInstance( myClass );
           Unmarshaller u = jc.createUnmarshaller();
           StringBuffer xmlStr = new StringBuffer( xmlReq );
           StringReader strReader = new StringReader( xmlStr.toString() );
           StreamSource strSource = new StreamSource(strReader);
           Object o = u.unmarshal( strSource );

    } catch (JAXBException e) {

        e.printStackTrace();
    }
    return instances;
}

but got this error -

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

Upvotes: 2

Views: 1769

Answers (3)

Rana
Rana

Reputation: 505

Another solution can be -

public Object unmarshallXml(String xmlReq, Object obj) {
    //ClientVariables instances = null;
    Object o = null;
    try {
        JAXBContext jc = JAXBContext.newInstance(obj.getClass());
        Unmarshaller u = jc.createUnmarshaller();
        StringBuffer xmlStr = new StringBuffer(xmlReq);
        StringReader strReader = new StringReader(xmlStr.toString());
        StreamSource strSource = new StreamSource(strReader);
        o = u.unmarshal(strSource);
        //instances = (ClientVariables) o;
    } catch (JAXBException e) {

        e.printStackTrace();
    }
    return o;
}

Call can be made like this -

        Utility util = new Utility();
        LookupInstances instances = new LookupInstances();
        instances = (LookupInstances) util.unmarshallXml(xmlReq, instances);

Upvotes: 0

bdoughan
bdoughan

Reputation: 148977

Can we decide the jaxb class at runtime during unmarshalling?

Yes, you just need to use one of the unmarshal methods that take a Class parameter.


Building the JAXBContext

Just because you want to unmarshal the class Foo doesn't necessarily mean that you can just do JAXBContext.createContext(Foo.class). This is because there may be other classes that you need that can not be transitively reached from that class (ObjectFactory) is a good example.

You can create the JAXBContext on the package name, but that requires one of the following:

  1. A class called ObjectFactory annotated with @XmlRegistry to be located in that package, with enough pointers to your model to pull in all the necessary classes. If you generate your model from an XML Schema this will be done for you.
  2. If you don't have the ObjectFactory class described above you can include a text file called jaxb.index with a carriage return separated list of short class names for your model.
  3. There aren't other packages in your model. If there are the JAXBContext needs to be bootstrapped off a colon separated context path, where each package included meets one of the two conditions above.

Upvotes: 3

dcsohl
dcsohl

Reputation: 7396

According to the API for Unmarshaller, you can call u.unmarshal(strSource, Foo.class) and this will return a JAXBElement<Foo>, on which you can call getValue() to get the actual Foo.

Also, read up on the usage of JAXBContext while you're at it. You probably want to pass it a package and not a single class - but you didn't include enough context (ha ha) for me to be sure.

Upvotes: 2

Related Questions