Newsgroup: it.comp.java
Titolo: Axis2 - come passare parametri complessi

Ciao a tutti,
utilizzando Netbeans ho sviluppato un web service Axis2 che espone due
metodi:
- public List<MyClass> get()
- public String put(List< MyClass> list)
L'obiettivo sarebbe quindi quello di ricevere o passare parametri
complessi, di tipo List<MyClass>
Il deploy del web service l'ho effettuato con successo su Tomcat.
Il problema è con il client generato da Netbeans per consumare il web
service, che non funziona. Non capisco se il problema è dovuto al
codice Java generato oppure al WSDL generato... spero possiate
aiutarmi
Questo è il codice che utilizzo:
- Web Service
//WSList.java
package wslist;
import java.util.ArrayList;
import java.util.List;
public class WSList {
    public List<MyClass> get()
    {
        List<MyClass> list = new ArrayList<MyClass>();
        list.add(new MyClass(1, "descr1"));
        list.add(new MyClass(2, "descr2"));
        return list;
    }
}
//MyClass.java
package wslist;
public class MyClass {
    public int id;
    public String descr;
}
- Client
//WSList_Client.java
package wslist_client;
public class WSList_Client {
    public static void main(String[] args) {
        try { // Call Web Service Operation
            wslist.WSList service = new wslist.WSList();
            wslist.WSListPortType port =
service.getWSListSOAP12PortHttp();
            // TODO process result here
            wslist.xsd.GetResponse result = port.get();
            System.out.println("Result = "+result);
        } catch (Exception ex) {
            // TODO handle custom exceptions here
        }
    }
}
//ObjectFactory.java
package wslist.xsd;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
@XmlRegistry
public class ObjectFactory {
    private final static QName _HelloResponseReturn_QNAME = new QName
("
http://wslist/xsd
", "return");
    private final static QName _HelloName_QNAME = new QName("http://
wslist/xsd", "name");
    public ObjectFactory() {
    }
    public HelloResponse createHelloResponse() {
        return new HelloResponse();
    }
    public Hello createHello() {
        return new Hello();
    }
    public GetResponse createGetResponse() {
        return new GetResponse();
    }
    @XmlElementDecl(namespace = "
http://wslist/xsd
", name = "return",
scope = HelloResponse.class)
    public JAXBElement<String> createHelloResponseReturn(String
value)
{
        return new JAXBElement<String>(_HelloResponseReturn_QNAME,
String.class, HelloResponse.class, value);
    }
    @XmlElementDecl(namespace = "
http://wslist/xsd
", name = "name",
scope = Hello.class)
    public JAXBElement<String> createHelloName(String value) {
        return new JAXBElement<String>(_HelloName_QNAME,
String.class,
Hello.class, value);
    }
    @XmlElementDecl(namespace = "
http://wslist/xsd
", name = "return",
scope = GetResponse.class)
    public JAXBElement<Object> createGetResponseReturn(Object value)
{
        return new JAXBElement<Object>(_HelloResponseReturn_QNAME,
Object.class, GetResponse.class, value);
    }
}
//GetResponse.java
package wslist.xsd;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "_return"
})
@XmlRootElement(name = "getResponse")
public class GetResponse {
    @XmlElementRef(name = "return", namespace = "
http://wslist/xsd
",
type = JAXBElement.class)
    protected JAXBElement<Object> _return;
    public JAXBElement<Object> getReturn() {
        return _return;
    }
    public void setReturn(JAXBElement<Object> value) {
        this._return = ((JAXBElement<Object> ) value);
    }
}
//WSListPortType.java
package wslist;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
import wslist.xsd.GetResponse;
import wslist.xsd.ObjectFactory;
@WebService(name = "WSListPortType", targetNamespace = "http://
wslist/")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface WSListPortType {
    @WebMethod(action = "urn:get")
    @WebResult(name = "getResponse", targetNamespace = "http://
wslist/
xsd", partName = "parameters")
    @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
    public GetResponse get();
    @WebMethod(action = "urn:hello")
    @WebResult(targetNamespace = "
http://wslist/xsd
")
    @RequestWrapper(localName = "hello", targetNamespace = "http://
wslist/xsd", className = "wslist.xsd.Hello")
    @ResponseWrapper(localName = "helloResponse", targetNamespace =
"
http://wslist/xsd
", className = "wslist.xsd.HelloResponse")
    public String hello(
        @WebParam(name = "name", targetNamespace = "
http://wslist/
xsd")
        String name);
}
- Questo è il WSDL generato
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="
http://schemas.xmlsoap.org/wsdl/
"
xmlns:axis2="
http://wslist/
" xmlns:ns1="
http://org.apache.axis2/xsd
"
xmlns:wsaw="
http://www.w3.org/2006/05/addressing/wsdl
"
xmlns:http="
http://schemas.xmlsoap.org/wsdl/http/
" xmlns:ns0="http://
wslist/xsd" xmlns:xs="
http://www.w3.org/2001/XMLSchema
"
xmlns:mime="
http://schemas.xmlsoap.org/wsdl/mime/
"
xmlns:soap="http://
schemas.xmlsoap.org/wsdl/soap/
" xmlns:soap12="http://
schemas.xmlsoap.org/wsdl/soap12/
" targetNamespace="
http://wslist/
">
    <wsdl:types>
        <xs:schema xmlns:ns="
http://wslist/xsd
"
attributeFormDefault="qualified" elementFormDefault="qualified"
targetNamespace="
http://wslist/xsd
">
            <xs:element name="getResponse">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="return"
nillable="true" type="xs:anyType"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:schema>
    </wsdl:types>
    <wsdl:message name="getRequest"/>
    <wsdl:message name="getResponse">
        <wsdl:part name="parameters" element="ns0:getResponse"/>
    </wsdl:message>
    <wsdl:portType name="WSListPortType">
        <wsdl:operation name="get">
            <wsdl:input message="axis2:getRequest"
wsaw:Action="urn:get"/>
            <wsdl:output message="axis2:getResponse"
wsaw:Action="urn:getResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="WSListSOAP11Binding"
type="axis2:WSListPortType">
        <soap:binding transport="
http://schemas.xmlsoap.org/soap/
http"
style="document"/>
        <wsdl:operation name="get">
            <soap:operation soapAction="urn:get" style="document"/>
            <wsdl:input>
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="WSListSOAP12Binding"
type="axis2:WSListPortType">
        <soap12:binding transport="
http://schemas.xmlsoap.org/soap/
http" style="document"/>
        <wsdl:operation name="get">
            <soap12:operation soapAction="urn:get" style="document"/>
            <wsdl:input>
                <soap12:body use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap12:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:binding name="WSListHttpBinding"
type="axis2:WSListPortType">
        <http:binding verb="POST"/>
        <wsdl:operation name="get">
            <http:operation location="WSList/get"/>
            <wsdl:input>
                <mime:content type="text/xml" part="get"/>
            </wsdl:input>
            <wsdl:output>
                <mime:content type="text/xml" part="get"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="WSList">
        <wsdl:port name="WSListSOAP11port_http"
binding="axis2:WSListSOAP11Binding">
            <soap:address location="
http://localhost:8080/axis2/
services/WSList"/>
        </wsdl:port>
        <wsdl:port name="WSListSOAP12port_http"
binding="axis2:WSListSOAP12Binding">
            <soap12:address location="
http://localhost:8080/axis2/
services/WSList"/>
        </wsdl:port>
        <wsdl:port name="WSListHttpport"
binding="axis2:WSListHttpBinding">
            <http:address location="
http://localhost:8080/axis2/
services/WSList"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
Spero nel vostro aiuto. Grazie mille in anticipo!

Se il web service lo sviluppo in modo da far restituire un array
MyClass[] anzichè una lista List<MyClass>, il client riesce
correttamente a leggerne la risposta...
Quindi, lato web service:
- public MyClass[] get() -> funziona
- public List<MyClass> get() -> non funziona
I metodi li ho definiti nel seguente modo:
public MyClass[] get()
    {
        List<MyClass> list = new ArrayList<MyClass>();
        list.add(new MyClass(1));
        list.add(new MyClass(2));
        return list.toArray(new MyClass[list.size()]);
    }
public List<MyClass> getList()
    {
        List<MyClass> list = new ArrayList<MyClass>();
        list.add(new MyClass(1));
        list.add(new MyClass(2));
        return list;
    }
Sapreste dirmi se è possibile restituire anche List<MyClass>?
Grazie per il vostro aiuto

 Sapreste dirmi se � possibile restituire anche List<MyClass>?
Per esperienza personale, esponi array e non liste. Eviterai una serie di 
problemi di cui non ho la soluzione :)

 problemi di cui non ho la soluzione :)
Grazie per il consiglio Manuel.
Riguardo l'utilizzo di array, è tutto ok con i metodi esposti che
"restituiscono" array, mentre ho ancora problemi con i metodi che
prendono in "input" array. Ad esempio:
//Lato web service
public String put(String list[])
    {
        return "list.length: "+list.length;
    }
//Lato client
public static void put()
    {
        try { // Call Web Service Operation
            wslist.WSList service = new wslist.WSList();
            wslist.WSListPortType port =
service.getWSListSOAP12PortHttp();
            // initialize WS operation arguments here
            java.util.List<java.lang.String> list = new
java.util.ArrayList<java.lang.String>();
            list.add("1");
            list.add("2");
            list.add("3");
            // process result here
            java.lang.String result = port.put(list);
            System.out.println("Result = "+result);
        } catch (Exception ex) {
            System.err.println(ex);
        }
    }
Come potrei fare? Grazie per il vostro aiuto!

 prendono in "input" array.
Sono un po' arrugginito in Axis, ma posta il pezzo di wsdd incriminato ed 
eventuali errori (se ne usi uno) e vediamo un po'.
Casomai, vedi se wsdl2java / java2wsdl (sempre di axis) fanno al caso tuo.

Ho risolto il problema cambiando il codice lato server, usando array
anzichè ArrayList. Lato client lo stub generato realizza un binding
tra l'array MyClass[] e la lista ArrayList<MyClass>. Un'altra cosa
importante è stata quella di aggiungere un costruttore di default
(senza parametri) alla classe MyClass.
-
http://carmelosaffioti.blogspot.com
-