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

JavaWeb ServicesJakarta EeJaxbJbossws

Java Problem Overview


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&lt;List&lt;RelationCanonical&gt;&gt; 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.

Java Solutions


Solution 1 - Java

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.

Solution 2 - Java

If that suits your purpose you can always define an array like this:

YourType[]

JAXB can certainly figure out what that is and you should be able to immediatly use it client side. I would also recommend you to do it that way, since you should not be able to modify the array retrieved from a server via a List but via methods provided by the web service

Solution 3 - Java

If you want to do this for any class.

return items.size() > 0 ? items.toArray((Object[]) Array.newInstance(
			items.get(0).getClass(), 0)) : new Object[0];

	

Solution 4 - Java

You can use "ArrayList" instead of inner "List"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShervin AsgariView Question on Stackoverflow
Solution 1 - JavaHenningView Answer on Stackoverflow
Solution 2 - JavaArgoView Answer on Stackoverflow
Solution 3 - JavaNickView Answer on Stackoverflow
Solution 4 - JavaAhmed Mousaad Abdel-WaneesView Answer on Stackoverflow