2012-12-11 40 views
5

我想檢查不同平臺之間的SOAP互操作性;我是一名Java程序員,尤其不瞭解C#。SOAP C#服務器與Java客戶端返回null

我有什麼管理在C#中要做到:

傳輸對象

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Xml.Serialization; 

[XmlRoot] 
public class Pack 
{ 
    private int id; 
    private string name; 

    public Pack() 
    { 
    } 

    public Pack(int anId, string aName) 
    { 
     this.id = anId; 
     this.name = aName; 
    } 

    public void setId(int anId) 
    { 
     this.id = anId; 
    } 

    public int getId() 
    { 
     return id; 
    } 

    public void setName(string aName) 
    { 
     this.name = aName; 
    } 

    public string getName() 
    { 
     return name; 
    } 
} 

Web服務

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Services; 
using System.Xml.Serialization; 

[WebService(Namespace = "http://tempuri.org/")] 
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] 
public class PackWS : System.Web.Services.WebService 
{ 
    private Dictionary<int, Pack> dictionary; 

    public PackWS() 
    { 
     dictionary = new Dictionary<int, Pack>(); 
    } 

    [WebMethod] 
    [XmlInclude(typeof(String))] 
    public String getName() 
    { 
     return "Goodbye world!"; 
    } 

    [WebMethod] 
    [XmlInclude(typeof(Pack))] 
    public void addPackage(Pack package) 
    { 
     dictionary.Add(package.getId(), package); 
    } 

    [WebMethod] 
    [XmlInclude(typeof(Pack))] 
    public Pack getPackage(int id) 
    { 
     return dictionary[id]; 
    } 
} 

該項目建立併發布的WSDL在指定的URI。我添加了一個Java客戶端部分:

傳輸對象

package user; 

import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Pack { 
    private int id; 
    private String name; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

接口:

package user; 

import javax.jws.WebService; 
import javax.jws.soap.SOAPBinding; 

@WebService(targetNamespace = "http://tempuri.org/", 
     portName = "PackWSSoap", 
     wsdlLocation = "http://localhost:57265/Service.asmx?wsdl", 
     serviceName = "PackWS") 
@SOAPBinding(style = SOAPBinding.Style.RPC) 
public interface PackWSSoap { 
    void addPackage(Pack pack); 
    Pack getPackage(int id); 
    String getName(); 
} 

的服務

package user; 

import javax.xml.namespace.QName; 
import javax.xml.ws.Service; 
import java.net.MalformedURLException; 
import java.net.URL; 

public class PackageClient { 
    public static void main(String[] args) { 
     try { 
      URL url = new URL("http://localhost:57265/Service.asmx?wsdl"); 
      QName qName = new QName("http://tempuri.org/", "PackWS"); 

      Service service = Service.create(url, qName); 

      PackWSSoap packWS = service.getPort(PackWSSoap.class); 

      System.out.println(packWS.getName());//null here 

      packWS.addPackage(getPack());//C# exception here 

      System.out.println(packWS.getPackage(getPack().getId()));//unreachable 


     } catch (MalformedURLException e) { 
      e.printStackTrace(); 
     } 
    } 

    static Pack getPack() { 
     return new Pack(){{ 
      setId(2); 
      setName("name"); 
     } 
     }; 
    } 
} 

當調用getName()方法,它應該返回一個簡單的字符串,但它返回null。當試圖通過調用addPackage(pack)將軟件包添加到我接收C#的異常在客戶端上,在Java:

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object. 
    at PackWS.addPackage(Pack package) in f:\DS Projects\ds5\NET\App_Code\PackWS.cs:line 38 
    --- End of inner exception stack trace --- 
    at com.sun.xml.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:163) 
    at com.sun.xml.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:94) 
    at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:236) 
    at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:206) 
    at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:103) 
    at $Proxy18.addPackage(Unknown Source) 
    at user.PackageClient.main(PackageClient.java:25) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 

因爲異常傳遞以及我不認爲是什麼毛病通信;但我相信我沒有向.NET服務器添加任何東西。任何幫助將不勝感激,併爲長期發佈感到抱歉。

這裏是WSDL

