簡體   English   中英

JAX-WS和SharePoint用戶組Web服務

[英]JAX-WS and SharePoint usergroup web service

我有一個小應用程序,它查詢我們的SharePoint服務器的Web服務接口,以獲取組的所有用戶的列表。 我可以看到原始HTTP響應將與列出的所有用戶一起返回,但JAX-WS響應對象(在NetBeans 6.9下創建)僅包含空白的Group Name String值。 HTTP響應中沒有所有用戶名的跟蹤。

任何人都知道為什么JAX-WS沒有正確讀取SOAP響應?

WSDL很長,但可以從各個位置廣泛訪問,包括這個站點: http//www.hezser.de/_vti_bin/UserGroup.asmx?wsdl

這是原始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" ....

在生成存根之前,您需要手動編輯UserGroup.wsdl。 您需要將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>

然后,在處理響應時,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);

為什么會這樣

問題是由多種條件引起的:

<GetUserCollectionFromGroup> :Web服務返回的響應包含<GetUserCollectionFromGroup>標記:

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

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尊重<xs:any>processContents屬性(請參閱<xs:any />的Mapping )。 processContents='strict' ,JAXB會嘗試根據子元素所屬的命名空間來匹配(和編組)子元素。

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.省略processContents ,默認值為strict

因此,當JAX-WS / JAXB處理來自Web服務的結果時,它會嘗試使用模式對<GetUserCollectionFromGroupResult>的子項進行編組。 子項在響應中顯示為與請求屬於同一名稱空間。 處理<GetUserCollectionFromGroup>元素時,會將其編組為<GetUserCollectionFromGroup>元素請求中使用的同一類的實例。 因此,您實際上無法訪問<Users>元素。

我搜索過高和低,我能找到的唯一解決方案是以太(a)編輯WSDL,如本答案開頭所述,或(b)編輯生成的存根。 不理想,但在這種情況下不可避免。

有關<xs:any>架構元素(以及processContents屬性)的更多信息可以在MSDN上找到

您的問題有點難以回答,因為我們沒有看到您正在使用的生成的客戶端,也沒有看到調用時的調試/錯誤消息,但我會嘗試。 您的WSDL看起來有效,如果您的JAX-WS工具堆棧能夠創建客戶端(具有適當的Java類)並且能夠正確調用端點,那么您到目前為止表現良好。

查看HTTP響應和您的WSDL,您的SOAP請求是GetUserCollectionFromGroup調用。 看看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>

WSDL基本上說你的調用可以返回任何類型的XML。 你從webservice獲得的是一個XML片段,如:

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

當然,這確實符合任何類型的XML的描述,但我認為您生成的客戶端無法理解它。 現在,我沒有使用NetBeans 6.9的jax-ws工具堆的經驗,但是你應該以這樣的方式配置WSDL到客戶端的生成,它將這個'any'轉換為java XML-Element或java XML-節點對象。

生成的此調用代碼是什么樣的? 它真的認為你得到一個String用戶嗎?

謝謝你的回復。 你是對的我應該發布生成的代碼,但調用和響應是如此簡單,我沒有想到它。 簡化了通話

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

返回的usersCollection只包含一個元素,即“groupName”,其值為“null”。

不幸的是,微軟似乎喜歡在幾乎所有的WSDL定義中使用ANY元素。 我有幾個工作,包括身份驗證,Web,列表,版本,但這個不會去。

我認為可以覆蓋默認的接收器代碼,但是今天早些時候我決定編寫自己的簡單SOAP客戶端可能更容易,而不是試圖找出修復JAX-WS接收器。 因此即使它可能不是最正確的方法,它也完成了工作。 這是所有恐怖的代碼。

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