JAXB "nor any of its super class is known to this context" avoid @XmlSeeAlso

16,768

So here is what the essence of the custom resolver looks like:

@Provider
@Produces ({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public class JaxbContextResolver implements ContextResolver<JAXBContext> {

  @Override
  public JAXBContext getContext(Class<?> type) {
    // load appropriate context data
    Class[] bindTypes = ...

    // create 
    try {
      return JAXBContext.newInstance(bindTypes);
    } catch (JAXBException e) {
      // todo:  this can be handled better but works for the example
      throw new RuntimeException(e);
    }
  }
}

Now, the processing for "load appropriate context data" is pretty simple. By basically mimicking @XmlSeeAlso using runtime data:

  1. Create a custom something (annotation, processing method, whatever) that marks a particular field/method as "contextual"
  2. Load the field/method data pulling the data types out
  3. Make sure you do not load duplicates and check for infinite recursion possibilities

Now, I used some caching to help make things more efficient for myself. I also created a slightly more complex setup for my root object where it actually kept track of the class data on its own and made it pretty speedy. I also created an alternative that marked classes as "contextual" that I used package inspection to load via annotations and just automatically add to the context but I have not checked efficiency on that yet. I have some ideas for a 3rd implementation, but I want to get more benchmarking completed.

Share:
16,768
el n00b
Author by

el n00b

Falling in love with Go and coming from a Java and C/C++ background. I generally love to code and create but absolutely abhor technology in the home (ironic, right?). Family, motorcycles and caffeine are the only other thing really important to me. Up for some D20 if you're down. Just trying to make a living, you know?

Updated on June 04, 2022

Comments

  • el n00b
    el n00b almost 2 years

    Explanation & Workaround

    Currently I am using JAX-RS and letting JAXB bindings automatically handle converting the data to XML and JSON for me in a JEE6 project. Everything is working absolutely fantastically until I try to create a generic response object to wrap all of my information in.

    When I attempt to use my generic response class com.eln00b.Wrapper (which contains a private Object result attribute within it) I get:

    javax.xml.bind.MarshalException - with linked exception: [com.sun.istack.SAXException2: class com.eln00b.CustomObject nor any of its super class is known to this context. javax.xml.bind.JAXBException: class com.eln00b.CustomObject nor any of its super class is known to this context.]

    So I add to com.eln00b.Wrapper:

    @XmlSeeAlso ({com.eln00b.CustomObject})
    public class Wrapper {
    }
    

    Everything works fine.

    The Problem

    I want this to be extremely generic. I do not want t constantly add classes to the @XmlSeeAlso annotation on the com.eln00b.Wrapper class. How do I have the system automatically locate all of my classes for the JAXB context?

    Even if it's a hack where I use something like Reflections to load the data, that's fine. I'm just not sure how to get the context to load all of that data without the @XmlSeeAlso annotation. With the large amount of annotations I will be creating it will just simply not work.

    How It Worked Manually

    It worked manually just by adding the data like so doing manual conversions. However, I do not want to use manual XML/JSON creation unless I absolutely need to (I don't want to deal with content negotiation or anything like that).

    Sample:

    JAXBContext.newInstance(new Class[] {Wrapper.class, CustomObject.class});