Consuming web service using wsdl in Domino - lotus-domino

We use web service Consumers\ Providors quite a bit in our application, both LS and java design elements.
I have a web service (wcf) wsdl that I am trying to import into a LotusScript Web Consumer design element and when saving I am getting the following error:
Not a member: INVOKE
...on line indicated below.
Function GetCopyDestinations(service As XSD_STRING, ocsCode As XSD_STRING, Fault1 As InteropErrorInfoStruct_n1) As ArrayOfInteropMessageDestination_n1
Set GetCopyDestinations = Service.Invoke("GetCopyDestinations", service, ocsCode, Fault1) <<<<=====ERROR ON THIS LINE
End Function
I take this to be that the wsdl --> Web service classes transformer does not like the structure of the wsdl...? I work with the developer who is creating the service we are consuming, so I can get the structure changed, but, from error above, I am not really sure where to start. I assume this means it does not think the Object Service has the method .Invoke().
I've had a look in the file: lsxsd.lss, which LS web service elements include. The "stub" class in the LS web service inherits from PortTypeBase which is in the lsxsd.lss file, PortTypeBase does not have an invoke() method, so I am not quite sure how\ where this method is inherited from. Other LS web services we use successfully, have exactly the same structure, so it would appear this is correct.
The only thing I can think of is to get my colleague to strip the wsdl back to bare bones, then add 1 method, see if it imports, add another, see if it imports, etc.
As a side note, I tried to import the ws into a java consumer, it imports fine. I then construct the stub in exactly the same way I do for all our other java consumer services, which it appears to do successfully. When I run my test harness agent, the stub is created, but it errors when trying to run any of the actions:
java.rmi.RemoteException: No operation description was found for the service
I take this to mean, it can't find the action in the wsdl file, or something similar...? The end point url and PortName appear correct if I output as it is running.
As a side note to this...the service I am attempting to consume above, we have a version working in production now, it is in a LS web consumer, but new one has had new actions added. For a sanity check, I then imported the "live" wsdl...which we know works...into a LS web consumer design element and run a test harness agent, works as expected...good. Then I imported "live" wsdl into a java consumer design element. When running the service, we get the same error...!?
java.rmi.RemoteException: No operation description was found for the service
So now I'm really, really confused. I would like to post the wsdl here, but I think NDA etc., will not allow me, but if it's any help, I am constructing the stub as follows:
ITKInteropV10Stub stub = (ITKInteropV10Stub) new ITKInteropServiceV10_ServiceLocator().getITKInteropV10();
This is a similar stub constructor pattern to all other java web services I consume.
I have been googling\ searching for a couple of days now, searching for errors listed above, I'm really struggling to find a way forward.
Ideally, solving the import in the LS web consumer would work best, since back end logic is currently in LS Script libs which will access this service. If I get it working in java, that's fine as well, it just makes the retrieval of data from the Web Service into the LS libs a bit more complex.
Any comments\ suggestion would be welcomed with open arms!
Regards
Nick

LotusScript is not case sensitive. You have a variable called "service" of XSD_STRING and another object called "Service" which looks like it might be a NotesWebServiceEngine object? (internal LS object).

Related

How do I create and Axis2 client

