I am developing a JaxWS-based test service which supports scripting of various actions in
the server. So, the service provides a single WebMethod which takes a list of command
strings and returns a list of result strings. I defined this using the following WSDL:
| <definitions
|
targetNamespace="http://jbossts.jboss.org/xts/servicetests/generated...
|
xmlns:s="http://www.w3.org/2001/XMLSchema"
|
xmlns:tns="http://jbossts.jboss.org/xts/servicetests/generated"
|
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
|
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
xmlns:wsaw="http://www.w3.org/2006/02/addressing/wsdl"
|
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
xmlns="http://schemas.xmlsoap.org/wsdl/" >
| <types>
| <s:schema
|
targetNamespace="http://jbossts.jboss.org/xts/servicetests/generated...
|
xmlns="http://jbossts.jboss.org/xts/servicetests/generated">
| <s:simpleType name="commandList">
| <s:list itemType="s:string"/>
| </s:simpleType>
|
| <s:simpleType name="resultList">
| <s:list itemType="s:string">
| </s:list>
| </s:simpleType>
|
| <s:complexType name="commandsType">
| <s:sequence>
| <s:element name="commandList"
type="commandList"/>
| </s:sequence>
| </s:complexType>
|
| <s:complexType name="resultsType">
| <s:sequence>
| <s:element name="resultList"
type="resultList"/>
| </s:sequence>
| </s:complexType>
|
| <s:element name="commands"
type="commandsType"/>
|
| <s:element name="results" type="resultsType"/>
|
| <!--
| <s:import
namespace="http://schemas.xmlsoap.org/soap/envelope/"
|
schemaLocation="http://schemas.xmlsoap.org/soap/envelope"/>
| -->
| </s:schema>
| </types>
|
| <message name="Commands">
| <part name="commands" element="tns:commands" />
| </message>
|
| <message name="Results">
| <part name="results" element="tns:results" />
| </message>
|
| <portType name="XTSServiceTestPortType">
| <operation name="serve">
| <input name="Commands" message="tns:Commands"
/>
| <output name="Results" message="tns:Results" />
| </operation>
| </portType>
|
| <binding name="XTSServiceTestPort_SOAPBinding"
type="tns:XTSServiceTestPortType">
| <soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
| <operation name="serve">
| <input message="tns:Commands">
| <soap:body use="literal"/>
| </input>
| <output message="tns:Commands">
| <soap:body use="literal"/>
| </output>
| </operation>
| </binding>
|
| <service name="XTSServiceTestService">
| <port binding="tns:XTSServiceTestPort_SOAPBinding"
name="XTSServiceTestPortType">
| <wsaw:UsingAddressing required="true"/>
| <soap:address
location="http://localhost:9000/xtsservicetests/XTSServiceTestService"/>
| </port>
| </service>
| </definitions>
|
I generated the Java code from this and obtained the following types
| @XmlAccessorType(XmlAccessType.FIELD)
| @XmlType(name = "commandsType", propOrder = {
| "commandList"
| })
| public class CommandsType {
| @XmlList
| @XmlElement(required = true)
| protected List<String> commandList;
| public List<String> getCommandList() {
| if (commandList == null) {
| commandList = new ArrayList<String>();
| }
| return this.commandList;
| }
| }
|
| @XmlAccessorType(XmlAccessType.FIELD)
| @XmlType(name = "resultsType", propOrder = {
| "resultList"
| })
| public class ResultsType {
| @XmlList
| @XmlElement(required = true)
| protected List<String> resultList;
| public List<String> getResultList() {
| if (resultList == null) {
| resultList = new ArrayList<String>();
| }
| return this.resultList;
| }
| }
|
The server interface was generated as follows:
| @WebService(name = "XTSServiceTestPortType", targetNamespace =
"http://jbossts.jboss.org/xts/servicetests/generated")
| @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
| public interface XTSServiceTestPortType {
| @WebMethod
| @WebResult(name = "results", targetNamespace =
"http://jbossts.jboss.org/xts/servicetests/generated", partName =
"results")
| public ResultsType serve(
| @WebParam(name = "commands", targetNamespace =
"http://jbossts.jboss.org/xts/servicetests/generated", partName =
"commands")
| CommandsType commands);
| }
|
This works fine for a whole load of cases where I supply a series of string commands and
get one or more strings as a reply. However, I found to my surprise a case where the
results gets mangled. One of my command types contains the single command
"subtransaction" which causes the server to start a subordinate transaction and
return a transaction id. I call it as follows
| commands = new CommandsType();
| commands.getCommandList().add("subtransaction");
|
| try {
| results = port.serve(commands);
| } catch (Exception e) {
| exception = e;
| }
|
On the server side I obtain a CommandsType containing a list with the single String
element "subtransaction" as expected. The code which returns the result is as
follows:
| result = new ResultsType();
| resultsList = result.getResultsList()
| String id = newTx.toString();
| resultsList.add(id);
| return resultsList;
|
When I look at resultsList it contains a single String soemthing like this
"AtomicTransactionIdentifier: urn:-53ef7d93:9592:499c0a00:ec".
Now, going back to the client the value returned from the call to port.serve(commands) is
a ResultsType whose ResultsList contains two strings,
"AtomicTransactionIdentifier:" and "urn:-53ef7d93:9592".
In my debugger I stepped up out of the server implementation method from the return
statement up to the point where the returned value was encoded into a SOAPMessage and
printed the message to System.out. The result was as follows:
| 13:54:22,795 INFO [STDOUT] <env:Envelope
xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'><env:...
xmlns:ns1="http://jbossts.jboss.org/xts/servicetests/generated"...:
urn:-53ef7d93:9592:499c0a00:ec</resultList></ns1:results></env:Body></env:Envelope>
|
It looks like the message text representation of the SOAP element corresponding to field
resultsList of type List is encoded by printing the text of each String separated by
spaces inside tags and decoded by reading back in the space-separated character
sequences found between these tags. This appears to ignore the presence of spaces embedded
in any of the Strings. That's not exactly what I would call robust :-).
Firstly, is this a WS issue or a JaxB issue?
Secondly, can I get round this by using a more sophiisticated schema or do I have to
resort to registering my own encode/decode callbacks with JaxB?
I realise I could avoid the problem by making sure my Strings don't contain spaces but
I'd prefer to implement a more usable service.
View the original post :
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4211101#...
Reply to the post :
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&a...