3

I have multiple root elements and thus, I need to write

JAXBElement<BookType> jaxbBookType = objectFactory.createBookType (bookType);
JAXBElement<OrderType> jaxbOrderType = objectFactory.createOrderType (orderType);

and so on. I don't want to write this piece of code again and again. I am trying to write a method which will return me JAXBElement based on its input.

What i am trying to write is

public <T> JAXBElement<T> getJaxbElement (Object obj){
    if (obj instanceof OrderType){
        return objectFactory.createOrderType((OrderType)obj);
    }
}

But obviously, I am doing it wrong. Since i don't know much about Generics and after reading it for a while, I am still confuse. Can someone help me little bit here.

Em Ae
  • 8,167
  • 27
  • 95
  • 162
  • Not directly answering the question, but you might be interested in using [simple binding](http://jaxb.java.net/2.1.2/docs/vendorCustomizations.html#simple) so that `xjc` generates `@XMLRootElement` annotations for base elements. As proposed [here](http://stackoverflow.com/a/9945237/851811). – Xavi López Sep 27 '12 at 16:18
  • I know about that. But i have schema in which i might have multiple root elements at the same time. see my existing discussion about it (http://stackoverflow.com/questions/11620825/xsd-for-having-2-root-elements-1-at-a-time) – Em Ae Sep 27 '12 at 16:19
  • Well, I guess it'll be hard to achieve a better solution given the invoked method's name is the thing to dynamize here based on the generics type at runtime. Maybe with reflection you could get the method's name. You'll have to pass along the `Class` of `T`, too, since generics are not retained at runtime. – Xavi López Sep 27 '12 at 16:28
  • I don't mind using `instanceof` object within the body. so i can avoid reflection here. However, I do want to return the custom `JAXBElement` as my return type. – Em Ae Sep 27 '12 at 16:38

4 Answers4

4

In case you can assume to use the instanceof operator with the parameter, just casting to JAXBElement<T> would be enough:

public <T> JAXBElement<T> getJaxbElement (Object obj){
    Object ret;
    if (obj instanceof OrderType){
        ret = objectFactory.createOrderType((OrderType)obj);
    }
    else if (obj instanceof BookType){
        ret = objectFactory.createBookType((BookType)obj);
    }
    return (JAXBElement<T>) ret;
}

In case you can't, being the method name what does have to be dynamic here, a possibility is to use reflection (always unreliable and likely to backfire with all kinds of problems).

Notice you'll also have to pass along the Class of T so that it'll be available at runtime (it's not possible to do T.getName()):

public <T> JAXBElement<T> getJaxbElement (Object obj, Class<T> clazz){
    ObjectFactory objectFactory = getObjectFactory();
    String methodName = "create" +  clazz.getName();
    Method m = objectFactory.getClass().getDeclaredMethod(methodName, clazz);
    Object ret = m.invoke(objectFactory, obj);
    return (JAXBElement<T>) ret;
}
Xavi López
  • 27,550
  • 11
  • 97
  • 161
  • Why do i have to use reflection here ? I have the object. can't i invoke the respective method in `if-else` clause using `instanceof` keyword ? – Em Ae Sep 27 '12 at 17:02
  • Indeed! You don't need reflection at all if you're fine with doing `instanceof`s. In that case just casting the result to `JAXBElement` will work. – Xavi López Sep 27 '12 at 17:04
  • I wrote following method public JAXBElement getJAXBElement (Object obj){ if (obj instanceof OrderType){ return (JAXBElement) objectFactory.createOrderType((OrderType)obj); } return null; } – Em Ae Sep 27 '12 at 17:09
0

Another option of a JAXBElement generic

public class Example<T> {

    public JAXBElement<T> toDo(final T genericType, Class<T> operationClass) {
        final JAXBElement<T> jaxbElement = 
            new JAXBElement<T>(new QName(operationClass.getClass().getSimpleName()), operationClass, genericType);

        return jaxbElement;
    }        
}

Regards!

Harold Castillo
  • 2,006
  • 19
  • 23
0

Simple way, I did below:

public static <T> JAXBElement<T> createJaxbElement(T object, Class<T> clazz) {
    return new JAXBElement<>(new QName(clazz.getSimpleName()), clazz, object);
}
m.nguyencntt
  • 935
  • 13
  • 19
-1
public <T> JAXBElement<T> getJaxbElement (Object obj){
    if (obj instanceof OrderType){
        return (JAXBElement<T>)objectFactory.createOrderType((OrderType)obj);
    }
}

or possibly make T obj's type

public <T> JAXBElement<T> getJaxbElement (T obj){
    if (obj instanceof OrderType){
        return (JAXBElement<T>)objectFactory.createOrderType((OrderType)obj);
    }
}
giannis christofakis
  • 8,201
  • 4
  • 54
  • 65
Joe
  • 7,922
  • 18
  • 54
  • 83