• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 895
  • Last Modified:

SOAP calls to Java Web Service

I have a VB client that uses SOAP to call methods in the java web service.  The code for the VB client looks like this:

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Call a webservice's method
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Set objXML = CreateObject("MSXML2.DOMDocument")
    Set objSearchResult = CreateObject("MSXML2.XMLHTTP")
       
    strSearchKey = "<?xml version=""1.0"" encoding=""utf-8""?>" & _
                "<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""" & _
                " xmlns:xsd=""http://www.w3.org/2001/XMLSchema""" & _
                " xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">" & _
                "<soap:Body>" & _
                "<getUserAttributes xmlns=""someuri"">"
 
    strSearchKey = strSearchKey & _
                  "<searchType1>" & "samAccountName" & "</searchType1>" & _
                  "<searchValues1>" & userName & "</searchValues1>" & _
                  "<filterOperator1>" & "1" & "</filterOperator1>" & _
                  "<searchType2>" & "" & "</searchType2>" & _
                  "<searchValues2>" & "" & "</searchValues2>" & _
                  "<filterOperator2>" & "1" & "</filterOperator2>" & _
                  "<attributeNames>" & "mail" & "</attributeNames>" & _
                  "<sortByAttribute>" & "" & "</sortByAttribute>" & _
                  "<sortOrder>" & "1" & "</sortOrder>" & _
                  "</getUserAttributes></soap:Body></soap:Envelope>"
 
    strHTTP = "someurl"
 
    strHeader = "/getUserAttributes"
 
    objSearchResult.Open "POST", strHTTP, False
    objSearchResult.setRequestHeader "SOAPAction", strHeader
    objSearchResult.setRequestHeader "Content-Type", "text/xml"
    objSearchResult.Send strSearchKey
   
    objXML.loadXML (objSearchResult.responseXML.xml)
 
    objXML.loadXML (objXML.selectSingleNode("/SOAP-ENV:Envelope/SOAP-ENV:Body/ns:getUserAttributesResponse/ns:getUserAttributesResult").Text)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


How can I recreate this in C++?  Is there some way of doing this without downloading other components (ex. MSSoap toolkit or EasySoap++)?

If anyone can direct me to some documentation or coding examples that would be a help.

Leo
0
Leo Eikelman
Asked:
Leo Eikelman
  • 12
  • 11
1 Solution
 
Infinity08Commented:
Create the same SOAP request (<soap:Envelope ... </soap:Envelope>), and use a HTTP library (libcurl eg.) to send it to the Java web service using the POST method. Wait for the reply, and process the reply ...

So, yes, you can easily do that ... although I did add the libcurl library for your ease of use. If you don't want to use an extra library, you can of course use sockets (eg. winsock for Windows), to open a connection to the web server, send a HTTP POST request with the SOAP request in the body over that connection, and parse the received reply.
0
 
Infinity08Commented:
Here's a nice winsock tutorial (look in the client section) :

http://johnnie.jerrata.com/winsocktutorial/

Here's libcurl :

http://curl.haxx.se/
0
 
Infinity08Commented:
btw, do you know how to program in C++ ?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
Leo EikelmanAuthor Commented:
Hey,

just got back from a meeting.

I have done a few C++ applications about 2 years ago, so I am just getting back into C++.

I will look into the links you provided when I get some time here and let you know if I have any questions.

Thanks,

Leo
0
 
Leo EikelmanAuthor Commented:
hmmm... I'm not really sure how to use libcurl with SOAP calls.

the link for http://johnnie.jerrata.com/winsocktutorial/ didn't seem to have any references to SOAP calls at all.

Is there any code examples you can provide?


Leo
0
 
Infinity08Commented:
SOAP is a protocol that is used over HTTP. HTTP is the transfer protocol used to send the SOAP payload to the web server.

The SOAP payload is in your case :

   char *soap_req = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
                              "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" \
                              " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" \
                              " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" \
                              "<soap:Body>" \
                              "<getUserAttributes xmlns=\"someuri\">" \
                              "<searchType1>samAccountName</searchType1>" \
                              "<searchValues1>userName</searchValues1>" \
                              "<filterOperator1>1</filterOperator1>" \
                              "<searchType2></searchType2>" \
                              "<searchValues2></searchValues2>" \
                              "<filterOperator2>1</filterOperator2>" \
                              "<attributeNames>mail</attributeNames>" \
                              "<sortByAttribute></sortByAttribute>" \
                              "<sortOrder>1</sortOrder>" \
                              "</getUserAttributes></soap:Body></soap:Envelope>";

Filling in the correct values of course !!

The HTTP protocol prescribes a command followed by a few headers, followed by a blank line, followed by the payload. So, in this case you'd get :

    char *http_headers = "POST /uri HTTP/1.1\r\n" \
                                    "Host: www.url.com\r\n" \
                                    "SOAPAction: http://www.url.com/soapaction\r\n" \
                                    "Content-Type: text/xml\r\n" \
                                    "Content-Length: 100\r\n" \
                                    "\r\n";

Of course using the correct URI, hostname, SOAP action and content length.
If you use libcurl, then you don't need to do this manually of course :)

For SOAP reference, check this page :

http://www.w3schools.com/soap/default.asp
0
 
Leo EikelmanAuthor Commented:
@Infinity08

... I know how SOAP works.  I created the VB SOAP calls in the initial questions.

My question is what do I use in C++ to call the web service using this SOAP?

I have looked at examples of MS Soap Toolkit but can't seem to get it to work properly.

Leo
0
 
Infinity08Commented:
The two options I gave are :

1) do-it-yourself using socket programming ... ie. use the example code from the socket tutorial I gave earlier to
      a) make a connection with the web server
      b) send the HTTP request with SOAP body (ie. HTTP headers followed by SOAP body as i gave in my previous post)
      c) receive the reply
      d) close the connection
   the reply is the reply to the SOAP request (preceded by some HTTP headers) ... you'll have to parse that reply the way you want

2) use a HTTP library (like libcurl) to do all the lower level HTTP stuff for you, so you can focus on SOAP. Use the examples you can find on their site to guide you.

Of course there are also SOAP libraries around, but I was under the impression that you didn't want to use those (from your first post : "without downloading other components (ex. MSSoap toolkit or EasySoap++)"). If you change your mind, personally I find gsoap not bad :

http://gsoap2.sourceforge.net/

On this same site you'll find examples and other help in doing what you want ...
0
 
Leo EikelmanAuthor Commented:
@infinity08

I have been trying to use MS SOAP Toolkit 2.0 to call my Java web service but I can't seem to get it right...

Do you know of any examples on using MS Soap toolkit 2.0?

Leo
0
 
Infinity08Commented:
Here are the MS developer resources for the MS SOAP toolkit 2.0 :

http://msdn.microsoft.com/webservices/webservices/building/soaptk/default.aspx

but I've never used it, so I'm afraid I can't give you an example myself just like that.

But here seems to be a good intro :

http://www.soapuser.com/client4.html
0
 
Leo EikelmanAuthor Commented:
unfortunately this is written in VB, but I'll look around microsoft's website.

Thanks,

Leo
0
 
Infinity08Commented:
>> unfortunately this is written in VB
I was indeed a bit too fast ... but I imagine that the C++ API is similar to the VB API.

This should be better for C++ :

http://www.codeguru.com/cpp/com-tech/complus/soap/article.php/c3945/

:)
0
 
Leo EikelmanAuthor Commented:
Yeah I've tried that one but I still can't seem to get it to work.

Most of the articles I looked at deal with RPC web services because the line at the end is

Reader->RPCResult->text

Mine is a document style web service so I am not sure what code I should be using to call it.

Leo
0
 
Infinity08Commented:
SOAP is intended to do RPCs (remote procedure call), so I'm not sure what you're saying ? Did you just want to retrieve a document ? If so, just drop SOAP, and stick with HTTP !
0
 
Leo EikelmanAuthor Commented:
I mean my web service WSDL file defines the each method as a document style.  I used SOAP to call these methods from VB so there should be no problem using SOAP.  What I mean by document style is this:  (This is from the WSDL file of the web service)

<<<<<<<<<<<<<<<SNIP>>>>>>>>>>>>>>>
....................
- <operation name="getApplicationInfo">
  <soap:operation soapAction="someNameSpace/getApplicationInfo" style="document" />
- <input>
  <soap:body use="literal" />
  </input>
- <output>
  <soap:body use="literal" />
  </output>
  </operation>
.........................
<<<<<<<<<<<<<<<SNIP>>>>>>>>>>>>>>>

Leo
0
 
Infinity08Commented:
That's just the description of the web service (WSDL = Web Service Definition Language).

You call the SOAP action someNameSpace/getApplicationInfo with some input and the result is some output.

How do you call the web service in the code ?
0
 
Leo EikelmanAuthor Commented:
This is the entire code I am using:

#include <atlbase.h>
#include <iostream>

// Replace with the path of SOAP DLLs
// Exclude was added to remove the automatic exclusions
#import "MSXML.dll" named_guids, raw_interfaces_only
#import "C:\\Program Files\\Common Files\\MSSoap\\Binaries\\MSSOAP1.dll" named_guids, no_namespace, raw_interfaces_only exclude("IStream","ISequentialStream","_LARGE_INTEGER","_ULARGE_INTEGER","tagSTATSTG","_FILETIME")

