views:

78

answers:

2

Hi All,

I have a small app which query our SharePoint server' Web Service interface for a list of all users for a group. I can see the raw HTTP response is coming back with all the users listed, but JAX-WS response object (as created under NetBeans 6.9) contains only a blank Group Name String value. There is no trace of all the user names from the HTTP response.

Anyone know why JAX-WS is not reading in the SOAP response correctly?

The WSDL is to long to post, but is widely accessable from various locations, including this site: http://www.hezser.de/_vti_bin/UserGroup.asmx?wsdl

Here's the start of raw HTTP response:

---[HTTP response - http://{server}/_vti_bin/usergroup.asmx - 200]---
null: HTTP/1.1 200 OK
Cache-control: private, max-age=0
Content-type: text/xml; charset=utf-8
Content-length: 136738
X-powered-by: ASP.NET
Server: Microsoft-IIS/6.0
Date: Wed, 22 Sep 2010 20:53:12 GMT
X-aspnet-version: 2.0.50727
Set-cookie: WSS_KeepSessionAuthenticated=80; path=/
Microsoftsharepointteamservices: 12.0.0.6303
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;&lt;soap:Body&gt;&lt;GetUserCollectionFromGroupResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/"&gt;&lt;GetUserCollectionFromGroupResult&gt;&lt;GetUserCollectionFromGroup&gt;&lt;Users&gt;&lt;User ID="201" Sid="S-1-5-21-1545385408-2720673749-3828181483-1245" ....
A: 

Your question is a bit hard to answer because we don't see the generated client you're using nor the debug/error messages on invocation, but I'll try. Your WSDL looks valid, and if your JAX-WS toolstack is capable of creating a client (with appropriate Java classes) and is able to invoke the endpoint correctly, you did well so far.

Looking at the HTTP response and your WSDL, your SOAP request was the GetUserCollectionFromGroup call. Looking at XML-Schema definition (in the WSDL) of GetUserCollectionFromGroupResponse I'm puzzled about one thing:

 <s:element name="GetUserCollectionFromGroupResponse"> 
    <s:complexType> 
      <s:sequence> 
        <s:element minOccurs="0" maxOccurs="1" name="GetUserCollectionFromGroupResult"> 
          <s:complexType mixed="true"> 
            <s:sequence> 
              <s:any /> 
            </s:sequence> 
          </s:complexType> 
        </s:element> 
      </s:sequence> 
    </s:complexType> 
  </s:element>

The WSDL basically says your call can return Any kind of XML. What you got back from the webservice is an XML piece like:

<users><user ID="201" Sid="" /></users>

Of course this does fit the description of Any kind of XML, but I think your generated client has trouble understanding it. Now, I don't have experience with the jax-ws toolstack of NetBeans 6.9, but you should configure the WSDL-to-client generation in such a way that it transforms this 'any' into a java XML-Element or java XML-Node object.

What does the generated code for this call look like? Does it really think you get a String user back?

ivy
A: 

Hi Ivy

Thanks for the response. You'r right I should have posted the generated code, but the invocation, and response was so simple I didn't think of it. Simplified the calls are

    System.setProperty("com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true");
    GetUserCollectionFromGroupResult usersCollection = null;

    Object o = null;
    UserGroup service = new UserGroup();
    UserGroupSoap port = service.getUserGroupSoap();

    usersCollection = port.getUserCollectionFromGroup(Settings.usersGroup);

The returned usersCollection only contains one element, which is "groupName" with value "null".

Unfortunately Microsoft seem to love to use the ANY element in almost all their WSDL definitions. I have several working, including Authentication, Webs, Lists, Versions, but this one just won't go.

I think it's possible to overwrite the default receiver code, but earlier today I decided it probably would be easier to just write my own simple SOAP client, rather to try and figure out to fix the JAX-WS receiver. So even though it's probably not the most correct approach, it got the work done. Here's the code in all it horror.

I'm new to Java, so go easy on me ;-)

    HashMap<String, String> users = null;
    String SOAPUrl = Settings.userListWebServiceURL;
    String SOAPAction = "http://schemas.microsoft.com/sharepoint/soap/directory/GetUserCollectionFromGroup";

    // Create the connection.
    URL url = new URL(SOAPUrl);
    URLConnection connection = url.openConnection();
    HttpURLConnection httpConn = (HttpURLConnection) connection;

    StringBuilder sb = new StringBuilder();
    sb.append("<?xml version=\"1.0\" ?><S:Envelope xmlns:S=\"http://schemas.xmlsoap.org/soap/envelope/\"&gt;&lt;S:Body&gt;&lt;GetUserCollectionFromGroup xmlns=\"http://schemas.microsoft.com/sharepoint/soap/directory/\"&gt;&lt;groupName&gt;");
    sb.append(Settings.usersGroup);
    sb.append("</groupName></GetUserCollectionFromGroup></S:Body></S:Envelope>");

    byte[] b = sb.toString().getBytes("UTF-8");

    // Set the appropriate HTTP parameters.
    httpConn.setRequestProperty("Content-Length", String.valueOf( b.length ) );
    httpConn.setRequestProperty("Content-Type","text/xml; charset=utf-8");
    httpConn.setRequestProperty("SOAPAction",SOAPAction);
    httpConn.setRequestMethod( "POST" );
    httpConn.setDoOutput(true);
    httpConn.setDoInput(true);

    // Everything's set up; send the XML that was read in to b.
    OutputStream out = httpConn.getOutputStream();
    out.write( b );
    out.flush();
    out.close();

    // Setup to receive the result and convert stream to DOM Document
    DOMParser parser = new DOMParser();
    InputStreamReader in = new InputStreamReader(httpConn.getInputStream());
    InputSource source = new InputSource(in);
    parser.parse(source);
    org.w3c.dom.Document d = parser.getDocument();
    in.close();
    httpConn.disconnect();

    // Read the DOM and contruct a Hashmap with username to e-mail mapping.
    NodeList nl = d.getElementsByTagName("User");
    users = new HashMap<String, String>();
    for (int i = 0; i < nl.getLength(); i++) {
        NamedNodeMap attr = nl.item(i).getAttributes();
        users.put(attr.getNamedItem("LoginName").getNodeValue(), attr.getNamedItem("Email").getNodeValue());
    }
Jan Petersen