Jaumzera Jaumzera - 6 months ago 35
Java Question

JAX-B customized XML output

I'm working with the ECCP protocol in order to integrate my CRM with the Elastix Call Center Module. The protocol uses a XML structure defined as follows:

<request id="1">
<request_type> <!-- this will be mapped to the Java request class -->
<attributes>
</attributes>
</request_type>
</request>


and

<response id="1">
<response_type> <!-- this will be mapped to the Java response class -->
<attributes>
</attributes>
</response_type>
</response>


I'm using JAX-B to map XML to Java classes but the problem is that I have to put the JAX-B generated XML inside a
<request></request>
XML every request and extract the content from
<response></response>
in every response because the ECCP protocol defines that every request and response needs to nested to their respective elements.

Here's the code I'm using to do that:

document = createDocument();
Element requestWrapper = document.createElement("request");
requestWrapper.setAttribute("id", String.valueOf(wrapped.getId()));
document.appendChild(requestWrapper);

JAXBContext jc = JAXBContext.newInstance(wrapped.getClass());
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(wrapped, requestWrapper);


Exemplifying:

One of ECCP's protocol operation is JAX-B-mapped into a class like this (getters and setters were omitted):

@XmlRootElement(name = "loginagent")
@XmlAccessorType(XmlAccessType.FIELD)
public class EccpLoginAgentRequest implements IEccpRequest {

@XmlElement(name = "agent_number")
private String agentNumber;

@XmlElement(name = "password")
private String password;
}


And JAX-B outputs the following:

<loginagent>
<agent_number>username</agent_number>
<password>password</password>
</loginagent>


But what the ECCP's protocol requires is:

<request id="1"> <!-- id is an auto-increment number to identify the request -->
<loginagent>
<username>username</username>
<password>password</password>
</loginagent>
</request>


The question is: is there any other way to achieve in any other better way?
Thank you.

Answer

I found a way to solve this in this post: XML element with attribute and content using JAXB

So I've mapped a EccpRequestWrapper object as the following:

@XmlRootElement(name = "request")
public class EccpRequestWrapper {
    @XmlAttribute
    private Long id;

    @XmlAnyElement
    private IEccpRequest request;
}

and then my request JAX-B outputs my request the way ECCP protocol requires. The @XmlAttribute and @XmlAnyElement annotation did the trick.

<request id="1">
   <login>
      <username>user</username>
      <password>****</password>
   </login>
</request>

A good JAXB guide can be found here https://jaxb.java.net/guide/Mapping_interfaces.html