I try to parse a XML(String) to a Object using JAXB, but I can't find the way to call the method I had created because I don't know how to specify the class BasicRequest<G>
with the SomeRequest
as G
public class XMLParser {
public <G extends BaseRequest> BasicRequest<G> xmlToRequest(String xml,
Class<BasicRequest<G>> t) {
BasicRequest<G> request = null;
try {
JAXBContext context = JAXBContext.instance(t);
Unmarshaller m = context.createUnmarshaller();
StringReader reader = new StringReader(xml);
JAXBElement<BasicRequest<G>> unmarshal = m.unmarshal(new
StreamSource(reader), t);
request = unmarshal.getValue();
} catch (JAXBException ex) {
//write log
}
return request;
}
}
This are my classes:
public abstract class BaseRequest {
protected String version;
//getter & setter
}
,
public class SomeRequest extends BaseRequest {
protected Integer id;
//getter & setter
}
and
public class BasicRequest<G extends BaseRequest> {
protected String user;
protected G data;
//getter & setter
}
All classes actually have the JAXB annotation correctly.
If someone could please give me a hand on how should I call the method or a better way to define it I would appreciate.
Perhaps someone better-versed in JAXB has a clever JAXB-centric solution, but from the standpoint of generics, I do not believe there is a way to do what you are trying to do. The type parameter information for the enclosing BasicRequest
class is erased at runtime (see Class object of generic class (java)), so any Class
object representing a BasicRequest
will simply reflect the raw type. (Correspondingly, the Unmarshaller
will have no way to know what that parameter is intended to be.)
You could try one of the following solutions:
JAXBElement<BasicRequest<G>>
. The cast will produce an unchecked cast warning (again, because of type erasure), which can be suppressed with the @SuppressWarnings("unchecked")
annotation on the enclosing method, if you wish.For each class you have which could take the place of G, you could create a subclass which extends BasicRequest parameterized with that class, i.e.:
public class SomeBasicRequest extends BasicRequest<SomeRequest> {
...
}
SomeBasicRequest
would not be assignable from Class<BasicRequest<G>>
, though, so you'd have to change the method header as follows:
public <G extends BaseRequest> BasicRequest<G> xmlToRequest(String xml, Class<? extends BasicRequest<G>> t) {
...
}