2015-05-06 37 views
6

Ten problem sprawił, że już od prawie dwóch dni jestem zakłopotany, naprawdę potrzebuję pomocy w jego zrozumieniu.Nie można odwzorować odpowiedzi usługi SOAP

Użyłem wsimport do wygenerowania kodu z dwóch różnych plików .wsdl dla projektu Java.

Pierwsza usługa działa dobrze, ale z jakiegoś powodu odpowiedź z drugiej usługi nie może zostać usunięta z obiektu odpowiedzi.

serwis robocza:

@WebMethod(action = "[actionName]") 
@WebResult(name = "getSimpleCompanyInfoResponse", partName = "getSimpleCompanyInfoResponse") 
public GetSimpleCompanyInfoResponse getSimpleCompanyInfo(
     @WebParam(name = "getSimpleCompanyInfoRequest", partName = "getSimpleCompanyInfoRequest") GetSimpleCompanyInfoRequest getSimpleCompanyInfoRequest); 

POJO Response:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "getSimpleCompanyInfoResponse", propOrder = { 
    //variables 
}) 
public class GetSimpleCompanyInfoResponse { 
    //variables 
} 

XML Response:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <SOAP-ENV:Body> 
     <ns1:getSimpleCompanyInfoResponse> 
      <getSimpleCompanyInfoResponse> 
       //variables 
      </getSimpleCompanyInfoResponse> 
     </ns1:getSimpleCompanyInfoResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

NIE usługa działa:

@WebMethod(operationName = "PersonnelInfo", action = "[actionName]") 
@WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse") 
public PersonnelInfoResponse personnelInfo(
@WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest); 

Response POJO: XML

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "PersonnelInfoResponse", propOrder = { 
    //variables 
}) 
public class PersonnelInfoResponse { 
    //variables 
} 

Response:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="[namespaceUri]" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
    <SOAP-ENV:Body> 
     <ns1:PersonnelInfoResponse> 
      //variables 
     </ns1:PersonnelInfoResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

Korzystanie -Dcom.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump = true lub monitoring z Wireshark Widzę, że koperta odpowiedzi z drugiej usługi przychodzi dobrze i unmarshalling nie rzuca żadnych wyjątków, ale w końcu PersonnelInfoResponse ma wartość null.

Jedyną różnicą, jaką widzę, jest to, że drugi ładunek odpowiedzi usługi w kodzie XML nie zawiera elementu zewnętrznego, który wydaje się być problemem. Jednak nie wiem, jak to "naprawić", aby nie szukał elementu zewnętrznego.

Jeśli coś było niejasne lub zaginęło, daj mi znać, a postaram się przekazać wszystkie informacje.

EDIT:

Nie, niestety nie mają żadnej kontroli nad samą usługę, mam tylko .wsdl i .XSD.

Dzwonię usługę tak:

ReportsControllerPortType port = new ReportsControllerService().getReportsControllerPort(); 

PersonnelInfoRequest request = new PersonnelInfoRequest(); 
//fill the required fields in the request, username, password, etc. 

PersonnelInfoResponse response = port.personnelInfo(request); 

Te odcinki serwisowe po stronie klienta (ReportsControllerService & ReportsControllerPortType) są automatycznie generowane przez wsimport według .wsdl i .XSD.

EDIT 2:

Usunięcie nazwy operacji nie działa usługa nie zainicjować. Poniżej znajdują się definicje z obu.WSDL-s:

serwis robocza:

<wsdl:message name="getSimpleCompanyInfoRequest"> 
    <wsdl:part name="getSimpleCompanyInfoRequest" type="tns:getSimpleCompanyInfoRequest" /> 
</wsdl:message> 
<wsdl:message name="getSimpleCompanyInfoResponse"> 
    <wsdl:part name="getSimpleCompanyInfoResponse" type="tns:getSimpleCompanyInfoResponse" /> 
</wsdl:message> 

<wsdl:portType name="MonitoringControllerPortType"> 
    <wsdl:operation name="getSimpleCompanyInfo"> 
     <wsdl:input message="tns:getSimpleCompanyInfoRequest" /> 
     <wsdl:output message="tns:getSimpleCompanyInfoResponse" /> 
    </wsdl:operation> 
</wsdl:portType> 

<wsdl:binding name="MonitoringControllerBinding" type="tns:MonitoringControllerPortType"> 
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> 

    <wsdl:operation name="getSimpleCompanyInfo"> 
     <soap:operation soapAction="[domain]/#getSimpleCompanyInfo" style="rpc" /> 
     <wsdl:input> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:input> 
     <wsdl:output> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:output> 
    </wsdl:operation> 
</wsdl:binding> 

<wsdl:service name="MonitoringControllerService"> 
    <wsdl:port name="MonitoringControllerPort" binding="tns:MonitoringControllerBinding"> 
     <soap:address location="[serviceUri]" /> 
    </wsdl:port> 
</wsdl:service> 

Nie usługa działa:

<wsdl:message name="PersonnelInfoRequest"> 
    <wsdl:part name="PersonnelInfoRequest" type="tns:PersonnelInfoRequest" /> 
</wsdl:message> 
<wsdl:message name="PersonnelInfoResponse"> 
    <wsdl:part name="PersonnelInfoResponse" type="tns:PersonnelInfoResponse" /> 
</wsdl:message> 

<wsdl:portType name="ReportsControllerPortType"> 
    <wsdl:operation name="PersonnelInfo"> 
     <wsdl:input message="tns:PersonnelInfoRequest" /> 
     <wsdl:output message="tns:PersonnelInfoResponse" /> 
    </wsdl:operation> 
