2012-12-11 32 views
5

Tôi muốn kiểm tra khả năng tương tác SOAP giữa các nền tảng riêng biệt; Tôi là một lập trình viên Java và không biết C# nói riêng.SOAP C# Máy chủ với máy khách Java không trả lại

gì có tôi quản lý để làm trong C#:

Việc chuyển giao đối tượng:

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

Các Web Service:

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]; 
    } 
} 

Dự án xây dựng và công bố các wsdl tại URI được chỉ định. Tôi đã thêm một phần Java client:

Transfer Object:

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

Giao diện:

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

Dịch vụ

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

Khi gọi phương thức getName(), nó sẽ trả về một String đơn giản, nhưng nó trả về null. Khi cố gắng để thêm một gói bằng cách gọi addPackage(pack) tôi nhận được một ngoại lệ từ C# trên máy khách, trong 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) 

Tôi không tin là bất cứ điều gì sai trái với truyền thông kể từ khi ngoại lệ được thông qua cũng; nhưng tôi tin rằng tôi đã không thêm gì đó vào máy chủ .NET. Bất kỳ trợ giúp sẽ được đánh giá cao và xin lỗi cho bài viết dài.

Đây là 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

Chỉ cần một gợi ý nhỏ, không giải quyết vấn đề của bạn, chỉ cần một thực hành tốt cho sau này duy trì, trong chú thích WebService của bạn, bạn đang sử dụng vị trí wsdl từ xa, sẽ tốt hơn nếu sử dụng địa chỉ uri địa phương (ví dụ: WEB-INF/WebContent/wsdl/Service.wsdl) –

+2

trông giống như một vấn đề trong wsdl của bạn. 'xmlns: soap12 =" http://schemas.xmlsoap.org/wsdl/soap12/ "' cho biết bạn đang sử dụng xà phòng 1.2. Máy khách java của bạn là SOAP 1.1 Cố gắng tạo ra máy khách với công cụ 'wsimport', nó thường hiển thị lỗi. – user1516873

+0

Vấn đề của bạn KHÔNG phải là 'Chuỗi' bạn nhận được không phải là rỗng. Dịch vụ web C# đang ném lỗi. Bạn sẽ nhận được dấu vết ngăn xếp ở phía C# để xem NullReferenceException xảy ra ở đâu. Ngoài ra, truy cập vào đây http: // localhost: 57265/Service.asmx từ trình duyệt của bạn sẽ cung cấp cho bạn một biểu mẫu nơi bạn có thể gọi trực tiếp WebMethods. Bạn có thể sử dụng điều đó để xem liệu ngoại lệ có xảy ra ở đó không và dấu vết ngăn xếp của bạn là gì. – tom

Trả lời

5

dịch vụ Web trong .NET không duy trì trạng thái phiên giữa các yêu cầu. Khi bạn khởi tạo từ điển, nó chỉ có trong khoảng thời gian của yêu cầu cụ thể đó. Về các yêu cầu tiếp theo, nó là null một lần nữa, do đó ngoại lệ bạn đang nhận được.

Nếu bạn muốn triển khai dịch vụ như thế này, sử dụng một đối tượng tồn tại giữa các yêu cầu, bạn có thể sử dụng Ứng dụng làm cửa hàng dùng chung. Nó trông hơi xấu xí bởi vì bạn phải gõ cast khi bạn truy cập nó, mặc dù.

khởi:

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

Thêm:

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

Reading:

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

Thông tin thêm về các cửa hàng ứng dụng - một thể hiện của HttpApplicationState - có sẵn tại http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.aspx

+1

Cảm ơn câu trả lời; lưu thông tin vào một tệp có vẻ là cách dễ nhất. Bạn cũng biết tại sao tôi nhận được null khi gọi [WebMethod] [XmlInclude (typeof (String))] Public String getName() { trả về "Tạm biệt thế giới!"; } – m3th0dman

+0

Bạn đã triển khai lại dịch vụ sau khi cập nhật mã để chỉ trả lại chuỗi? Tôi vừa thử mã cập nhật của bạn và nhận Tạm biệt thế giới!

2

Nếu không cần thiết, tôi sẽ không bao giờ sử dụng xà phòng.Tôi sẽ khuyên bạn nên sử dụng một dịch vụ web REST đặt trong các đối tượng JSON cơ thể.

+0

Tôi biết rằng REST là tốt hơn từ hầu hết các quan điểm, nhưng điều này là dành cho mục đích học tập ... – m3th0dman

1

Tệp .asmx của bạn (dịch vụ web ASP.NET) ở đâu?

Trường hợp ngoại lệ bạn nhận được từ PackWS.cs: dòng 38 phải là phương thức web getPackage().

Khi tôi chạy PackageClient tôi nhận được

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! 

Và trên dịch vụ web .NET tôi nhận được

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: 

Để khắc phục điều đó làm theo những gì Scott nêu trên.

Thanh toán toàn bộ nguồn cho dịch vụ web NET tại

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

và Java client tại

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

Các vấn đề liên quan