2012-12-11 13 views
5

Chciałbym sprawdzić współdziałanie SOAP między różnymi platformami; Jestem programistą Java i nie znam w szczególności C#.Serwer SOAP C# z klientem Java null return

Co udało mi się zrobić w C#:

Przedmiotem transferu:

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

Usługa 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]; 
    } 
} 

Projekt tworzy i publikuje WSDL w określonym URI. Dodałem część kliencką Java:

Przedmiotem transferu:

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

Interfejs:

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

Usługa

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

Podczas wywoływania metody getName() powinien zwracać prosty ciąg, ale zwraca wartość null. Gdy próbuje dodać pakiet dzwoniąc addPackage(pack) Otrzymuję wyjątek od C# na kliencie, w Javie:

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) 

Nie wierzę, aby być nic złego w komunikacji ponieważ wyjątek jest przekazywany dobrze; ale uważam, że nie dodałem czegoś do serwera .NET. Każda pomoc będzie doceniona i przykro z powodu długiego postu.

Oto 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

Tylko trochę sugestia, nie rozwiązując problemu, tylko dobre praktyki na później utrzymanie, w adnotacji WebService, używasz zdalnej lokalizacji wsdl, lepiej byłoby użyć lokalnego uri (przykład: WEB-INF/WebContent/wsdl/Service.wsdl) –

+2

wygląda na problem w Twoim kodzie wsdl. 'xmlns: soap12 =" http://schemas.xmlsoap.org/wsdl/soap12/ "' mówi, że używasz mydła 1.2. Twój klient java to SOAP 1.1 Spróbuj wygenerować klienta za pomocą narzędzia 'wsimport', zwykle pokazuje błędy. – user1516873

+0

Twoim problemem NIE jest to, że 'String', który otrzymujesz, nie ma wartości NULL. Usługa internetowa C# rzuca błąd. Powinieneś uzyskać ślad stosu po stronie C#, aby zobaczyć, gdzie występuje wyjątek NullReferenceException. Również tutaj http: // localhost: 57265/Service.asmx z przeglądarki powinien dać ci formularz, w którym możesz bezpośrednio wywołać WebMethods. Możesz go użyć, aby sprawdzić, czy występuje tam wyjątek i jaki jest twój ślad stosu. – tom

Odpowiedz

5

usługi internetowe w .NET nie utrzymują stan sesji pomiędzy żądaniami. Po zainicjowaniu słownika jest on dostępny tylko przez czas trwania tego konkretnego żądania. Przy kolejnych żądaniach jest znowu pusty, stąd wyjątek, który otrzymujesz.

Jeśli chcesz zaimplementować usługę w ten sposób, używając obiektu, który utrzymuje się między żądaniami, możesz użyć aplikacji jako magazynu współużytkowanego. Wygląda to trochę brzydko, ponieważ musisz wpisać rzut po uzyskaniu do niego dostępu.

Inicjalizacja:

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

dodania:

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

Reading:

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

Więcej informacji o sklepie aplikacja - wystąpienie HttpApplicationState - jest dostępny w http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.aspx

+1

Dzięki za odpowiedź; zapisanie informacji do pliku wydaje się najprostszym sposobem. Czy wiesz również, dlaczego uzyskuję wartość zerową podczas wywoływania [WebMethod] [XmlInclude (typeof (String))] public String getName() { return "Goodbye world!"; } – m3th0dman

+0

Czy ponownie wdrożyłeś usługę po aktualizacji kodu, aby zwrócić tylko ciąg znaków? Właśnie wypróbowałem twój zaktualizowany kod i otrzymałem Żegnaj świat!

2

Jeśli nie jest to bezwzględnie konieczne, nigdy nie używałbym mydła.Polecam użyć usługi internetowej REST umieszczając obiekty JSON ciała.

+0

Jestem świadomy, że REST jest lepszy z większości punktów widzenia, ale służy do celów edukacyjnych ... – m3th0dman

1

Gdzie jest plik .asmx (serwis WWW ASP.NET)?

Wyjątek, który otrzymujesz, pochodzi z PackWS.cs: wiersz 38, który powinien być metodą webową getPackage().

Kiedy biegnę PackageClient uzyskać

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! 

A na usługi WWW .NET mam

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: 

Aby ustalić, które następują co Scotta wspomniano powyżej.

Zamówienie cały źródło dla usługi WWW .NET na

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

i Java klienta w

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