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.

4
  • Not directly answering the question, but you might be interested in using simple binding so that xjc generates @XMLRootElement annotations for base elements. As proposed here. Commented Sep 27, 2012 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 (stackoverflow.com/questions/11620825/…) Commented Sep 27, 2012 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. Commented Sep 27, 2012 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<T> as my return type. Commented Sep 27, 2012 at 16:38

5 Answers 5

5

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;
}
Sign up to request clarification or add additional context in comments.

3 Comments

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 ?
Indeed! You don't need reflection at all if you're fine with doing instanceofs. In that case just casting the result to JAXBElement<T> will work.
I wrote following method public <T> JAXBElement<T> getJAXBElement (Object obj){ if (obj instanceof OrderType){ return (JAXBElement<T>) objectFactory.createOrderType((OrderType)obj); } return null; }
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!

Comments

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);
}

Comments

0

Note that, methodName is not always equal to create + clazz.getName(). Maybe better to map by the first param type.

    @SneakyThrows
    public <T> JAXBElement<T> getJaxbElement(ObjectFactory objectFactory, T obj) {
        Method method = Arrays.stream(objectFactory.getClass().getDeclaredMethods())
                .filter(m -> m.getParameterCount() == 1)
                .filter(m -> obj.getClass().equals(Arrays.stream(m.getParameterTypes()).findFirst().get()))
                .findFirst()
                .orElseThrow();
        Object ret = method.invoke(objectFactory, obj);
        return (JAXBElement<T>) ret;
    }

Assume that the target object has a ObjectFactory class in the same package, then wen can use reflection to create ObjectFactory instance.

    @SneakyThrows
    public <T> JAXBElement<T> getJaxbElement(T obj) {
        Class<?> factoryClass = Class.forName(obj.getClass().getPackageName() + ".ObjectFactory");
        Object objectFactory = factoryClass.getDeclaredConstructor().newInstance();
        return getJaxbElement(objectFactory,obj);
    }

    @SneakyThrows
    public <T> JAXBElement<T> getJaxbElement(Object objectFactory, T obj) {
        Method method = Arrays.stream(objectFactory.getClass().getDeclaredMethods())
                .filter(m -> m.getParameterCount() == 1)
                .filter(m -> obj.getClass().equals(Arrays.stream(m.getParameterTypes()).findFirst().get()))
                .findFirst()
                .orElseThrow();
        Object ret = method.invoke(objectFactory, obj);
        return (JAXBElement<T>) ret;
    }

Comments

-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);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.