Complex parameters in axis2 web services

C

carmelo

Hi everybody,
I'm developing a web service on which I need to use complex variables
as parameters, using Netbeans 6.7. For example I need to implement
these functions:

public ArrayList<String> get()

public String put(ArrayList<String> list)

I can build and deploy this WS without errors, but I was not able to
make a working client for consuming it. For developing the client I
used the Netbeans Web Service Client wizard... Here is the code:

- Web Service
public ArrayList<String> get()
{
ArrayList<String> list = new ArrayList<String>();
list.add("a1");
list.add("a2");
return list;
}

public String put(ArrayList<String> list)
{
String r = null;
for(int i=0; i<list.size(); i++)
r = r +","+ list.get(i);
return r;
}

- Client
//Put
try {
wslist.Wslist service = new wslist.Wslist();
wslist.WslistPortType port = service.getWslistHttpSoap12Endpoint();

ArrayList<String> list = new ArrayList();
list.add("a1");
list.add("a2");

java.lang.String result = port.put(list);
System.out.println("Result = "+result);
} catch (Exception ex) {
System.err.println(ex);
}

- When the client runs, I get this exception for port.put(list):

javax.xml.ws.WebServiceException: javax.xml.bind.MarshalException
- with linked exception:
[javax.xml.bind.JAXBException: class java.util.ArrayList nor any of
its super class is known to this context.]

- This is the generated WSDL file part relative to the put()
function:
<xs:element name="put">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="list" nillable="true"
type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>



How can I do? I hope you can help me

Thank you very much in advance for your help!
 
C

csaffi

In other words, I need to handle ArrayList<String>, or more
generically List<myClass>, with a JAX-WS web service...


I hope you can help me
 
A

Arne Vajhøj

csaffi said:
In other words, I need to handle ArrayList<String>, or more
generically List<myClass>, with a JAX-WS web service...

I hope you can help me

Try with String[] and MyClass[] instead.

Reason: what should a .NET app or PHP app do with a
java.util.List/java.util.ArrayList ?

Arne
 
A

Arne Vajhøj

I said:
csaffi said:
In other words, I need to handle ArrayList<String>, or more generically
List<myClass>, with a JAX-WS web service...

I hope you can help me
Try with String[] and MyClass[] instead.

Reason: what should a .NET app or PHP app do with a
java.util.List/java.util.ArrayList ?

Why is it any harder or easier for a .NET or PHP app to deal with getting
sent a Java List than it is for it to deal with getting sent a Java
array? Both need to be marshalled in some language-independent way, and,
indeed, they can both be marshalled the same.

If they are marshalled to the same because JAX-WS gives List/ArrayList
special treatment, then it is not a problem.

But if JAX-WS treats it just like any other class, then .NET or
PHP will be told that it is a class
java.util.List/java.util.ArrayList, that they can not
do anything about.

Arne
 
C

csaffi

csaffi said:
In other words, I need to handle ArrayList<String>, or more
generically List<myClass>, with a JAX-WS web service...
I hope you can help me

Try with String[] and MyClass[] instead.

Reason: what should a .NET app or PHP app do with a
java.util.List/java.util.ArrayList ?

Arne

Thank you Arne for your answer, but I'd like to use
ArrayList<MyClass>, because clients are java coded too and they expect
to receive an ArrayList<MyClass> for response.

Is it possible to use ArrayList<MyClass> as input or output parameter
in a web service?

Thank you very much for your help
 
C

csaffi

Thank you guys for your answers.
The web service and the client are both java coded, so there is no
problem with the ArrayList type. My problem is that clients need to
pass/receive ArrayList<MyClass> objects to/from the web service...

For developing the Web Service and the Client I used Netbeans 6.7. The
WS is an Axis2 Web Service, created using the Netbeans "create Axis2
Service from Java..."

I hope you can help me handling complex parameters with Axis2 web
services...


Here is the entire code I used:


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

}


- Here is the generated WSDL

<?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:eek:peration name="get">
<wsdl:input message="axis2:getRequest"
wsaw:Action="urn:get"/>
<wsdl:eek:utput message="axis2:getResponse"
wsaw:Action="urn:getResponse"/>
</wsdl:eek:peration>
</wsdl:portType>
<wsdl:binding name="WSListSOAP11Binding"
type="axis2:WSListPortType">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document"/>
<wsdl:eek:peration name="get">
<soap:eek:peration soapAction="urn:get" style="document"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:eek:utput>
<soap:body use="literal"/>
</wsdl:eek:utput>
</wsdl:eek:peration>
</wsdl:binding>
<wsdl:binding name="WSListSOAP12Binding"
type="axis2:WSListPortType">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/
http" style="document"/>
<wsdl:eek:peration name="get">
<soap12:eek:peration soapAction="urn:get" style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
</wsdl:input>
<wsdl:eek:utput>
<soap12:body use="literal"/>
</wsdl:eek:utput>
</wsdl:eek:peration>
</wsdl:binding>
<wsdl:binding name="WSListHttpBinding"
type="axis2:WSListPortType">
<http:binding verb="POST"/>
<wsdl:eek:peration name="get">
<http:eek:peration location="WSList/get"/>
<wsdl:input>
<mime:content type="text/xml" part="get"/>
</wsdl:input>
<wsdl:eek:utput>
<mime:content type="text/xml" part="get"/>
</wsdl:eek:utput>
</wsdl:eek:peration>
</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>



