Reputation: 13340
My code is the following:
System.out.println("This will save a table to XML data sheet.");
System.out.println("Please pick a table to save: " + listOfTables.toString());
command = scan.nextLine();
if(listOfTables.contains(command))
{
System.out.println("successfuly found table to save: " + command);
try //Java reflection
{
Class<?> myClass = Class.forName(command); // get the class named after their input
Method listMethod = myClass.getDeclaredMethod("list"); // get the list method from the class
Object returnType = listMethod.invoke(myClass, new Object[]{}); // run the list method
ArrayList<Object> objectList = (ArrayList)returnType; // get the arraylist of objects to send to XML
try
{
JAXBContext jaxbContext = JAXBContext.newInstance(myClass);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<?> jaxbElement = new JAXBElement<?>(new QName("jaxbdemo", "generated"), myClass, objectList.get(0));
marshaller.marshal(jaxbElement, System.out);
} catch (JAXBException e) {}
}
catch (ClassNotFoundException | SecurityException | NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { }
My problem is that neither:
JAXBElement<?> jaxbElement = new JAXBElement<?>(new QName("jaxbdemo", "generated"), myClass, objectList.get(0));
Nor:
JAXBElement<myClass> jaxbElement = new JAXBElement<myClass>(new QName("jaxbdemo", "generated"), myClass, objectList.get(0));
will compile. So what do I need to put between the <> for my JAXBElement type? Btw I'm getting:
The constructor JAXBElement<myClass>(QName, Class<myClass>, myClass) refers to the missing type myClass
and:
Cannot instantiate the type JAXBElement<?>
Upvotes: 2
Views: 2448
Reputation: 55233
You need to use a helper method to do this. Here's a rough example:
static <T> void helper(Class<T> myClass) {
Method listMethod = myClass.getDeclaredMethod("list");
Object returnType = listMethod.invoke(myClass, new Object[]{});
@SuppressWarnings("unchecked") // [carefully document why this is okay here]
ArrayList<T> objectList = (ArrayList<T>)returnType;
...
JAXBElement<T> jaxbElement = new JAXBElement<T>(
new QName("jaxbdemo", "generated"),
myClass,
objectList.get(0)
);
...
}
From that point, you're free to return a JAXBElement<?>
or else finish the remaining work within the helper.
As noted, you should document the unchecked cast, explaining why invoking list
for a given class represented by a Class<T>
is guaranteed to return an ArrayList<T>
, as your code assumes. This methodology seems brittle to me at best and I can already spot a mistake when you call invoke
:
listMethod.invoke(myClass, new Object[]{});
That method takes the instance on which to invoke the method as its first argument (or null
if it's a static method), but you're passing in myClass
- that can't possibly be right.
Upvotes: 1