I've been given a WDSL file and have to create a web service client using axis2. I've been able to generate the CallbackHandler and Stub using WSDL2java. I've tried following this tutorial to create the Client http://briansjavablog.blogspot.com.au/2013/01/axis2-web-service-client-tutorial.html
I'm not sure if I implemented the client properly. It runs, but I'm not sure how you view any output results. I've never dealt with web services before. The Stub file that was generated contains so much code, how am I supposed to know what I should be calling? All tutorials I've found give example Clients, but I want to know what I need to look at to create my own.
If anyone has any advice or links to creating clients that are easy to understand, it would be appreciated.
I think that this probably went un-answered for a while due to the fact that the question is not clear and you probably need an introduction to Web Services and SOAP in general. If you are given the WSDL (or can pull it from a URL out there somewhere) then you are using the Web Service as a client - you have (from the post) already created the stub for client use. You simply need to use it. You are sending a request to the server (Web Service) and sending it the data that it requires (as the SOAP parameters that are laid out in the Web Service schema). Based on this SOAP request you will get a response. Your stubs that are created for the client act as the invocation and response points for your client.
So your question as to how do you test it: you decide what to do with the response as this is what you are coding into the client.
And about creating your own Web Service - you would need to start with a schema (often times you write your objects/data and the functions that you want them to perform and tools (like Axis2) will generate the server code (for Web Services and SOAP transport) on top of this.
So in your question, I think that you need to a) check out some Web Services books/online tutorials to figure out what it is, b) code your client to display the results and stuff - and just make sure that you are actually sending and getting responses from the Web Service, and c) also see what it would take to create your own Web Service (for whatever purpose you are planning the service to be established for, before creating your own.
Effectively I think that you just need to get your feet wet with Web Services in the first place. And the tutorial that you pointed out ( http://briansjavablog.blogspot.com.au/2013/01/axis2-web-service-client-tutorial.html) is excellent for anyone looking to get a web services client started - thanks for posting that.

Accessing .NET WCF services from Android

I have a .NET WCF service (not a web service) with many methods, some accepting and returning complex data types. I use these services from my Windows Phone 7 apps. It all works great and it's easy.
Now I'm evaluating the feasibility of porting some of my apps to Android, but I can't figure out how to invoke my WCF services from an Android client.
I have a working example I found in Invoke webservices from Android.
But this looks to be accessing a "Web Service", not a WCF Service.
My service is at http://www.deanblakely.com/Service2.svc, and it contains a simple method named "SimpleTest" that just returns the string "Alive".
Using the code in the linked article, I put http://www.deanblakely.com/Service2.svc in SOAP_ADDRESS and SimpleTest in OPERATION_NAME. But I have no idea what to put in SOAP_ACTION and WSDL_TARGET_NAMESPACE. I don't even know if this approach is valid.
In .NET, Visual Studio builds us a "Service Reference" and everything just works.
I also don't understand the following two lines of code...
httpTransport.call(SOAP_ACTION, envelope);
Object response = envelope.getResponse();
With WCF services, the call is async so we make the call to SimpleTestAsync and leave a callback for the async return. These two lines of code appear to be synchronous, no?
When communicating with WCF services from a non-Windows client, you are basically treating it as an XML Web Service. If you configure your WCF service to use a basicHttp binding, it will act just like any other web service, as far as Java is concerned.
Normally, to call a WCF service from Java, you use wsimport to create a custom set of proxy and data classes, similar to the way a service reference works. Android doesn't have all the libraries needed for those classes, but I did find this URL:
http://code.google.com/p/androidclientgenerator-wsimport/
That is a proxy class generator specifically for Android. Instead of using the code on that web page, you may want to download this proxy generator; you simply have to pass it the URL to your service's WSDL page and it will create typed Java classes for everything. If you have complex types being passed back and forth, this is probably a much better option.
However, if you want to continue with the sample code, you'll need to fill in those variables you've identified. The variables are just the typical parameters for a SOAP envelope. These are defined in the WSDL for your service, and are primarily based on the namespace that you have defined for your service. (They are largely independent of the actual URL that your service lives at, with one exception). You specify the namespace in the WCF service contract:
[ServiceContract(Namespace = "http://namespaces.deanblakely.com/wcf")]
Note that the namespace URL doesn't need to point to a real resource, though frequently they do. It doesn't even need to be a URL (I often use urns); it just needs to be a unique string of characters. For now lets assume you assigned the above namespace to your service.
The WSDL_TARGET_NAMESPACE is just the namespace, exactly as above. The OPERATION_NAME is the name of the method you want to call, for example SimpleTest. The SOAP_ACTION is the combination of namespace an operation; in your case that would be http://namespaces.deanblakely.com/wcf/SimpleTest. In your WSDL you would see this described in an operation tag:
<wsdl:operation name="SimpleTest">
<soap:operation soapAction="http://namespaces.deanblakely.com/wcf/SimpleTest" style="document"/>
The SOAP_ADDRESS is the only one that actually points to your service file, e.g. http://www.deanblakely.com/Service2.svc.
Hopefully that will get you started calling in to your web service; if not feel free to stop back and get more assistance.
EDIT: Missed the part about async calls.
Yes, the method described on that web page is synchronous. WCF service methods are synchronous by default, with the option to include asynchronous calls when generating a service reference in Visual Studio. wsimport generates async-ready proxies, so using the Android client generate may also help you out in this area.

WCF service reference update

Right now we have around 5 service reference added to our projects in a single solution.
I am force to add service reference even for projects having indirect dependencies calling service methods. Is there a way to get around for this situation.
For every single change in the service method, I have to update every single service reference to effect those changes. It is very time consuming too.
I am just wondering, is there any way i cam manage these things globally by making single service reference for the whole solution.
help appreciated.....:)
You should be able to use the svcutil.exe command line utility to generate a single service file (.cs file for example) from multiple service URL's. The nice thing about this is that you can share clinet-side DTO's and message types accross services if they have the same schema.
SvcUtil Reference: http://msdn.microsoft.com/en-us/library/aa347733.aspx
In regards to the requirement of adding the service reference to projects with indirect dependencies. You should probably not consume the service reference and related types directly from your service client. To improve maintainability and adaptability, you should wrap your service reference(s) in a facade. The facade would map between local types and service reference types, and give you much more agility in terms of responding to service changes. You would then only need to have the service references in a single location (preferably an independent project) along with the facade. The facade, which should change infrequently, will buffer you from the issues you are currently having with your service references.
You won't be able to get a single reference if you have multiple service, unfortunately.I stand corrected - see jrista's answer.
What you could do is create and update the service references automatically: instead of adding them manually in Visual Studio using Add Service Reference check out the svcutil.exe command line tool which will basically do the same thing.
Since it's a command line tool, you can have it run as e.g. part of your continuous build and update the necessary proxy client files every time you build the app.
Check out these additional links for tutorials and explanations about the details of using svcutil.exe:
http://msdn.microsoft.com/en-us/library/ms734712.aspx
http://asadsiddiqi.wordpress.com/2008/10/25/how-to-generate-wcf-client-proxy-class-using-svcutilexe/
http://www.xvpj.net/2008/03/08/wcf-step-by-step-tutorial/
Marc

WCF ChannelFactory vs generating proxy

Just wondering under what circumstances would you prefer to generate a proxy from a WCF service when you can just invoke calls using the ChannelFactory?
This way you won't have to generate a proxy and worry about regenerating a proxy when the server is updated?
Thanks
There are 3 basic ways to create a WCF client:
Let Visual Studio generate your proxy. This auto generates code that connects to the service by reading the WSDL. If the service changes for any reason you have to regenerate it. The big advantage of this is that it is easy to set up - VS has a wizard and it's all automatic. The disadvantage is that you're relying on VS to do all the hard work for you, and so you lose control.
Use ChannelFactory with a known interface. This relies on you having local interfaces that describe the service (the service contract). The big advantage is that can manage change much more easily - you still have to recompile and fix changes, but now you're not regenerating code, you're referencing the new interfaces. Commonly this is used when you control both server and client as both can be much more easily mocked for unit testing. However the interfaces can be written for any service, even REST ones - take a look at this Twitter API.
Write your own proxy - this is fairly easy to do, especially for REST services, using the HttpClient or WebClient. This gives you the most fine grain control, but at the cost of lots of service API being in strings. For instance: var content = new HttpClient().Get("http://yoursite.com/resource/id").Content; - if the details of the API change you won't encounter an error until runtime.
Personally I've never liked option 1 - relying on the auto generated code is messy and loses too much control. Plus it often creates serialisation issues - I end up with two identical classes (one in the server code, one auto generated) which can be tided up but is a pain.
Option 2 should be perfect, but Channels are a little too limiting - for instance they completely lose the content of HTTP errors. That said having interfaces that describe the service is much easier to code with and maintain.
I use ChannelFactory along with MetadataResolver.Resolve method. Client configuration is a bother, so I get my ServiceEndpoint from the server.
When you use ChannelFactory(Of T), T is either the original contract that you can get from a reference in you project or a generated contract instance. In some projects, I generated the code from a Service Reference because I could not add a reference to the contract dll. You can even generate an asynch contract with the service reference and use that contract interface with ChannelFactory.
The main point of using ChannelFactory for me was to get rid of the WCF client config information. In the sample code below, you can see how to achieve a WCF client without config.
Dim fixedAddress = "net.tcp://server/service.svc/mex"
Dim availableBindings = MetadataResolver.Resolve(GetType(ContractAssembly.IContractName), New EndpointAddress(fixedAddress))
factoryService = New ChannelFactory(Of ContractAssembly.IContractName)(availableBindings(0))
accesService = factoryService.CreateChannel()
In my final project, the availableBindings are checked to use net.tcp or net.pipe if available. That way, I can use the best available binding for my needs. I only rely on the fact that a metadata endpoint exist on the server.
I hope this helps
BTW, this is done using .NET 3.5. However it does work also with 4.0.
Well in order to use ChannelFactory<T> you must be willing to share contract assemblies between the service and the client. If this is okay with you then ChannelFactory<T> can save you some time.
The proxy will build async functions for which is kind of nice.
My answer is a kind of summary of Keith's and Andrew Hare's answers.
If you do not control server, but have only WSDL/URL- generate proxy using Visual Studio or svcutil. (Note that Visual Studio sometimes failed, when svcutil works better).
When you control both server and client, share interfaces/contracts and call ChannelFactory
.
It's not just a matter of time saved. Using the WSDL generated proxy is dangerous because if you forget to update the service reference you can leave the solution in an inconsistent state. Everything compiles but the service contract is broken. I definetly suggest to use a ChannelFactory whenever possible, you make your life much easier.
A possible alternative could be to write a prebuild script that calls the SVCUtil utility to create the proxy everytime you build your project, but anyway ChannelFactory is much more neat and elegant.

How to unit test a WCF server/client?

I have a WCF server that is a library assembly. (I am writing it so I can mock the level below it) It is called var a client helper class that is in a different assembly. As the data that is transferred is complex and the server has to send call-backs to the clients I wish to test the WCF code in isolation.
(I am only interested in the TCP channel or NamePipe channel)
I do not wish to mock WCF, as the risk I am trying to control is my usage of WCF.
It there a easy way to
Load my WCF server into a different app domain
(I could load the WCF server into the main app domain, but then I it harder to prove that the objects were serialized correctly rather than just pointer moved about.)
Setup all the WCF config so the client class can call it (most likely named pipes or TCP)
And use it in some nunit test
I rather not have my unit tests depending on config file.
I expect (hope) that there are some util classes for setting up WCF unit test that I can just pass the type of my server class to and will give me back a client factory that connects to the server.
Am I going about this the wrong way, e.g there a better way of testing my communication layer and usage of WCF?
It is by far the easiest approach if you spin up the service in-proc, because then you don't need to write a lot of complex synchronization code to determine when the service is running and when it isn't.
Don't worry about pointers being passed around - they won't (unless you choose the new in-proc binding in WCF 4). It's the binding that determines how and if objects are serialized. Named pipes are excellent for this purpose.
I always spin up a new ServiceHost in each test case inside a using statement, which effectively guarantees that the host is running before calls are being made to it, and that it is properly closed after each test. This last part is important because it ensures test independence.
You may also want to look at a series of blog posts I wrote about a very similar subject.
You can use SOA Cleaner for testing your WCF. Take a look at http://xyrow.com
no installation is needed. It's not unit testing, but it can be very helpful (you can have it run on your build, as it supports command line too).