简体   繁体   English

JAX-WS和SharePoint用户组Web服务

[英]JAX-WS and SharePoint usergroup web service

I have a small app which query our SharePoint server' Web Service interface for a list of all users for a group. 我有一个小应用程序,它查询我们的SharePoint服务器的Web服务接口,以获取组的所有用户的列表。 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. 我可以看到原始HTTP响应将与列出的所有用户一起返回,但JAX-WS响应对象(在NetBeans 6.9下创建)仅包含空白的Group Name String值。 There is no trace of all the user names from the HTTP response. HTTP响应中没有所有用户名的跟踪。

Anyone know why JAX-WS is not reading in the SOAP response correctly? 任何人都知道为什么JAX-WS没有正确读取SOAP响应?

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 WSDL很长,但可以从各个位置广泛访问,包括这个站点: http//www.hezser.de/_vti_bin/UserGroup.asmx?wsdl

Here's the start of raw HTTP response: 这是原始HTTP响应的开始:

---[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"><soap:Body><GetUserCollectionFromGroupResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/directory/"><GetUserCollectionFromGroupResult><GetUserCollectionFromGroup><Users><User ID="201" Sid="S-1-5-21-1545385408-2720673749-3828181483-1245" ....

You'll need to edit the UserGroup.wsdl manually before generating the stubs. 在生成存根之前,您需要手动编辑UserGroup.wsdl。 You need to add processContents='skip' to the <s:any> tag where the response is defined. 您需要将processContents='skip'添加到定义响应的<s:any>标记中。

<s:element name="GetUserCollectionFromGroupResponse">
 <s:complexType>
  <s:sequence>
    <s:element minOccurs="0" maxOccurs="1" name="GetUserCollectionFromGroupResult">
      <s:complexType mixed="true">
        <s:sequence>
          <!-- Added the "processContents" attribute below -->
          <s:any processContents='skip' />    
        </s:sequence>
      </s:complexType>
    </s:element>
  </s:sequence>
 </s:complexType>
</s:element>

Then, when processing the response, JAXB will return the children as DOM Elements: 然后,在处理响应时,JAXB将子元素作为DOM元素返回:

UserGroup service = new UserGroup();
UserGroupSoap port = service.getUserGroupSoap();

GetUserCollectionFromGroupResult usersCollection = port.getUserCollectionFromGroup(Settings.usersGroup);
List<Object> content = usersCollection.getContent();
org.w3c.dom.Element usersElement = (org.w3c.dom.Element) content.get(0);

Why this works 为什么会这样

The problem is caused by a combination of conditions: 问题是由多种条件引起的:

A. The response returned by the web service contains a <GetUserCollectionFromGroup> tag: <GetUserCollectionFromGroup> :Web服务返回的响应包含<GetUserCollectionFromGroup>标记:

<GetUserCollectionFromGroupResult>
    <GetUserCollectionFromGroup>
       <Users>
          <User ID="4" Name="User1_Display_Name" />
          <User ID="5" Name="User2_Display_Name" />
       </Users>
    </GetUserCollectionFromGroup>
</GetUserCollectionFromGroupResult>

B. The schema embedded in the WSDL defines the <GetUserCollectionFromGroup> as containing one child, <groupName> (this is the element used to make the request): B.嵌入在WSDL中的模式将<GetUserCollectionFromGroup>定义为包含一个子组<groupName> (这是用于发出请求的元素):

<s:element name="GetUserCollectionFromGroup">
  <s:complexType>
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="1" name="groupName" type="s:string"/>
    </s:sequence>
  </s:complexType>
</s:element>

C. JAXB honors the processContents attribute of <xs:any> (see Mapping of <xs:any /> ). C. JAXB尊重<xs:any>processContents属性(请参阅<xs:any />的Mapping )。 When processContents='strict' , JAXB tries to match (and marshall) the child elements based on the namespace they belong to. processContents='strict' ,JAXB会尝试根据子元素所属的命名空间来匹配(和编组)子元素。

D. The WSDL schema definition for the <GetUserCollectionFromGroupResult> includes <xs:any> : D. <GetUserCollectionFromGroupResult>的WSDL模式定义包括<xs:any>

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

E. When processContents is omitted, the default is strict . E.省略processContents ,默认值为strict

Thus, when JAX-WS/JAXB processes the results from the web service, it tries to marshall the children of <GetUserCollectionFromGroupResult> using the schema. 因此,当JAX-WS / JAXB处理来自Web服务的结果时,它会尝试使用模式对<GetUserCollectionFromGroupResult>的子项进行编组。 The children appear in the response as belonging to the same namespace as the request. 子项在响应中显示为与请求属于同一名称空间。 When the <GetUserCollectionFromGroup> element is processed, it is marshalled to an instance of the same class used in the request for the <GetUserCollectionFromGroup> element. 处理<GetUserCollectionFromGroup>元素时,会将其编组为<GetUserCollectionFromGroup>元素请求中使用的同一类的实例。 Thus, you are effectively blocked from getting at the <Users> elements. 因此,您实际上无法访问<Users>元素。

I've searched high and low, and the only solution(s) that I can find is to ether (a) edit the WSDL as described at the start of this answer, or (b) edit the generated stubs. 我搜索过高和低,我能找到的唯一解决方案是以太(a)编辑WSDL,如本答案开头所述,或(b)编辑生成的存根。 Not ideal, but unavoidable in this case. 不理想,但在这种情况下不可避免。

More information about the <xs:any> schema element (and the processContents attribute) can be found on MSDN here . 有关<xs:any>架构元素(以及processContents属性)的更多信息可以在MSDN上找到

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. 您的WSDL看起来有效,如果您的JAX-WS工具堆栈能够创建客户端(具有适当的Java类)并且能够正确调用端点,那么您到目前为止表现良好。

Looking at the HTTP response and your WSDL, your SOAP request was the GetUserCollectionFromGroup call. 查看HTTP响应和您的WSDL,您的SOAP请求是GetUserCollectionFromGroup调用。 Looking at XML-Schema definition (in the WSDL) of GetUserCollectionFromGroupResponse I'm puzzled about one thing: 看看GetUserCollectionFromGroupResponse的 XML-Schema定义(在WSDL中)我很困惑一件事:

 <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. WSDL基本上说你的调用可以返回任何类型的XML。 What you got back from the webservice is an XML piece like: 你从webservice获得的是一个XML片段,如:

<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. 当然,这确实符合任何类型的XML的描述,但我认为您生成的客户端无法理解它。 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. 现在,我没有使用NetBeans 6.9的jax-ws工具堆的经验,但是你应该以这样的方式配置WSDL到客户端的生成,它将这个'any'转换为java XML-Element或java XML-节点对象。

What does the generated code for this call look like? 生成的此调用代码是什么样的? Does it really think you get a String user back? 它真的认为你得到一个String用户吗?

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". 返回的usersCollection只包含一个元素,即“groupName”,其值为“null”。

Unfortunately Microsoft seem to love to use the ANY element in almost all their WSDL definitions. 不幸的是,微软似乎喜欢在几乎所有的WSDL定义中使用ANY元素。 I have several working, including Authentication, Webs, Lists, Versions, but this one just won't go. 我有几个工作,包括身份验证,Web,列表,版本,但这个不会去。

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. 我认为可以覆盖默认的接收器代码,但是今天早些时候我决定编写自己的简单SOAP客户端可能更容易,而不是试图找出修复JAX-WS接收器。 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 ;-) 我是Java的新手,所以对我很轻松;-)

    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/\"><S:Body><GetUserCollectionFromGroup xmlns=\"http://schemas.microsoft.com/sharepoint/soap/directory/\"><groupName>");
    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());
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM