SOAP mit C++
-
Hallöche
Ich hoffe, dass der Artikel hier richtig ist...
Also ich bin momentan gerade dabei einen Systinet C++ SOAP-Server zu betreiben. Habe bis jetzt nur primitive datentype in dem wsdlc-Document verwendet und es lief tadellos. Wenn ich primitive Datentypen verwende, dann erscheinen die auch als solche in dem dementsprechenden C++ Code via Übersetzung des wsdl-Documentes mit 'wsdlc'. Einen string kann ich dann auch als einen C++ String verwenden.
Jetzt habe ich mich schlau gemacht, wie man Arrays mit SOAP verwendet. Wenn ich jedoch solch ein Array in einer Funktion als Rückgabewert verwende und einen primitiven Datentyp als Übergabeparameter, erscheint mein primitiver Übergabeparameter nicht mehr als ein solcher....
...verwirrt????... hier mein wsdl-File:<?xml version="1.0" encoding="utf-8" ?> <definitions name="GuiFairSOAP" targetNamespace="http://systinet.com/wsdl/GuiFairSOAP/wsdl/" xmlns:tns="http://systinet.com/wsdl/GuiFairSOAP/wsdl/" xmlns:map='http://systinet.com/mapping/' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/' xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd1="http://systinet.com/wsdl/GuiFairSOAP/xsd1/"> <types> <xsd:schema elementFormDefault="qualified" targetNamespace="http://dev.systinet.com/GuiFairSOAP/Types/" xmlns:tns="http://dev.systinet.com/GuiFairSOAP/Types/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/' xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'> <!-- Elemenst for getDatabaseDataRequest --> <xsd:element name='getDatabaseDataRequest'> <xsd:complexType> <xsd:sequence> <xsd:element name='query' nillable='true' type='xsd:string'/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name='getDatabaseDataResponse'> <xsd:complexType> <xsd:sequence> <xsd:element name='response' nillable='true' type='xsd:string'/> </xsd:sequence> </xsd:complexType> </xsd:element> [b]<xsd:complexType name="ArrayType"> <xsd:complexContent> <xsd:restriction base="SOAP-ENC:Array"> <xsd:attribute ref="SOAP-ENC:arrayType" wsdl:arrayType="xsd:float[]"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType>[/b] </xsd:schema> </types> <message name="GuiFairSOAP_getDatabaseData_Request_Soap"> <part name="arguments" element="tns:getDatabaseDataRequest"/> </message> <message name="GuiFairSOAP_getDatabaseData_Response_Soap"> [b] <part name="return_vals" type="tns:ArrayType"/>[/b] </message> <portType name="GuiFairSOAP"> <operation name="getDatabaseData"> <input message="tns:GuiFairSOAP_getDatabaseData_Request_Soap"/> <output message="tns:GuiFairSOAP_getDatabaseData_Response_Soap"/> </operation> </portType> <binding name="GuiFairSOAP" type="tns:GuiFairSOAP"> <operation name="getDatabaseData"> <soap:operation soapAction="getDatabaseData" style="document"/> <input> <soap:body parts="arguments" use="literal"/> </input> <output> <soap:body parts="return_vals" use="literal"/> </output> </operation> </binding> <service name="GuiFairSOAPService"> <!-- We will build our SSC service to this URL --> <port name="GuiFairSOAPService" binding="tns:GuiFairSOAP"> <soap:address location="http://localhost:6070/GuiFairSOAP/" /> </port> </service> </definitions>
Die Funktion die dann von 'wsdlc' definiert wird schaut dann wie folgt aus
/** * getDatabaseData method. * * WSDL operation name: 'getDatabaseData' * @param arguments is input parameter (WSDL name: 'arguments') **/ virtual ::ArrayType getDatabaseData (::GetDatabaseDataRequest & arguments) = 0;
Würde ich anstelle von 'type="tns:ArrayType"' 'element="tns:getDatabaseDataResponse"' verwenden, würde die Definition wie folgt ausschauen:
virtual WASP_STD_NS::string getDatabaseData (const WASP_STD_NS::string & query) = 0;
Gibt es eine Möglichkeit, dass wenigstens mein Übergabe-String dann noch als string erscheint, wenn ich ein Array verwende???
Ich hoffe, dass mir dabei jemand weiterhelfen kann....
Viele liebe Grüße
Manfred
-
Da (Zeile 17-24) isses doch eigentlich schon:
<!-- Elemenst for getDatabaseDataRequest --> <xsd:element name='getDatabaseDataRequest'> <xsd:complexType> <xsd:sequence> <xsd:element name='query' nillable='true' type='xsd:string'/> </xsd:sequence> </xsd:complexType> </xsd:element>
Dann müsstest Du's hier (Zeile 41-43)
[html]<message name="GuiFairSOAP_getDatabaseData_Request_Soap">
<part name="arguments" element="tns:getDatabaseDataRequest"/>
</message>[/html]doch eigentlich patchen können:
<message name="GuiFairSOAP_getDatabaseData_Request_Soap"> <part name="arguments" element="xsd:string"/> </message>
Grüsse
*this
-
Das war ein sehr guter Tipp, dankeschön...
hat bis dahin geklappt
Jetzt habe ich allerdings ein anderes Problem...
Schicke ich nun meine Anfrage an den Server, so meckert er:Wrong XML token encountered during primitive type deserialization
Er kann anscheinend den Typ nicht richtig zuordnen...
Ich nutze als Client Axis2Java. Mein Aufruf schaut so aus:OperationClient() sender2 = new ServiceClient().createClient(ServiceClient.ANON_OUT_IN_OP); MessageContext mcout = new MessageContext(); options2 = mcout.getOptions(); targetEPR = new EndpointReference("http://localhost:6080/GuiFairSOAP"); options2.setTo(targetEPR); options2.setAction("getDatabaseData"); mcout.setEnvelope(createSOAPEnvelope()); sender2.addMessageContext(mcout); sender2.execute(true); //false->nonblocking true->blocking MessageContext mcin = sender2.getMessageContext("In"); SOAPEnvelope response = mcin.getEnvelope(); public SOAPEnvelope createSOAPEnvelope(){ SOAPFactory fac = OMAbstractFactory.getSOAP11Factory(); SOAPEnvelope envelope = fac.getDefaultEnvelope(); OMNamespace omNs = fac.createOMNamespace("http://www.w3.org/2001/XMLSchema", "xsd"); OMElement method = fac.createOMElement("getDatabaseData", omNs); OMElement value = fac.createOMElement("double", omNs); //benötige nun einen doublewert value.setText("1.0"); method.addChild(value); envelope.getBody().addChild(method); return envelope; }
Und so sieht dann die SOAP-Nachricht aus:
POST /GuiFairSOAP HTTP/1.1 SOAPAction: "getDatabaseData" User-Agent: Axis2 Host: 127.0.0.1:6080 Transfer-Encoding: chunked Content-Type: text/xml; charset=UTF-8 11a <?xml version='1.0' encoding='UTF-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header /> <soapenv:Body> <xsd:getDatabaseDataxmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:double>1.0</xsd:double> </xsd:getDatabaseData> </soapenv:Body> </soapenv:Envelope>0
Kann evtl. jemand für ganz blöde (wie mich wahrscheinlich
) schreiben, wie ich einen solchartigen Aufruf umsetze? Ich weiß, es ist ein wenig viel verlangt, aber ich denke, dass der Code ansich nicht so gravieren lang sein wird... Interessieren würde mich, falls sich an der wsdl nichts ändern würde, nur der java und c++ code (sprich primitiver als übergabeparameter und array als response) (Meine Methode lautet in c++ so: "virtual ::ArrayType getDatabaseData (double arguments) = 0;") habe schon etliche tutorials durch, aber ich bekomm es einfach nicht hin und das geht mittlerweile schon ne halbe ewigkeit so. Demjenigen wäre ich total dankbar....
Gruß Manfred
Nachtrag:
evtl liegt das auch einfach nur an nem falschen Namespace, den ich verwende...
-
Falls es weiterhilft, ich habe den Fehler reproduzieren können, indem ich zwei primitive übergabeparameter sende und einen primitiven parameter zurücksende.
Nun bin ich völlig verwirrt....
Habe folgendes:<xsd:element name="testType3" type="xsd:double"/> <xsd:element name="testType4" type="xsd:double"/> <xsd:element name="testType5" type="xsd:int"/> ... <message name="GuiFairSOAP_fahr2cel_Request_Soap"> <part name="fahr1" element="local:testType3"/> <part name="fahr2" element="local:testType5"/> </message> <message name="GuiFairSOAP_fahr2cel_Response_Soap"> <part name="response" element="local:testType4"/> </message>
und JavaCode:
... opArgs = new Object[]{4, 5}; payload = BeanUtil.getOMElement(opGetDB, opArgs, null, false, null); ...
komische Sache. Hoffentlich kann mir jemand dabei helfen...