9

I'm trying to marshal an object that has an Object as one of its fields.

@XmlRootElement
public class TaskInstance implements Serializable {
   ...
   private Object dataObject;
   ...
}

The dataObject can be one of many different unknown types, so specifying each somewhere is not only impractical but impossible. When I try to marshal the object, it says the class is not known to the context.

MockProcessData mpd = new MockProcessData();
TaskInstance ti = new TaskInstance();
ti.setDataObject(mpd);

String ti_m = JAXBMarshall.marshall(ti);

"MockProcessData nor any of its super class is known to this context." is what I get.

Is there any way around this error?

skaffman
  • 398,947
  • 96
  • 818
  • 769
jcovert
  • 550
  • 1
  • 7
  • 21
  • What are you attempting to serialize MockProcessData to? i.e. what is the desired representation? – mtpettyp Feb 16 '10 at 17:53
  • As a first time JAXB user, I have exactly the same problem trying to marshal an object tree created from scratch, i.e. not created from a compiled XSD. In fact I want to do it the other way round, and generate the schema from the classes once I have the code working. I tried wrapping my object in a JAXBElement as described, and I got exactly the same "Foobar is not known to this context" message as before, so I am no farther forward. –  May 20 '11 at 20:40
  • Hey Dasmotiu - I ended up including the @XMLSeeAlso annotation and providing all the classes that it could try to unmarshal the object to. For example: @XmlSeeAlso({ StringType.class, DecimalType.class, NumericType.class, BooleanType.class, StructType.class, ListType.class, DateType.class, SpatialType.class }) public abstract class FieldType { – jcovert May 21 '11 at 19:55

2 Answers2

7

JAXB cannot marshal any old object, since it doesn't know how. For example, it wouldn't know what element name to use.

If you need to handle this sort of wildcard, the only solution is to wrap the objects in a JAXBElement object, which contains enough information for JAXB to marshal to XML.

Try something like:

QName elementName = new QName(...); // supply element name here
JAXBElement jaxbElement = new JAXBElement(elementName, mpd.getClass(), mpd);
ti.setDataObject(jaxbElement);
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • Looks good, but I have two questions about this. Firstly, the element name - it's not exactly clear to me what it is used for, but I assume "dataObject" would be sufficient? And secondly, JAXBElement is a raw type, and the compiler warns me that it should be parametrized. I know a warning is a warning and not an error, but since I'm in unfamiliar territory, it seems like a good idea to find out more. I'm not sure what I'd parametrize it with either, since I'm dealing with 'Objects'. Thanks! – jcovert Feb 16 '10 at 15:45
  • @jcovert: The element name and namespace can be anything you like, so yes, `dataObject` would be fine. As for the generics, just use `JaxbElement`, it's just a compilation thing, JAXB doesn't care at runtime. – skaffman Feb 16 '10 at 17:19
  • 1
    It took me a few minutes to get it working, but indeed this is an excellent solution. One minor change (for anyone else who might encounter the same problem): `ti.setDataObject(jaxbElement)` should be `ti.setDataObject(jaxbElement.getValue())` Thanks again for the help! – jcovert Feb 17 '10 at 17:59
  • 1
    Hi I tried to do this. But Still I'm getting the same error. My question is posted here. http://stackoverflow.com/questions/14057932/javax-xml-bind-jaxbexception-class-nor-any-of-its-super-class-is-known-to-t . Can you please help me? – Shanaka Dec 27 '12 at 17:11
  • I liked the idea will try myself and post the result. What I wanna do is write a ResultSet object to XML – Acewin Feb 10 '15 at 00:30
0

Method:

public String marshallXML(Object object) {
        JAXBContext context;
        try {
            context = JAXBContext.newInstance(object.getClass());
            StringWriter writer = new StringWriter();
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(object, writer);
            String stringXML = writer.toString();
            return stringXML;
        } catch (JAXBException e) {

        }
}

Model:

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Customer {
    String name;
    int id;
    public String getName() {
        return name;
    }
    @XmlElement
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    @XmlAttribute
    public void setId(int id) {
        this.id = id;
    }
}
alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
Pinkesh Sharma
  • 2,428
  • 20
  • 16