Is there a way to pass Class as a Parameter to the JAXB XMLAdapter or access Getter method from another class
Asked Answered
G

1

0

I am trying to create an XMLAdapter class for one of my objects. I need to access Getters from another class so that some of the objects can be populated from that class's Getters` but I am unable to do so.

Basically, I would like to access my Child class Getter methods within the XMLAdapter. I can create an Object of the Child class and access but it results in NULL. Initially, I am populating the Objects in the Child and Parent class. I would like to access the same value within XML Adapter so I am wondering if there is a way to pass reference of a class to my XMLAdapter.

I have the following Parent class which will have the values:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlTransient
@XmlSeeAlso({Child.class})
public class Parent{
    private String eventID;
}

Following is my Child class which will be used during marshalling to create XML:

@XmlRootElement(name = "child")
@XmlType(name = "child", propOrder = { "name","extension"})
public class Child extends Parent
{
    
    @XmlElement (name = "name") 
    private String name;
    
    @JsonIgnore
    @XmlJavaTypeAdapter (ExtensionAdapter.class)
    @XmlElement (name = "extension") 
    private Extension extension;

}

Following is my Extension class:

@NoArgsConstructor
@AllArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
public class Extension {
    private String eventID;
}

Following is my XMLAdapter class:

public class ExtensionAdapter extends XmlAdapter<Child, Extension> {

    @Override
    public Extension unmarshal(Child valueType) throws Exception {
        System.out.println("UN-MARSHALLING");
        return null;
    }

    @Override
    public Child marshal(Extension boundType) throws Exception {
        System.out.println("MARSHALLING");
        System.out.println(boundType);
        //If I create the New child type then I am unable to access the eventID from its getter as Child class is nulll
        Child be = new Child();
        be.setEventID(boundType.getEventID());
        return be;
    }
}

Basically, I would like to access the Child glass Getter methods within the XMLAdapter so that I can populate my Extension class EventID with that. I tried a lot of things but nothing worked so I am posting here.

Is there a way I can pass my Child class as a parameter to XMLAdapter so that I can access the Getter methods from it? Because if I create a new Object of Child class then all of its Getter methods are null. However at the start I am populating all the fields in Parent and Child class (name and eventID). I just want to populate the same value within the Extension class eventID using the XMLAdapter.

I hope I was able to explain the need. If you have any suggestions or sample code then it would be really useful.

Please Note: I have used very sample code here. I am aware that whatever I am trying to achieve can be achieved using the proper POJO and JAXB Annotations but my actual class is complex and I am not allowed to modify it. All I can add is the new Annotations. Hence, I am trying to achive this using the XMLAdapter.

Ganny answered 29/4, 2021 at 6:41 Comment(1)
Basically, i wanted to check the type of element within MAP and process accordingly. I was able to do it. If someone wants to do the a bit different then they can try to create a intermediate class which will set the value later it can be used within the Adapter class.Ganny
G
0

I wanted to achieve something like this so I was able to do that without needing to access the class. Posting the answer so it can be useful to somebody in the future.

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.lang3.NotImplementedException;

import io.openepcis.model.jaxb.MyAdapter.MapWrapper;

public class MyAdapter extends XmlAdapter<MapWrapper, Map<String, Object>> {

    private DocumentBuilder documentBuilder;

    public MyAdapter() throws Exception {
        documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    }

    @Override
    public Map<String, Object> unmarshal(MapWrapper valurType) throws Exception {
        throw new NotImplementedException();
    }

    @SuppressWarnings("unchecked")
    @Override
    public MapWrapper marshal(Map<String, Object> m) throws Exception {
        if (m == null) {
            return null;
        }
        MapWrapper wrapper = new MapWrapper();
        List elements = new ArrayList();
        for (Map.Entry<String, Object> property : m.entrySet()) {
            if (property.getValue() instanceof Map) {
                elements.add(new JAXBElement<MapWrapper>(new QName(getCleanLabel(property.getKey())), MapWrapper.class, marshal((Map) property
                                    .getValue())));

            } else {
                elements.add(new JAXBElement<String>(new QName(getCleanLabel(property.getKey())), String.class, property.getValue().toString()));
            }

        }
        wrapper.elements = elements;
        return wrapper;

    }

    // Return a XML-safe attribute. Might want to add camel case support
    private String getCleanLabel(String attributeLabel) {
        attributeLabel = attributeLabel.replaceAll("[()]", "").replaceAll("[^\\w\\s]", "_").replaceAll(" ", "_");
        return attributeLabel;
    }

    public static class MapWrapper {
        @XmlAnyElement
        List elements;
    }
Ganny answered 9/5, 2021 at 11:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.