</wsdl:portType> 

<wsdl:binding name="ReportsControllerBinding" type="tns:ReportsControllerPortType"> 
    <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> 
    <wsdl:operation name="PersonnelInfo"> 
     <soap:operation soapAction="[domain]/#PersonnelInfo" style="rpc" /> 
     <wsdl:input> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:input> 
     <wsdl:output> 
      <soap:body use="literal" namespace="[namespaceUri]" /> 
     </wsdl:output> 
    </wsdl:operation> 
</wsdl:binding> 

<wsdl:service name="ReportsControllerService"> 
    <wsdl:port name="ReportsControllerPort" binding="tns:ReportsControllerBinding"> 
     <soap:address location="[serviceUri]" /> 
    </wsdl:port> 
</wsdl:service> 

EDIT 3:

ReportsControllerService i MonitoringControllerService rozszerzenie javax.xml.ws.Service i zawierają definicje lokalizacji schematu .wsdl i używanego obszaru nazw. Klasa usługi zwraca obiekt portType jak widać:

/** 
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2 
*/ 
@WebServiceClient(name = "ReportsControllerService", targetNamespace = "[namespaceUri]", wsdlLocation = "[wsdlUri]") 
public class ReportsControllerService extends Service { 

    @WebEndpoint(name = "ReportsControllerPort") 
    public ReportsControllerPortType getReportsControllerPort() { 
     return super.getPort(new QName("[namespaceUri]", "ReportsControllerPort"), ReportsControllerPortType.class); 
    } 
} 

ReportsControllerPortType to interfejs, który zawiera metody dla każdego punktu końcowego sterowania, który istnieje w służbie

/** 
* This class was generated by the JAX-WS RI. JAX-WS RI 2.2.9-b130926.1035 Generated source version: 2.2 
*/ 
@WebService(name = "ReportsControllerPortType", targetNamespace = "[namespaceUri]") 
@SOAPBinding(style = SOAPBinding.Style.RPC) 
@XmlSeeAlso({ObjectFactory.class}) 
public interface ReportsControllerPortType { 

    @WebMethod(operationName = "PersonnelInfo", action = "[actionName]") 
    @WebResult(name = "PersonnelInfoResponse", partName = "PersonnelInfoResponse") 
    public PersonnelInfoResponse personnelInfo(
     @WebParam(name = "PersonnelInfoRequest", partName = "PersonnelInfoRequest") PersonnelInfoRequest personnelInfoRequest); 
    } 
} 

Chodzi o to, wszystko te klasy są automatycznie generowane przez JAX-WS (jak widać z komentarzy) na podstawie schematu .wsdl. Implementacja jest pobierana gdzieś wewnątrz JDK i nie mam nad tym kontroli. Tak, mogę zmienić kod, więc pomijam JAX-WS, ale jak rozumiem, ma to być standardowy sposób korzystania z usług SOAP opartych na .wsdl w postaci de facto.

Projekt wykorzystuje Spring jako bazę-framework i już potwierdziłem, że obie usługi będą działać, gdy używam Spring-WS, więc mogę refaktoryzować, ale chcę zrozumieć, dlaczego ta metoda nie działa.

+0

Twoje pytanie jest niejasne: w jaki sposób dzwonisz do serwisu? Czy kontrolujesz zarówno usługę, jak i klienta? – kolossus

+0

@kolossus, zredagowałem moje pytanie, aby odpowiedzieć na twoje. – rorschach

+0

Co to jest 'ReportsControllerService' i co się dzieje w' getReportsControllerPort() '? – kolossus

Odpowiedz

1

Wydaje mi się, że mogłem się dowiedzieć, dlaczego Twój serwis internetowy źle się zachowuje. Zgodnie ze specyfikacją, RPC usługa musi spełniać następujące kryteria w swojej mydła wiązania (czyli @SOAPBinding adnotacji tam masz)

  1. style z RPC: sprawdź

  2. use z LITERAL: Sprawdź

  3. parameterStyle z WRAPPED: z opisu dałeś, wydaje się, że WRAPPED jest n W tym przypadku, widząc, jak otrzymujesz nagiego PersonnelInfoResponse (i ewentualnie wysyłając nagiego PersonnelInfoRequest) bez żadnego zawijania, oznacza to, że sama usługa jest zepsuta.

Fragment the JAX-WS spec:

Zastosowanie RPC stylu wymaga użycia WRAPPED parametrów stylu.Odchylenia od tego są błędne.

+0

'PersonnelInfoRequest' jest wysyłany owinięty w' PersonnelInfo', ale tak, wynikiem jest nagi 'PersonnelInfoResponse'. Z tego, co mogłem znaleźć również w Google, wydaje mi się, że jest to problem. Dziękuję za potwierdzenie tego. Niestety, nie mam kontroli nad usługą, więc zreformowałem kod i użyłem Spring-WS do wykonania połączeń. Teraz działa. – rorschach

0

Jest jedna oczywista różnica między połączeń 2:

Należy starać się usunąć operationName = "PersonnelInfo" z drugiego naboru, który nie jest obecny w pierwszej pracy jednego.

+0

To nie działa, ponieważ, jak rozumiem, jeśli go brakuje, JAX-WS próbuje przeanalizować nazwę operacji z podpisem metody. Ponieważ metoda zaczyna się od małej litery * p *, to kończy się niepowodzeniem. Zaktualizowałem swój pierwotny wpis o definicje .wsdl, ponieważ możesz zobaczyć, że są praktycznie identyczne w swojej strukturze. – rorschach