Search code examples
javapluginsjaxbrcp

Dynamically adding types to a jaxb context


I have multiple plug-ins in my RCP-based project. I want to be able to define @XMLElements in one plug-in that can then be marshaled / un-marshaled from the core plugin. To do so, I report the classes that are serializable as soon as the plug-in is loaded. However, dynamically adding classes seems to be not supported by the JAXBContext. I implemented a work-around by holding all classes in a list and creating a new JAXBContext every time some new classes are reported based on that list, but this solution is not really nice.

Is there a better way to do that?


Solution

  • You definitely can not add classes dynamically to a JAXBContext. This has to do with maintaining the thread safety of JAXBContext.

    I have recently posted an example on my blog explaining how to leverage the @XmlAnyElement annotation to generate a generic message that could have different payloads:

    Root Object

    The root element for the body property will be controlled by that objects @XmlRootElement.

    package message;   
    
    import javax.xml.bind.annotation.*;   
    
    @XmlRootElement@XmlAccessorType(XmlAccessType.FIELD) 
    public class Message {
        @XmlAttribute
        private String to;       
    
        @XmlAttribute    
        private String from;       
    
        @XmlAnyElement    
        private Object body;   
    }
    

    Creating the JAXBContext

    Instead of creating the JAXBContext on an array of classes, the JAXBContext could be created on a context path:

    JAXBContext.newInstance("message:customer:product"); 
    

    This context path includes 3 package names seperated by the colon ':' character. In each of these packages we need to include a file named jaxb.index with a list of files. Below is an example of the jaxb.index file in the customer package:

    Address
    Customer 
    

    When we want to add a model to represent orders to our framework we would extend our JAXBContext creation to like (this String could be passed in as a variable):

    JAXBContext.newInstance("message:customer:product:order");