I hope in your help. Thank you again guys!
 
A

Arne Vajhøj

Mike said:
Arne said:
I said:
In other words, I need to handle ArrayList<String>, or more
generically List<myClass>, with a JAX-WS web service...

I hope you can help me
Try with String[] and MyClass[] instead.

Reason: what should a .NET app or PHP app do with a
java.util.List/java.util.ArrayList ?
Why is it any harder or easier for a .NET or PHP app to deal with
getting sent a Java List than it is for it to deal with getting
sent
a Java array? Both need to be marshalled in some
language-independent way, and, indeed, they can both be marshalled
the same.
If they are marshalled to the same because JAX-WS gives
List/ArrayList
special treatment, then it is not a problem.

But if JAX-WS treats it just like any other class, then .NET or
PHP will be told that it is a class
java.util.List/java.util.ArrayList, that they can not
do anything about.

If you want language-independence, write the XMLSchema that means
"some indefinite number of these" (i.e. maxOccurrs="unbounded"). Let
the toolkit on the client side map it to one language construct, and
let the toolkit on the server side potentially map it to another. It
doesn't matter whether they're arrays, lists, vectors, or something
else entirely.

That is also an option.

But I believe that array support is mandated by the SOAP
standard.

Arne
 
M

Mike Schilling

Arne said:
Mike said:
Arne said:
I V wrote:
In other words, I need to handle ArrayList<String>, or more
generically List<myClass>, with a JAX-WS web service...

I hope you can help me
Try with String[] and MyClass[] instead.

Reason: what should a .NET app or PHP app do with a
java.util.List/java.util.ArrayList ?
Why is it any harder or easier for a .NET or PHP app to deal with
getting sent a Java List than it is for it to deal with getting
sent
a Java array? Both need to be marshalled in some
language-independent way, and, indeed, they can both be
marshalled
the same.
If they are marshalled to the same because JAX-WS gives
List/ArrayList
special treatment, then it is not a problem.

But if JAX-WS treats it just like any other class, then .NET or
PHP will be told that it is a class
java.util.List/java.util.ArrayList, that they can not
do anything about.

If you want language-independence, write the XMLSchema that means
"some indefinite number of these" (i.e. maxOccurrs="unbounded").
Let
the toolkit on the client side map it to one language construct,
and
let the toolkit on the server side potentially map it to another.
It
doesn't matter whether they're arrays, lists, vectors, or
something
else entirely.

That is also an option.

But I believe that array support is mandated by the SOAP
standard.

To the best of my knowledge, the SOAP 1.1 and 1.2 standards do not
include any sort of language binding definitons, and whether SOAP
arrays are represented in Java by arrays or Lists is none of their
concern.
 
A

Arne Vajhøj

Mike said:
Arne said:
Mike said:
Arne Vajhøj wrote:
I V wrote:
In other words, I need to handle ArrayList<String>, or more
generically List<myClass>, with a JAX-WS web service...

I hope you can help me
Try with String[] and MyClass[] instead.

Reason: what should a .NET app or PHP app do with a
java.util.List/java.util.ArrayList ?
Why is it any harder or easier for a .NET or PHP app to deal with
getting sent a Java List than it is for it to deal with getting
sent
a Java array? Both need to be marshalled in some
language-independent way, and, indeed, they can both be
marshalled
the same.
If they are marshalled to the same because JAX-WS gives
List/ArrayList
special treatment, then it is not a problem.

But if JAX-WS treats it just like any other class, then .NET or
PHP will be told that it is a class
java.util.List/java.util.ArrayList, that they can not
do anything about.
If you want language-independence, write the XMLSchema that means
"some indefinite number of these" (i.e. maxOccurrs="unbounded").
Let
the toolkit on the client side map it to one language construct,
and
let the toolkit on the server side potentially map it to another.
It
doesn't matter whether they're arrays, lists, vectors, or
something
else entirely.
That is also an option.

But I believe that array support is mandated by the SOAP
standard.

To the best of my knowledge, the SOAP 1.1 and 1.2 standards do not
include any sort of language binding definitons,

That is correct.
and whether SOAP
arrays are represented in Java by arrays or Lists is none of their
concern.

True.

But it seems as reasonable expectation that for code first then
Java array can and will be translated to SOAP array.

Arne
 
M

Mike Schilling

Arne said:
Mike Schilling wrote:

That is correct.


True.

But it seems as reasonable expectation that for code first then
Java array can and will be translated to SOAP array.

Sure, but "code first" is a toolkit notion, not a SOAP notion.
 
J

jrobinss

Hi, I read other answers, and I think maybe what you're looking for is
called "binding".

Basically, you're asking for a specific Java type, whereas you're
using SOAP. As others have said, SOAP to Java is merely a mapping, the
client can use List and the server Array, or vice-versa, the
communication will still work. So your problem is only generation
config.