void Add()
{
ISoapSerializerPtr Serializer;
ISoapReaderPtr Reader;
ISoapConnectorPtr Connector;
IStream *inputstream;
IStream *outputstream;

_bstr_t endpoint = L"EndPointURL";
_bstr_t action = L"SoapAction";
_variant_t vEndPoint = "http://someurl/somejws.jws/WSDL";
_variant_t vAction = "getApplicationInfo";

_bstr_t method = L"getApplicationInfo";
_bstr_t command = L"getApplicationInfo";
_bstr_t m = L"m";
_bstr_t a = L"strAppName";
_bstr_t val1 = L"*";

USES_CONVERSION;

try
{
// Create the Connector
Connector.CreateInstance(__uuidof(HttpConnector));

// Connect to the web service
Connector->put_Property(endpoint,vEndPoint);
Connector->put_Property(action,vAction);

// Begin the message to the server
Connector->BeginMessage();

// Create the SoapSerializer
Serializer.CreateInstance(__uuidof(SoapSerializer));

// Connect the serializer to the input stream of the connector
Connector->get_InputStream(&inputstream);
_variant_t stream = inputstream;
Serializer->Init(stream);

// Build the XML message manually
Serializer->startEnvelope(NULL,NULL,NULL);
Serializer->startBody(NULL);
Serializer->startElement(method,command,NULL,m);
Serializer->startElement(a,NULL,NULL,NULL);
Serializer->writeString(val1);
Serializer->endElement();
Serializer->endElement();
Serializer->endBody();
Serializer->endEnvelope();

// Send the message to the web service
Connector->EndMessage();

// Create the SoapReader
Reader.CreateInstance(__uuidof(SoapReader));

// Connect the reader to the output stream of the connector
Connector->get_OutputStream(&outputstream);
_variant_t outstream = outputstream;
VARIANT_BOOL bres;
Reader->Load(outstream, _bstr_t(L""), &bres);

// Get the results from the server and print it
MSXML::IXMLDOMElementPtr element;
Reader->get_RPCResult((IXMLDOMElement **)&element);
BSTR buff;
element->get_text(&buff);
std::cout << W2A(buff) << std::endl;

}
catch(...)
{
std::cout << "Something wrong happened !" << std::endl<< std::endl;
}
}

int main()
{
CoInitialize(NULL);
Add();
CoUninitialize();

return 0;
}



I wasn't exactly sure what the 'm' in this line

Serializer->startElement(method,command,NULL,m);

was supposed to be for so I just left it as what it was when I got the code example of the internet.

When I run this code I get the "Something wrong happened !" printed out and I am not sure how to debug to see what actually happened that caused an error.

Thanks,

Leo
0
 
Infinity08Commented:
First of all, you can narrow it down by using smaller try-catch blocks, as well as by printing out intermediary results. Try to find where exactly the error occurs this way, and what happens. Then you can fix the problem ... debugging often takes longer than the actual writing of the code :)
0
 
Leo EikelmanAuthor Commented:
I get an error on this line:

>>element->get_text(&buff);


Any idea why this might be happening?


Leo
0
 
Infinity08Commented:
After this :

    Reader->get_RPCResult((IXMLDOMElement **)&element);

check that element now contains a valid MSXML::IXMLDOMElementPtr (ie. isn't null). If get_RPCResult() didn't complete successfully (couldn't receive from the web service), then it might be that nothing was filled in

    BSTR buff;
    element->get_text(&buff);

What's the prototype of the get_text() method ? Is it something like :

    get_text(BSTR * b)

??
0
 
Leo EikelmanAuthor Commented:
ok I checked my program and I noticed I was usign the wrong URL.  now the program does not crash but I am receiving an error from WebLogic.  

This line:

std::cout << W2A(buff) << std::endl;

prints out

fc:JWSError

I am not sure how to actually get the value of the error...


Do you see any syntax problems with my code?

Leo
0
 
Leo EikelmanAuthor Commented:
the signature for get_text is:

HRESULT get_text(BSTR *text)


Leo
0
 
Infinity08Commented:
That's an error on the (Java) web server side.

I don't know the MS Soap toolkit as I said before, so I can't tell you if there's a way to get more info on the error (there probably is).

You could also check the server logs (if there are any) to see where the problem lies.

Third option is to use a packet sniffer (like ethereal) to see what the message was ...
0

Featured Post

Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

  • 12
  • 11
Tackle projects and never again get stuck behind a technical roadblock.
Join Now