Generic WebService (SOAP) client library for C++ - c++

I'm looking for a simple C++ WebService Client Library that can be easily linked into my application.
Preferably this library:
can be used to access any SOAP WebService (so I can pass the URL, the WebService name, the WebService method and all the arguments as arguments to a function call)
can be linked statically in a C++ application (so no DLL's)
is freeware or available at a low cost
can be used royalty-free in my application
can query the Web service for its WSDL and return me the available method names, arguments of the methods and their data types
Before anyone of you answers .NET: been there, tried it. My major objections against .NET are:
you can generate the proxy but it's impossible to change the WebService name in the generated proxy code afterwards, since .NET uses reflection to check the WebService name (see Dynamically call SOAP service from own scripting language for my question regarding that problem)
generating the proxy class on the fly doesn't always seem to work correctly
I already used Google to look up this information, but I couldn't find one.
Thanks
EDIT:
To clarify this further, I really want something where I can write code like this (or something in this style):
SoapClient mySoapClient;
mySoapClient.setURL("http://someserver/somewebservice");
mySoapClient.setMethod("DoSomething");
mySoapClient.setParameter(1,"Hello");
mySoapClient.setParameter(2,12345);
mySoapClient.sendRequest();
string result;
mySoapClient.getResult(result);
No dynamic code generation.

Have you looked at gSOAP? I think it will be suitable for your needs.
http://gsoap2.sourceforge.net/

I found a solution using on-the-fly-generated assemblies (which I couldn't get working the previous time). Starting point is http://refact.blogspot.com/2007_05_01_archive.html.
E.g. This is the code to use the PeriodicTable web service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Services;
using System.Web.Services.Description;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Xml.Serialization;
using System.IO;
using System.Reflection;
namespace GenericSoapClient
{
class Program
{
static void method1()
{
Uri uri = new Uri("http://www.webservicex.net/periodictable.asmx?WSDL");
WebRequest webRequest = WebRequest.Create(uri);
System.IO.Stream requestStream = webRequest.GetResponse().GetResponseStream();
// Get a WSDL
ServiceDescription sd = ServiceDescription.Read(requestStream);
string sdName = sd.Services[0].Name;
// Initialize a service description servImport
ServiceDescriptionImporter servImport = new ServiceDescriptionImporter();
servImport.AddServiceDescription(sd, String.Empty, String.Empty);
servImport.ProtocolName = "Soap";
servImport.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties;
CodeNamespace nameSpace = new CodeNamespace();
CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
codeCompileUnit.Namespaces.Add(nameSpace);
// Set Warnings
ServiceDescriptionImportWarnings warnings = servImport.Import(nameSpace, codeCompileUnit);
if (warnings == 0)
{
StringWriter stringWriter =
new StringWriter(System.Globalization.CultureInfo.CurrentCulture);
Microsoft.CSharp.CSharpCodeProvider prov =
new Microsoft.CSharp.CSharpCodeProvider();
prov.GenerateCodeFromNamespace(nameSpace,
stringWriter,
new CodeGeneratorOptions());
string[] assemblyReferences =
new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
CompilerParameters param = new CompilerParameters(assemblyReferences);
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.TreatWarningsAsErrors = false;
param.WarningLevel = 4;
CompilerResults results = new CompilerResults(new TempFileCollection());
results = prov.CompileAssemblyFromDom(param, codeCompileUnit);
Assembly assembly = results.CompiledAssembly;
Type service = assembly.GetType(sdName);
//MethodInfo[] methodInfo = service.GetMethods();
List<string> methods = new List<string>();
// only find methods of this object type (the one we generated)
// we don't want inherited members (this type inherited from SoapHttpClientProtocol)
foreach (MethodInfo minfo in service.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{
methods.Add(minfo.Name);
Console.WriteLine (minfo.Name + " returns " + minfo.ReturnType.ToString());
ParameterInfo[] parameters = minfo.GetParameters();
foreach (ParameterInfo pinfo in parameters)
{
Console.WriteLine(" " + pinfo.Name + " " + pinfo.ParameterType.ToString());
}
}
// Create instance of created web service client proxy
object obj = assembly.CreateInstance(sdName);
Type type = obj.GetType();
object[] args0 = new object[] { };
string result0 = (string)type.InvokeMember(methods[0], BindingFlags.InvokeMethod, null, obj, args0);
Console.WriteLine(result0);
object[] args1 = new object[] { "Oxygen" };
string result1 = (string)type.InvokeMember(methods[1], BindingFlags.InvokeMethod, null, obj, args1);
Console.WriteLine(result1);
}
}
}
}
In this code I explicitly use methods[0] and methods[1] but in reality you would check the method names of course. In this example I get the names of all elements in the periodic table, then get the atomic weight of oxygen.
This example does not yet contain logic to support a proxy. I still need to add this, but for the moment, it solves my biggest problem, namely, having a generic SOAP client.
EDIT:
I know this code is C# and I was originally asking for a C++ solution, but this code proves that it can work in a .NET environment (which I can still use in limited parts of my application), and I will probably rewrite this code into C++/.NET, which solves my problem.

Axis2C : http://axis.apache.org/axis2/c/core/index.html
Axis2C ticks most of the above , please check for static linking. .
EDIT: As per last few messages on the list, static linking is incomplete. The below still holds:
Perhaps I do not understand the question correctly. Any web service you call you need to specify the endpoint URL and the operation & parameters.
Are you referring to dynamically "discovering" the services & presenting the option to call them...? If so I doubt this is possible.
If you are referring to generic framework, SOAP messages are client end responsibility any way... You should not have a problem wrapping them under some of the toolkit API's. WSDL code generation is not mandatory. I have written a few services from scratch, i.e. You can set endpoint, service and craft the SOAP message, parameters, headers etc. as you feel.
Cheers!

Related

Missing Xerces C++ class to copy attributes of element for use after SAX2 parsing

The documentation of xerces anticipates the need to make a copy of attributes, but the AttributesImpl class doesn't seem to exist. Neither does the facility seem to exist in other associated classes in either the current 3.2.3 version of xerces or previous 2.X
Xerces documentation in the file itself src/xercesc/sax2/Attributes.hpp says:
"The instance provided will return valid results only during the scope of the startElement invocation (to save it for future use, the application must make a copy: the AttributesImpl helper class provides a convenient constructor for doing so)."
See also I've left issue here as a bug in xerces
https://issues.apache.org/jira/browse/XERCESC-2238
Appears I will be stuck instead creating my own version of attributes in which to copy or clone, and not overwritten each new line. Not saving whole document (which would defeat purpose of SAX streaming parse), but the existing framework populating Attributes is pretty convoluted and undocumented. Obviously the library and docs are designed to use the api, not to hack or extend the application.
Is this really correct, AttributesImpl is helper class in the documentation that doesn't actually exist? Neither is there a different class with this functionality to save an element's attributes for later use (outside the handler)?
Below is a working version of an Attributes deep copy utility function. It may be missing a few includes which I'm getting from other includes of my larger file. When I get the chance, I'll try making this a stand alone and update this answer. It still falls short of the Java version utility, due to inaccessible members of RefVectorOf class, because the wrapping class, the Attributes interface and VecAttributesImpl interface, do not provide access to them. https://xerces.apache.org/xerces-j/apiDocs/org/xml/sax/helpers/AttributesImpl.html
Last release of Xerces C/C++ is from 2016, so although marked status active, https://projects.apache.org/project.html?xerces-for_c++_xml_parser , really not so much. Can't vouch for libhunt site, but came up in quick google just now https://cpp.libhunt.com/xerces-c++-alternatives . One can see latest comment here, note use of the phrase "unless a security issue pops up or new committers appear to revive the project" https://issues.apache.org/jira/browse/XERCESC-2238?page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel&focusedCommentId=17571942#comment-17571942
Leaving the status of Xerces C/C++ as active is either a lie or a gross and negligent oversight. This page shows no major release since 2010. https://xerces.apache.org/news.html (C++ is listed below the Java project updates)
#include <xercesc/validators/common/GrammarResolver.hpp>
#include <xercesc/framework/XMLGrammarPool.hpp>
#include <xercesc/sax2/Attributes.hpp>
#include <xercesc/util/RefVectorOf.hpp>
#include "spdlog/spdlog.h"
#define tr XMLString::transcode
static spdlog::logger logger = getLog();
/*
* cloneAttributes
* Uses LocalName as key instead of QName and ignores URI and URI id, id inside RefVectorOf
* but inaccessible to wrapper VecAttributesImpl, and type defaults to CDATA
*/
VecAttributesImpl* cloneAttributes(VecAttributesImpl& attrs, bool useScanner=false){
// from XMLReaderFactory::CreateXMLReader line 49
MemoryManager* const memManager = XMLPlatformUtils::fgMemoryManager;
XMLScanner* scanner;
if(useScanner){
// from void SAX2XMLReaderImpl::initialize() line 124
GrammarResolver* grammarResolver = new (memManager) GrammarResolver(0, memManager); // line 127
// use of 0 from SAX2XMLReaderImpl.hpp line 74 default constructor, XMLGrammarPool* const gramPool = 0
XMLStringPool* URIStringPool = grammarResolver->getStringPool(); // line 128
scanner = XMLScannerResolver::getDefaultScanner(0, grammarResolver, memManager);
// line 42 of XMLScannerResolver::getDefaultScanner uses return new (manager) IGXMLScanner(valToAdopt, grammarResolver, manager);
scanner->setURIStringPool(URIStringPool);
}else{
scanner = NULL;
}
VecAttributesImpl* newAttrs = new VecAttributesImpl(); //VecAttributesImpl is not a vector, it's a wrapper around RefVectorOf
RefVectorOf<XMLAttr> * newRefVectorOf = new (memManager) RefVectorOf<XMLAttr> (32, false, memManager) ;
XMLSize_t atLen = attrs.getLength();
XMLSize_t i;
std::stringstream bruce;
XMLAttr* cpXMLAttr;
for(i = 0;i<atLen;i++){
//Ever QName != LocalName? when URI != ""? logger.debug(format("{}. QName LocalName URI type: {}, {}, {}, {}", i, tr(attrs.getQName(i)), tr(attrs.getLocalName(i)), tr(attrs.getURI(i)),tr(attrs.getType(i)))); // #suppress("Invalid arguments")
cpXMLAttr = new (memManager) XMLAttr
(
0, //URIId, 0 if reading file, but int is inaccessible from attrs, inside RefVectorOf XMLAttr, and getURI(i) returns an XMLCh*
attrs.getLocalName(i),
attrs.getValue(i)
);
if(logger.level() == spdlog::level::debug){
bruce << tr(attrs.getLocalName(i))<<" : "<<tr(attrs.getValue(i))<< " | ";
}
newRefVectorOf->addElement(cpXMLAttr);
}
logger.debug(bruce.str());
newRefVectorOf->size();
logger.debug(newRefVectorOf->size());
//The scanner can actually be set to NULL and the above scanner construction skipped if the VecAttributesImpl isn't scanning.
newAttrs->setVector(newRefVectorOf, newRefVectorOf->size(), scanner, false);
return newAttrs;
}

Trouble using M2Doc core generation API and SiriusServices

I am trying to generate documentation using the core generation API (as described here https://www.m2doc.org/ref-doc/3.1.0/index.html#core-generation-api). But I have the following error:
Couldn't find the 'isRepresentationDescriptionName()' service.
(It works fine when I use the genconf not programmatically).
I tried to add the SiriusServices using SiriusServiceConfigurator, but didn't manage to solve this issue.
Or maybe is it because I didn't add the SiriusSession option that refers to the .aird file?
I have looked at how new services are added in the newEnvironmentWithDefaultServices work but it is seems not applicable for SiriusServices.
final IQueryEnvironment queryEnvironment = org.eclipse.acceleo.query.runtime.Query
.newEnvironmentWithDefaultServices(null);
final Monitor monitor = new BasicMonitor.Printing(System.out);
final ResourceSet resourceSetForModels = session.getTransactionalEditingDomain().getResourceSet();
resourceSetForModels.createResource(modelUri);
try (DocumentTemplate template = M2DocUtils.parse(resourceSetForModels.getURIConverter(), templateURI,
queryEnvironment, classProvider, monitor)) {
final Map<String, Object> variable = new HashMap<>();
M2DocUtils.generate(template, queryEnvironment, variable, resourceSetForModels, outputURI, monitor);
...
Thanks
The Sirius related services need the Sirius Session. The Session is initialized using the SiriusSession option in the .genconf file. It should be set to an URI referencing the .aird file. In the class M2DocUtils you have several methods to create an IQueryEnvironment that take a Map of String where you can add the SiriusSession option, for instance:
M2DocUtils.getQueryEnvironment(ResourceSet, URI, Map<String, String>)
Note that your code needs to be ran inside of Eclipse, not a standalone java program.

Bing Map throws exception in 'Windows Runtime Component' project

First of all I want to apologize for the English.
I'am develop windows 8.1 store app. On C++/CX language. My solution contains several projects. One of projects has the 'Windows Runtime Component' type, and perform geocoding and reverse geocoding.
For a geocoding I use 'Bing Maps SDK for Windows 8.1 Store apps'(link).
Here's my algorithm:
void addressByLocation(double latitude, double longitude)
{
ResourceLoader^ loader = ref new ResourceLoader();
String^ credentials = loader->GetString("BingMapCredentials");
Location^ location = ref new Location(latitude, longitude);
ReverseGeocodeRequestOptions^ requestOptions = ref new ReverseGeocodeRequestOptions(location);
Map^ map = ref new Map();
map->Credentials = credentials;
SearchManager^ searchManager = map->SearchManager;
task<LocationDataResponse^> reverseGeocodeTask(searchManager->ReverseGeocodeAsync(requestOptions));
reverseGeocodeTask.then([=](LocationDataResponse^ response)
{
if (!response->HasError)
{
//
}
});
}
I've got the problem in this line:
Map^ map = ref new Map();
It always generates an exception with text:
"Platform::DisconnectedException ^ at memory location 0x0396DF80.
HRESULT:0x80010108 The object invoked has disconnected from its clients.
WinRT information: The object invoked has disconnected from its clients."
But I noticed something weird. If add project to the solution which contains UI(xaml), my code in this project works perfectly fine, without any exceptions.
Can somebody specify an error to me? Or give the explanation for this strange behavior.
There is probably other methods to perform geocoding for windows 8.1 store apps, which I don't know yet.
Thanks.

using dot net api how to find out cpu & memory utilization in vmware environment?

We have our vmware environment, and from that we are able to find out allocated memory & CPU through dot net API and we also want to find out its CPU and memory utilization (Max, Min, Avg).
But, we are not able to find any methods or properties in dot net api (VCloudSDK_V5_5)
So, I need dot net code sample to find out cpu & memory utilization in vmware environment.
I looked every where but i couldn't find.
Any C# Code Sample?
we are trying with this code:
http://vmware-gadget.googlecode.com/svn-history/r19/trunk/Vmware-Gadget/VmwareReader/VMPerfCounter.cs
We implemented an example with reference of VimService dll, but we are not able to connect through it.
We are getting Error: Request Failed with error message...
Error In the below method on line (_sic = _service.RetrieveServiceContent(_svcRef);)
System.Net.ServicePointManager.CertificatePolicy = new Program();
//Gets service contents
_svcRef.type = "ServiceInstance";
_svcRef.Value = "ServiceInstance";
// _service is VimService
_service = new VimService();
_service.Url = url;
_service.CookieContainer = new CookieContainer();
// _sic is ServiceContent
_sic = _service.RetrieveServiceContent(_svcRef); // Error at this line
_service.LoginCompleted += new LoginCompletedEventHandler(_service_LoginCompleted);
_session = _service.Login(_sic.sessionManager, usid, pwd, null);
But, there is no error message.
Can anyone help on this?
You should probably look at the vSphere Guest API documentation, this is where you can find the functions to do this type of monitoring. You can use the DllImport method to alias the methods documented in the vmGuestLib.dll. To learn how to access those methods from C# read Consuming Unmanaged DLL Functions and look at the documentation for DllImport.
Here is an example DllImport definition for the VMGuestLib_OpenHandle, VMGuestLib_GetMemActiveMB and VMGuestLib_CloseHandle functions:
using System.Runtime.InteropServices;
public enum VMGuestLibError {
VMGUESTLIB_ERROR_SUCCESS = 0,
VMGUESTLIB_ERROR_OTHER,
VMGUESTLIB_ERROR_NOT_RUNNING_IN_VM,
VMGUESTLIB_ERROR_NOT_ENABLED,
VMGUESTLIB_ERROR_NOT_AVAILABLE,
VMGUESTLIB_ERROR_NO_INFO,
VMGUESTLIB_ERROR_MEMORY,
VMGUESTLIB_ERROR_BUFFER_TOO_SMALL,
VMGUESTLIB_ERROR_INVALID_HANDLE,
VMGUESTLIB_ERROR_INVALID_ARG,
VMGUESTLIB_ERROR_UNSUPPORTED_VERSION
};
[DllImport("vmGuestLib.dll")] public static extern VMGuestLibError VMGuestLib_OpenHandle(ref IntPtr handle);
[DllImport("vmGuestLib.dll")] public static extern VMGuestLibError VMGuestLib_GetMemActiveMB(IntPtr handle, ref UInt32 memActiveMB);
[DllImport("vmGuestLib.dll")] public static extern VMGuestLibError VMGuestLib_CloseHandle(IntPtr handle);
Here are some decent API docs
I actually just began on a similar project myself, and I was able to use this code sample as a staring point. User Coffeetocode offers a very easy walkthrough on getting the .net api up and running.
From there, use the aforementioned API docs to find the various member names.
For example:
string provisioned_disk_space = "" + ((vm.Summary.Storage.Uncommitted + vm.Summary.Storage.Committed) / 1073741824);
string used_disk_space = "" + (vm.Summary.Storage.Committed / 1073741824);
string number_of_cpus = "" + vm.Summary.Config.NumCpu;
string total_ram = "" + (vm.Summary.Config.MemorySizeMB/1024);
And I think the members you're looking for are
VirtualMachine.Summary.QuickStats.GuestMemoryUsage;
VirtualMachine.Summary.QuickStats.OverallCpuUsage;

Autogenerate Stub code in C++ to access a webservice?

I'm chancing my arm with this question.
I'm looking for a tool which will avoid doing a lot of coding by autogenerating much of the code to access a webservice.
I'm trying to help out someone who uses a 4GL system which doesn't support webservices. However they can access a win32 dll - which looks like being the easiest solution. All they need to do is occasionally call a function on a web service and get a result back.
Its been a loooong time since I wrote any C++ and my attempts at doing this have just exposed how rusty I am.
I've played around with the gsoap2 toolkit and MS's svcutil.exe tool for auto generating code.
They do what they are supposed to do but, unlike the add reference tool in visual studio with vb.net or c#.net, these toolkits don't generate a stub access class that I managed to find.
Instead they generate individual function calls for each method and you have to pass them httpcontexts and a whole load of other stuff - something I don't really want to have to learn how to do for a one off.
What I want to do is mechanical:
Take the wsdl definition
AutoGenerate the Webservice access code (done - gsoap2)
Write/generate a small stub to open the webservice and authenticate using basic authentication and to return an instance of the webservice instance class.
publish as a dll
The idea being to have a single dll with a single function like
getws(username, password, url)
which will return an object which exposes the methods of the webservices - a stub, nothing clever.
I know I'm clutching at straws here but does anyone know of a tool/way to avoid all the mechanical work and to end up with a simple class which I can modify to add authentication.
The webservice has around 30 methods - and I have to expose them all, each has a collection of parameters. Writing a stub class to call the functions generated by gsoap2 would be a lot of typing and a nightmare to get to work/debug. Theres got to be a better way.
What I want to do is the equivalent of the .net code below - VS autogenerates the WS code. All I have to do is expose it in my class.
Private Shared oWs As WS.publicws = Nothing
Public Shared Function GetWS(ByVal Username As String, ByVal password As String, ByVal URL As String) As WS.publicws
Dim oBinding As New ServiceModel.BasicHttpBinding
If Not oWs Is Nothing Then Return oWs
Dim oEndPoint As New ServiceModel.EndpointAddress(URL)
oBinding.Security.Mode = ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly
oBinding.Security.Transport.Realm = ServiceModel.HttpClientCredentialType.Basic
oWS = New WS.publicws (oBinding, oEndPoint)
oWS.ClientCredentials.UserName.UserName = username
oWS.ClientCredentials.UserName.Password = password
Using scope = New ServiceModel.OperationContextScope(oWs.InnerChannel)
ServiceModel.OperationContext.Current.OutgoingMessageProperties(System.ServiceModel.Channels.HttpRequestMessageProperty.Name) = httpRequestProperty
End Using
Return oWs
End Function