简体   繁体   中英

how to pass any type of object into a method that has Class types within it

I have a method that turns a model class into an xml body for rest requests with rest assured:

public String getXmlBodyForRequest(PatchRequest model) {
    StringWriter sw = new StringWriter();

    JAXBContext jaxbContext = JAXBContext.newInstance(PatchRequest.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty(JAXB_FORMATTED_OUTPUT, TRUE);

    QName qName = new QName("com.companyname.testdata", "demo");
    JAXBElement<PatchRequest> root = new JAXBElement<>(qName, PatchRequest.class, model);

    jaxbMarshaller.marshal(root, sw);
    return sw.toString();
}

The above code takes the PatchRequest passed to it and converts it to xml for the PATCH body. I wanted to expand this to include any model class so I attempted using generics:

    public <T> String getXmlBodyForRequest(T model) {
    StringWriter sw = new StringWriter();

    JAXBContext jaxbContext = JAXBContext.newInstance(T.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty(JAXB_FORMATTED_OUTPUT, TRUE);

    QName qName = new QName("com.companyname.testdata", "demo");
    JAXBElement<T> root = new JAXBElement<>(qName, T.class, model);

    jaxbMarshaller.marshal(root, sw);
    return sw.toString();
}

but of course I can't put in T.class for the JAXBContext or the QName. I was wondering what way I would approach making the code accept any type of object. Thanks in advance A

You can get the class object for any instance by calling getClass() on it. This works for JAXBContext.newInstance :

JAXBContext jaxbContext = JAXBContext.newInstance(model.getClass());

However, unfortunately this doesn't satisfy the type checker in the case of new JAXBElement :

JAXBElement<T> root = new JAXBElement<>(qName, model.getClass(), model);

Results in:

cannot infer type arguments for JAXBElement<>
  reason: inference variable T has incompatible bounds
    equality constraints: capture#1 of ? extends java.lang.Object
    lower bounds: T

The workaround is to have your getXmlBodyForRequest also require the class parameter, in the same way the JAXBElement constructor does:

public <T> String getXmlBodyForRequest(Class<T> declaredType, T model) {
    StringWriter sw = new StringWriter();

    JAXBContext jaxbContext = JAXBContext.newInstance(declaredType);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty(JAXB_FORMATTED_OUTPUT, TRUE);

    QName qName = new QName("com.companyname.testdata", "demo");
    JAXBElement<T> root = new JAXBElement<>(qName, declaredType, model);

    jaxbMarshaller.marshal(root, sw);
    return sw.toString();
}

This moves the problem further up the stack, but at some point you'll hit code that is dealing with the concrete type, where you can then specify the class literal as in PatchRequest.class

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM