javaweb-servicesjakarta-eejaxbjbossws

java.util.List is an interface, and JAXB can't handle interfaces


I seemed to get the following exception when trying to deploy my application:

Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of     IllegalAnnotationExceptions
java.util.List is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
    at java.util.List
    at private java.util.List     foobar.alkohol.register.webservice.jaxws.GetRelationsFromPersonResponse._return
    at     foobar.alkohol.register.webservice.jaxws.GetRelationsFromPersonResponse
java.util.List does not have a no-arg default constructor.
    this problem is related to the following location:
        at java.util.List
        at private java.util.List foobar.alkohol.register.webservice.jaxws.GetRelationsFromPersonResponse._return
    at     foobar.alkohol.register.webservice.jaxws.GetRelationsFromPersonResponse


My code worked just well until I changed the return type from List to List<List<RelationCanonical>>

Here is the partial webservice:


@Name("relationService")
@Stateless
@WebService(name = "RelationService", serviceName = "RelationService")
@SOAPBinding(style = SOAPBinding.Style.DOCUMENT, use = SOAPBinding.Use.LITERAL, parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
public class RelationService implements RelationServiceLocal {

    private boolean login(String username, String password) {
        Identity.instance().setUsername(username);
        Identity.instance().setPassword(password);
        Identity.instance().login();
        return Identity.instance().isLoggedIn();
    }

    private boolean logout() {
        Identity.instance().logout();
        return !Identity.instance().isLoggedIn();
    }

    @WebMethod
    public List<List<RelationCanonical>> getRelationsFromPerson(@WebParam(name = "username")
    String username, @WebParam(name = "password")
    String password, @WebParam(name = "foedselsnummer")
    String... foedselsnummer) {

......
......
......
}


I have also tried by removing the @SOAPBinding and trying default, but the same result occurs. Appreciate any help

UPDATE

I want to note out something. I changed all List to ArrayList, and then it compiled. The reason why I say compiled and not worked is because it behaves strange. I get an Object of type: RelationServiceStub.ArrayList but the object has no get methods or does not behave as a List either. I also tried to cast it to a List but that didnt work.

Note that this is after I have used Axis 2 and wsdl2java So yes, now it compiles, but I dont know how to get the data out.


Solution

  • In my understanding, you will not be able to process a plain List via JAXB, as JAXB has no idea how to transform that into XML.

    Instead, you will need to define a JAXB type which holds a List<RelationCanonical> (I'll call it Type1), and another one to hold a list of those types, in turn (as you're dealing with a List<List<...>>; I'll call this type Type2).

    The result could then be an XML ouput like this:

    <Type2 ...>
        <Type1 ...>
            <RelationCanonical ...> ... </RelationCanonical>
            <RelationCanonical ...> ... </RelationCanonical>
            ...
        </Type1>
        <Type1>
            <RelationCanonical ...> ... </RelationCanonical>
            <RelationCanonical ...> ... </RelationCanonical>
            ...
        </Type1>
        ...
    </Type2>
    

    Without the two enclosing JAXB-annotated types, the JAXB processor has no idea what markup to generate, and thus fails.

    --Edit:

    What I mean should look somewhat like this:

    @XmlType
    public class Type1{
    
        private List<RelationCanonical> relations;
    
        @XmlElement
        public List<RelationCanonical> getRelations(){
            return this.relations;
        }
    
        public void setRelations(List<RelationCanonical> relations){
            this.relations = relations;
        }
    }
    

    and

    @XmlRootElement
    public class Type2{
    
        private List<Type1> type1s;
    
        @XmlElement
        public List<Type1> getType1s(){
            return this.type1s;
        }
    
        public void setType1s(List<Type1> type1s){
            this.type1s= type1s;
        }
    }
    

    You should also check out the JAXB section in the J5EE tutorial and the Unofficial JAXB Guide.