Moxy xmlbinding with virtual props having individual xml-path

112 views Asked by At

Is it possible to have a Moxy xml-bindings oxm file for an object such as shown below. The object has a Map that is Keyed with name of the parameter, and Value would be a configured value. Each parameter has its own xml-path. The question is where can I specify the xml-path for the virtual props?. I could use the key as xpath itself. But, still not sure how the binding will turn into...

public class ServiceData{
  String Id;
  String desc;

  @XmlTransient
  private Map<String, Object> parameters= new HashMap<>();

  public Object getCustomProps(String name){
      return parameters.get(name);
  }

  public void putCustomProps(String name, Object value){
    parameters.put(name, value);
  }
}

The binding file may look like below, but, I am stuck on how I would assign xml-path to each entry in the map.

<?xml version="1.0" encoding="US-ASCII"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" package-name="net.blah.blah.domain">
<java-types>
    <java-type name="ServiceData">
        <xml-virtual-access-methods get-method="getCustomProps" set-method="putCustomProps" />
        <xml-root-element name="serviceData"/>
        <java-attributes>
            <xml-element java-attribute="id"
                         type="java.lang.String"
                         xml-path="parameters/group[@name='group1']/parameter[@name='param1']/text()"/>

        </java-attributes>
    </java-type>
</java-types>

1

There are 1 answers

0
user3434028 On BEST ANSWER

I was able to accomplish this with the following binding. I chose the json binding as that is what I actually need, but, it is similar to XML binding as well.

{
  "package-name": "net.company.demo",
  "xml-schema": {
    "element-form-default": "QUALIFIED",
    "namespace": "http://www.example.com/customer"
  },
  "java-types": {
    "java-type": {
      "name": "Pojo",
      "xml-virtual-access-methods": {
        "get-method": "get",
        "set-method": "set"
      },
      "xml-root-element": {
        "name": "rootElement"
      },
      "java-attributes": {
        "xml-element": {
          "java-attribute": "message",
          "type": "java.lang.String",
          "xml-path": "/params/parameter[@name='message']/text()"
        },
        "xml-element": {
          "java-attribute": "shouldValidate",
          "type": "java.lang.String",
          "xml-path": "/params/parameter[@name='validate']/text()"
        },
        "xml-element": {
          "java-attribute": "buffer",
          "type": "java.lang.String",
          "xml-path": "/params/parameter[@name='buffer']/text()"
        }
      }
    }
  }
}

Pojo is

public class Pojo{

private String id;

private Map<String, Object> data = new HashMap<String, Object>();

public Object get(String name){
    return data.get(name);
}

public void set(String name, Object value){
    data.put(name, value);
}

}

Application code looks like

        final Map<String, Object> jaxbContextProps = new HashMap<String, Object>();
    jaxbContextProps.put(JAXBContextProperties.OXM_METADATA_SOURCE, "binding.json");
    jaxbContextProps.put(JAXBContextProperties.MEDIA_TYPE, "application/xml");

    final Map<String, Object> marshallerProps = new HashMap<String, Object>();
    marshallerProps.put(Marshaller.JAXB_FORMATTED_OUTPUT, true);

    final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setLazyInit(true);
    marshaller.setClassesToBeBound(Pojo.class);
    marshaller.setJaxbContextProperties(jaxbContextProps);
    marshaller.setMarshallerProperties(marshallerProps);

    Pojo pojo = new Pojo();
    pojo.set("message", "This is some message");
    pojo.set("shouldValidate", "Yes");
    pojo.set("buffer", "1000");

    StringWriter writer = new StringWriter();
    StreamResult streamResult = new StreamResult(writer);
    marshaller.marshal(pojo,  streamResult);
    //System.out.println(writer.toString());