So maybe what you're looking for is this:
[...] <jxb:globalBindings collectionType="java.util.Vector" [...] /
(extracted from some JAXB stuff I did some time ago).

This may not be a definitive answer, but I hope it will provide you
some keywords for googling. Often the keywords are what I'm missing
when I have a problem: the answer is out there, but I don't know its
name. :)

Try googling "binding" and "Axis2".
Side-note: Personally I have used Axis1 and JAX-WS, at the time I was
testing tools I coldn't get anything to really work with Axis2. No
tool is great anyway, I more or less agree with most of the criticism
of SOAP I encounter on the web.

Oh, another note: the Axis2 mailing-list was quite helpful when I was
trying it out! Don't hesitate to give it a go.

Hope this helps
 
L

Lew

jrobinss said:
So maybe what you're looking for is this:
[...]   <jxb:globalBindings   collectionType="java.util.Vector" [....] /

I trust
<jxb:globalBindings collectionType="java.util.ArrayList" [...] />
would work?

'Vector' is so very passé.
 
J

jrobinss

jrobinss said:
So maybe what you're looking for is this:
[...]   <jxb:globalBindings   collectionType="java.util.Vector" [....] /

I trust
 <jxb:globalBindings   collectionType="java.util.ArrayList" [...] />
would work?

'Vector' is so very passé.

:)

I would like to say that I wrote it on purpose to get a reaction like
that, like, trolling, you know...

But in all honesty it was a copy paste from old stuff, which in turn
was copy pasted from web samples, and only ever used for isolated
testing of tools. So all in all I plead guilty but with no great
consequence.

Even though it may be said that this here proves that bad code should
never be written, just like some politically incorrect e-mails,
beacuse once it's written you never know where it may end up. :)
 
L

Lew

jrobinss said:
So maybe what you're looking for is this:
[...] <jxb:globalBindings collectionType="java.util.Vector" [...] /
I trust
<jxb:globalBindings collectionType="java.util.ArrayList" [...] />
would work?

'Vector' is so very passé.
:)

I would like to say that I wrote it on purpose to get a reaction like
that, like, trolling, you know...

Oh, you're good. You're very good.
But in all honesty it was a copy paste from old stuff, which in turn
was copy pasted from web samples, and only ever used for isolated
testing of tools. So all in all I plead guilty but with no great
consequence.

That's fine as long as the indicated trick works for other 'collectionType'
values as well.

It's not that 'Vector' (and 'Hashtable') are so bad, really, but just not as
good and shiny and eager to please as their replacements.

More seriously, can that 'collectionType' attribute take interface values, or
must it have a concrete type?
 
C

csaffi

Hi everybody,
thank you very much for all your suggestions!

Therefore the problem is on the WSDL generated by Netbeans? The only
thing I need to pass and receive complex parameters like List<MyClass>
is to fix the WSDL?


Thank you very much in advance for your help
 
C

carmelo

If the web service returns a MyClass[] array instead of a list
List<MyClass>, the client reads properly the response...

Therefore, on the web service side we have:
- public MyClass[] get() -> works
- public List<MyClass> get() -> does NOT work

I defined these two methods in the following manner:

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


Is it possible to return List<MyClass> too?

Thank you very much for your help
 
C

csaffi

Using arrays, it works with methods which "return" an array of
MyClass, but I'm still having problems with methods which take an
array as "input" parameter. For example:

//Web service side
public String put(String list[])
{
return "list.length: "+list.length;
}

//Client side
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);
}

}


How can I do? Thank you very much in advance!
 
J

jrobinss

Lew answered me:
Oh, you're good.  You're very good.

?
I don't understand this remark. I assume it to be ironic.
More seriously, can that 'collectionType' attribute take interface values, or
must it have a concrete type?

I don't know.
 
J

jrobinss

csaffi said:
Hi everybody,
thank you very much for all your suggestions!

Therefore the problem is on the WSDL generated by Netbeans? The only
thing I need to pass and receive complex parameters like List<MyClass>
is to fix the WSDL?

I'm wondering if you read what I wrote and perhaps thought it was
useless or not understandable.

From what I understand you have server and client code.

Both may be generated independently from the same WSDL. Other than
that, they may bear no relationship.

To the best of my knowledge, the WSDL is not in cause, all it has is
some "unbounded" flag to say that there may be several instances of an
object.

The server code, if I understand correctly, satisfies you, with its
List.

The client code doesn't with its arrays.

What if you change the tool's options (for instance JAXB's binding XML
file, or Axis2), couldn't you generate the client-side code that you
want?
 
L

Lew

Answering Lew's predictable response to a reference to 'java.util.Vector',

Lew answered:
?
I don't understand this remark. I assume it to be ironic.

You wrote, humorously, that you aimed to get a reaction. I answered,
humorously, intending to imply that you succeeded brilliantly. I fell for the
'Vector' trap lock, stock and barrel.

I meant only to play along with the humor of your post. I readily confess
that references to 'java.util.Vector' and 'java.util.Hashtable' will usually
get a reaction from me. I intended to imply that you successfully tweaked my
nose and that I admire you for that.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top