@XmlDiscriminatorNode/@XmlDescriminatorValue not working on WebLogic Server
Asked Answered
S

1

5

Following are the classes I am using for create sub classes using MOXy JAXB conversion on WebLogic 10.3.2 version. I am using the EclipseLink 2.4.1 MOXy for generating the XML. I am unable to generate the type attribute in the following code. Let me know if I am doing anything wrong here.

I am using EclipseLink MOXy 2.4.1 and WebLogic 10.3.2 and MOXy 2.4.1 is configured in the WebLogic

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlDiscriminatorNode("@type")
public abstract class BaseEntity {

    private String firstName;
    private String lastName;

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}

Subclass

package forum13831189;

import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;

@XmlDiscriminatorValue("xyz")
public class XyzEntity extends BaseEntity {

    public XyzEntity() {
        super();
    }

}

Another Sub Class

import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;

@XmlDiscriminatorValue("Abc")
public class AbcEntity extends BaseEntity {
}

RESTful Web Service Class:

@GET
@Path("/xyz")
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public Representation getAccount() throws CPAException {
    Representation rep = new Representation();
    BaseEntity entity = new XyzEntity();
    entity.setFirstName("first-name");
    entity.setLastName("last-name");
    rep.setEntity(entity);
    return rep;
}

@XmlRootElement
static class Representation {
    private BaseEntity entity;

    public BaseEntity getEntity() {
        return entity;
    }

    public void setEntity(BaseEntity entity) {
        this.entity = entity;
    }
}

The above is generating the following XML.

<representation>
     <firstName>first-name</firstName>
      <lastName>last-name</lastName>
 </representation>

The attribute type is not generated in the above.


Thanks a lot. Yes, I missed jaxb.properties in the above. Also, Yes when I use the PUT or POST, when XML is de-serialized, it is not able to create the subclasses if @XmlSeeAlso is not present.

Shear answered 12/12, 2012 at 1:10 Comment(0)
A
2

There are a couple items that may be causing you problems.

BaseEntity

By default a JAX-RS implementation creates a JAXBContext on the return type or parameter of the service method, in this case Represenatation. When processing the domain model the JAXB impl will also pull in referred types such as BaseEntity. It can't automatically pull in subclasses so we can use the @XmlSeeAlso annotation to reference those.

import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlDiscriminatorNode("@type")
@XmlSeeAlso({AbcEntity.class, XyzEntity.class})
public abstract class BaseEntity {

    private String firstName;
    private String lastName;

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}

jaxb.properties

Also since @XmlDescriminatorNode/@XmlDescriminatorValue are MOXy extensions you need to make sure you specify MOXy as your JAXB provider. This is done by adding a file named jaxb.properties in the same package as your domain model with the following entry.

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Demo

Below is a standalone example that mimics what your RESTful service does.

import javax.xml.bind.*;
import javax.xml.bind.annotation.XmlRootElement;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Representation.class);

        Representation rep = new Representation();
        BaseEntity entity = new XyzEntity();
        entity.setFirstName("first-name");
        entity.setLastName("last-name");
        rep.setEntity(entity);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(rep, System.out);
    }

    @XmlRootElement
    static class Representation {
        private BaseEntity entity;

        public BaseEntity getEntity() {
            return entity;
        }

        public void setEntity(BaseEntity entity) {
            this.entity = entity;
        }
    }

}

Output

Below is the output from running the demo code. See that the type attribute is now present.

<?xml version="1.0" encoding="UTF-8"?>
<representation>
   <entity type="xyz">
      <firstName>first-name</firstName>
      <lastName>last-name</lastName>
   </entity>
</representation>

For More Information

Arrowwood answered 12/12, 2012 at 10:50 Comment(3)
Thanks a lot. I missed jaxb.properties in the above.Shear
In the above example, I am using same method for producing XML and JSON as @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) Can you please let me know how to configure MOXY JSON to be used.Shear
@Shear - The following is the best way to configure MOXy as your JSON provider: blog.bdoughan.com/2012/05/…Arrowwood

© 2022 - 2024 — McMap. All rights reserved.