<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> 
<wsdl:types> 
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/"> 
<s:element name="getName"> 
<s:complexType/> 
</s:element> 
<s:element name="getNameResponse"> 
<s:complexType> 
<s:sequence> 
<s:element minOccurs="0" maxOccurs="1" name="getNameResult" type="s:string"/> 
</s:sequence> 
</s:complexType> 
</s:element> 
<s:element name="addPackage"> 
<s:complexType> 
<s:sequence> 
<s:element minOccurs="1" maxOccurs="1" name="package" nillable="true" type="tns:Pack"/> 
</s:sequence> 
</s:complexType> 
</s:element> 
<s:complexType name="Pack"/> 
<s:element name="addPackageResponse"> 
<s:complexType/> 
</s:element> 
<s:element name="getPackage"> 
<s:complexType> 
<s:sequence> 
<s:element minOccurs="1" maxOccurs="1" name="id" type="s:int"/> 
</s:sequence> 
</s:complexType> 
</s:element> 
<s:element name="getPackageResponse"> 
<s:complexType> 
<s:sequence> 
<s:element minOccurs="1" maxOccurs="1" name="getPackageResult" nillable="true" type="tns:Pack"/> 
</s:sequence> 
</s:complexType> 
</s:element> 
</s:schema> 
</wsdl:types> 
<wsdl:message name="getNameSoapIn"> 
<wsdl:part name="parameters" element="tns:getName"/> 
</wsdl:message> 
<wsdl:message name="getNameSoapOut"> 
<wsdl:part name="parameters" element="tns:getNameResponse"/> 
</wsdl:message> 
<wsdl:message name="addPackageSoapIn"> 
<wsdl:part name="parameters" element="tns:addPackage"/> 
</wsdl:message> 
<wsdl:message name="addPackageSoapOut"> 
<wsdl:part name="parameters" element="tns:addPackageResponse"/> 
</wsdl:message> 
<wsdl:message name="getPackageSoapIn"> 
<wsdl:part name="parameters" element="tns:getPackage"/> 
</wsdl:message> 
<wsdl:message name="getPackageSoapOut"> 
<wsdl:part name="parameters" element="tns:getPackageResponse"/> 
</wsdl:message> 
<wsdl:portType name="PackWSSoap"> 
<wsdl:operation name="getName"> 
<wsdl:input message="tns:getNameSoapIn"/> 
<wsdl:output message="tns:getNameSoapOut"/> 
</wsdl:operation> 
<wsdl:operation name="addPackage"> 
<wsdl:input message="tns:addPackageSoapIn"/> 
<wsdl:output message="tns:addPackageSoapOut"/> 
</wsdl:operation> 
<wsdl:operation name="getPackage"> 
<wsdl:input message="tns:getPackageSoapIn"/> 
<wsdl:output message="tns:getPackageSoapOut"/> 
</wsdl:operation> 
</wsdl:portType> 
<wsdl:binding name="PackWSSoap" type="tns:PackWSSoap"> 
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/> 
<wsdl:operation name="getName"> 
<soap:operation soapAction="http://tempuri.org/getName" style="document"/> 
<wsdl:input> 
<soap:body use="literal"/> 
</wsdl:input> 
<wsdl:output> 
<soap:body use="literal"/> 
</wsdl:output> 
</wsdl:operation> 
<wsdl:operation name="addPackage"> 
<soap:operation soapAction="http://tempuri.org/addPackage" style="document"/> 
<wsdl:input> 
<soap:body use="literal"/> 
</wsdl:input> 
<wsdl:output> 
<soap:body use="literal"/> 
</wsdl:output> 
</wsdl:operation> 
<wsdl:operation name="getPackage"> 
<soap:operation soapAction="http://tempuri.org/getPackage" style="document"/> 
<wsdl:input> 
<soap:body use="literal"/> 
</wsdl:input> 
<wsdl:output> 
<soap:body use="literal"/> 
</wsdl:output> 
</wsdl:operation> 
</wsdl:binding> 
<wsdl:binding name="PackWSSoap12" type="tns:PackWSSoap"> 
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/> 
<wsdl:operation name="getName"> 
<soap12:operation soapAction="http://tempuri.org/getName" style="document"/> 
<wsdl:input> 
<soap12:body use="literal"/> 
</wsdl:input> 
<wsdl:output> 
<soap12:body use="literal"/> 
</wsdl:output> 
</wsdl:operation> 
<wsdl:operation name="addPackage"> 
<soap12:operation soapAction="http://tempuri.org/addPackage" style="document"/> 
<wsdl:input> 
<soap12:body use="literal"/> 
</wsdl:input> 
<wsdl:output> 
<soap12:body use="literal"/> 
</wsdl:output> 
</wsdl:operation> 
<wsdl:operation name="getPackage"> 
<soap12:operation soapAction="http://tempuri.org/getPackage" style="document"/> 
<wsdl:input> 
<soap12:body use="literal"/> 
</wsdl:input> 
<wsdl:output> 
<soap12:body use="literal"/> 
</wsdl:output> 
</wsdl:operation> 
</wsdl:binding> 
<wsdl:service name="PackWS"> 
<wsdl:port name="PackWSSoap" binding="tns:PackWSSoap"> 
<soap:address location="http://localhost:57265/Service.asmx"/> 
</wsdl:port> 
<wsdl:port name="PackWSSoap12" binding="tns:PackWSSoap12"> 
<soap12:address location="http://localhost:57265/Service.asmx"/> 
</wsdl:port> 
</wsdl:service> 
</wsdl:definitions> 
+0

