In javax xml. Create a general collection in bind

In the rest server I write, I have several collection classes that contain a single item returned from my service:

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "person_collection")
public final class PersonCollection {
    @XmlElement(name = "person")
    protected final List<Person> collection = new ArrayList<Person>();

    public List<Person> getCollection() {
        return collection;
    }
}

I want to refactor these to use generics, so the boilerplate code can be implemented in superclasses:

public abstract class AbstractCollection<T> {
    protected final List<T> collection = new ArrayList<T>();

    public List<T> getCollection() {
        return collection;
    }
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "person_collection")
public final class PersonCollection extends AbstractCollection<Person> {}

How do I set the @ xmlelement annotation on a superclass collection? I'm thinking about something involving @ xmljavatypeadapter and reflection, but I want something simpler How do I create a jaxbcontext? By the way, I'm using resteasy 1.2 1 GA as jax-rs front end

Update (for Andrew white): This is the code that demonstrates the class object that gets the type parameter:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;

public class TestReflection
        extends AbstractCollection<String> {
    public static void main(final String[] args) {
        final TestReflection testReflection = new TestReflection();

        final Class<?> cls = testReflection.getClass();
        final Type[] types = ((ParameterizedType) cls.getGenericSuperclass()).getActualTypeArguments();
        for (final Type t : types) {
            final Class<?> typeVariable = (Class<?>) t;
            System.out.println(typeVariable.getCanonicalName());
        }
    }
}

class AbstractCollection<T> {
    protected List<T> collection = new ArrayList<T>();
}

This is the output: Java lang.String.

Solution

Reflection problem

The following is the reflection test to be performed I believe type erasure is the reason to prevent this from happening:

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class TestReflection extends AbstractCollection<String> {

    private List<Integer> childCollection = new ArrayList<Integer>();


    public List<Integer> getChildCollection() {
        return childCollection;
    }

    public static void main(final String[] args) throws Exception {
        final TestReflection testReflection = new TestReflection();

        final Class<?> cls = testReflection.getClass();
        Method method1 = cls.getmethod("getChildCollection",new Class[] {});
        System.out.println(method1.getGenericReturnType());

        Method method2 = cls.getmethod("getCollection",new Class[] {});
        System.out.println(method2.getGenericReturnType());
   }

}

The above code will output the following This is because the "getcollection" method is in the context of abstractcollection, not testreflection This is to ensure backward compatibility of Java binaries:

java.util.List<java.lang.Integer>
java.util.List<T>

Alternative methods

If the items in the collection will use the @ xmlrootelement annotation, you can do what you want with the following:

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;

public abstract class AbstractCollection<T> {

    protected List<T> collection = new ArrayList<T>();

    @XmlAnyElement(lax=true)
    public List<T> getCollection() {
        return collection;
    }

}

Suppose person looks like this:

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {

}

Then the following demo code:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(PersonCollection.class,Person.class);

        PersonCollection pc = new PersonCollection();
        pc.getCollection().add(new Person());
        pc.getCollection().add(new Person());

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,true);
        marshaller.marshal(pc,System.out);
    }

}

Will produce:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person_collection>
    <person/>
    <person/>
</person_collection>

For more information, see

> http://bdoughan.blogspot.com/2010/08/using-xmlanyelement-to-build-generic.html

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>