2

I have a requirement to generate an XML file with below format using JAXB2, It has both Fixed and Variable xml content.

What is the Constraint?

The content of Variable XML Part should be one of the 5 different XML schema( planned to have JAXB2.0 implemented 5 different java classes to generate it) which is need to be embedded in the fixed XML content.

XML Format:

<user_info>
  <header>     //Fixed XML Part
     <msg_id>..</msg_id>
     <type>...</type>
  </header>
  <user_type>    //  Variable XML content
                      // (userType : admin, reviewer, auditer, enduser, reporter)
    ........  
  </user_type>
</user_info>

What I tried ?

I have created a JAXB annotated Java classes for the above XML metadata. For the variable XML part, I used common Parent class (BaseUserType) which was extended by all 5 different Classes <user_type>. And tried to Override the marshall(..) operation using @XmlJavaTypeAdapter. (as below)

JAXB Annotated Class:

@XmlRootElement(name="user_info")
public class UserInfo {

    private Header header;  //reference to JAXB annotated Class Header.class

    @XmlJavaTypeAdapter(value=CustomXMLAdapter.class)
    private BaseUserType userType; // Base class - acts as a common Type
                                    //  for all 5 different UserType JAXB annotated Classes

    // Getters setters here..
    // Also tried to declare JAXB annotations at Getter method
}

Custom XML Adapter Class:

public class CustomXMLAdapter extends XmlAdapter<Writer, BaseInfo> { 
       private Marshaller marshaller=null; 

        @Override 
        public BaseInfo unmarshal(Writer v) throws Exception { 
            // Some Implementations here...
        }

        @Override 
        public Writer marshal(BaseInfo v) throws Exception { 
                OutputStream outStream = new ByteArrayOutputStream(); 
                Writer strResult = new OutputStreamWriter(outStream); 
                if(v instanceof CustomerProfileRequest){ 
                    getMarshaller().marshal((CustomerProfileRequest)v, strResult ); 
                } 
                return strResult; 
        }

        private Marshaller getMarshaller() throws JAXBException{ 
                if(marshaller==null){ 
                        JAXBContext jaxbContext = JAXBContext.newInstance(Admin.class, Reviewer.class, Enduser.class, Auditor.class, Reporter.class);
                        marshaller = jaxbContext.createMarshaller(); 
                } 
                return marshaller; 
        } 
}

Where I'm Struggling now?.

I'm not facing any errors or warnings, the XML is being generated (as shown below). But the output is not the expected one. It doesn't embeds the Variable XML part with Fixed one correctly.

Output

 <user_info>
        <header> 
           <msg_id>100</msg_id>
           <type>Static</type>
        </header>
        <user_type/> // Empty Element, even though we binded the value properly.
    </user_info>

My Questions are :

  1. Why the JAXB marshallers could not embeds the "CustomXMLAdapter" marshalled content with Parent one (UserInfo.class).
  2. Do we have an any alternative option in JAXB to do this Simple?
  3. How to specify the BoundType, ValueType in XMLAdapter. Is there any specific Type to be given in order to Embed the content to Parent Class Marshalling?
omega
  • 592
  • 2
  • 5
  • 21

1 Answers1

1

An XmlAdapter works by allowing you to convert from your domain object, to another value object that JAXB can better handle for the purposes of Marshalling/Unmarshalling.

If all the model objects from the other schemas are really sub classes of BaseUserType, then all you need to do is make the JAXBContext aware of them. You can do this when you create the JAXBContext by having a colon separated String with all the package names.

JAXBContext jc = JAXBContext.newInstance("com.example.common:com.example.foo:com.example.bar");
bdoughan
  • 147,609
  • 23
  • 300
  • 400