只是一個小建議,而不是解決您的問題,只是一個良好的實踐後維護,在您的WebService註釋中,您使用的是遠程wsdl位置,最好使用本地uri (例如:WEB-INF/WebContent/wsdl/Service.wsdl) –

+2

在您的wsdl中看起來像一個問題。 'xmlns:soap12 =「http://schemas.xmlsoap.org/wsdl/soap12/」'說你正在使用soap 1.2。您的Java客戶端是SOAP 1.1嘗試使用'wsimport'工具生成客戶端,它通常會顯示錯誤。 – user1516873

+0

你的問題不是你所接收的'String'不是null。 C#Web服務正在拋出錯誤。您應該在C#端獲取堆棧跟蹤以查看NullReferenceException發生的位置。另外,從瀏覽器到這裏http:// localhost:57265/Service.asmx會給你一個表單,你可以直接調用WebMethods。你可以用它來查看是否有異常發生,以及你的堆棧跟蹤是什麼。 – tom

回答

5

在.NET Web服務不維護請求之間的會話狀態。當初始化字典,它只是針對有特定要求的持續時間。在隨後的請求,它的空重,所以你得到的例外。

如果要使用一個在請求之間持續存在的對象來實現這樣的服務,可以使用Application作爲共享存儲。它看起來有點難看,因爲你有,當你訪問它強制類型轉換,雖然。

初始化:

Application["dictionary"] = new Dictionary<int, Pack>(); 

添加:

((Dictionary<int, Pack>)Application["dictionary"]).Add(package.getId(), package); 

閱讀:

return ((Dictionary<int, Pack>)Application["dictionary"])[id]; 

有關應用程序商店更多信息 - HttpApplicationState的一個實例 - 可在http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.aspx

+1

感謝您的回答;將信息保存到文件似乎是最簡單的方法。你也知道爲什麼當我調用[WebMethod] [XmlInclude(typeof(String))] public String getName() { { } return「Goodbye world!」; } – m3th0dman

+0

更新代碼以僅返回字符串後,您是否重新部署服務?我剛剛嘗試更新後的代碼,並得到再見了世界!

2

如果不是絕對必要的,我絕不會使用肥皂。我建議你使用放入正文JSON對象的REST Web服務。

+0

我知道REST從大多數觀點來看都更好,但這是爲了學習的目的... – m3th0dman

1

您的.asmx文件(ASP.NET Web服務)在哪裏?

您得到的異常來自PackWS.cs:第38行,它應該是getPackage()web方法。

當我運行PackageClient我得到

Dec 22, 2012 7:13:50 AM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL 
INFO: Creating Service {http://tempuri.org/}PackWS from WSDL: http://10.0.1.32:49232/PackWS.asmx?wsdl 
Dec 22, 2012 7:13:51 AM org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromWSDL 
INFO: Creating Service {http://tempuri.org/}PackWS from WSDL: http://10.0.1.32:49232/PackWS.asmx?wsdl 
Hello world! 

而在.NET Web服務,我得到

System.Collections.Generic.KeyNotFoundException was unhandled by user code 
    HResult=-2146232969 
    Message=The given key was not present in the dictionary. 
    Source=mscorlib 
    StackTrace: 
     at System.Collections.Generic.Dictionary`2.get_Item(TKey key) 
     at PackWS.getPackage(Int32 id) in c:\Users\Vineet\Documents\Visual Studio 2012\Projects\PackWS\PackWS\PackWS.asmx:line 39 
    InnerException: 

爲了解決這個問題遵循什麼斯科特的上述。對於.NET Web服務在

https://github.com/firefoxNX/StackOverflow/tree/master/PackWS

和Java客戶端

結帳整個源在

https://github.com/firefoxNX/StackOverflow/tree/master/PackWSClient