Axis2 with complexTypes in Groovy - web-services

So I'm having a couple of ANT scripts using Groovy to process complex calculations normal ANT can't do (at least afaik). I'm trying to access an Axis2 web service using a SOAP-envelope via Groovy. The request and response is pretty simple, except for two complexType attributes (one in the request, one in the response).
The first thing I've stumbled across was Groovy Soap. It is quite easy to use, you simply instantiate a SoapClient and call the web service method. Unfortunately it cannot handle complexType attributes in the request, which I need:
Current Limitations:
....
4: Custom data types cannot be processed on client side when using the Groovy SOAP module with the current groovy-1.0 release.
Then I've read a lot about GroovyWS. I created my Grape config file in my user.home, javac and $GROOVY_HOME are available (basically did everything as described on the project quick guide page). Grape somehow retrieved Ivy, when I first started the script (I have no experience with Grape, but I suspect it's very similar to Maven).
Then started my simple script:
#Grab(group='org.codehaus.groovy.modules', module='groovyws',version='0.5.2')
import groovyx.net.ws.WSClient
proxy = new WSClient("http://127.0.0.1/axis2/services/ReleaseService?wsdl", this.class.classLoader)
proxy.initialize()
Unfortunately I couldn't even initialize the web client (without the Groovy Soap library in the classpath):
SEVERE: Could not compile java files for http://127.0.0.1/axis2/services/ReleaseService?wsdl.
Caught: java.lang.IllegalStateException: Unable to create JAXBContext for generated packages: Provider com.sun.xml.bind.v2.ContextFactory could not be instantiated: javax.xml.bind.JAXBException: "com.intershop.qa.tae.ws.xsd" doesnt contain ObjectFactory.class or jaxb.index java.lang.IllegalStateException: Unable to create JAXBContext for generated packages: Provider com.sun.xml.bind.v2.ContextFactory could not be instantiated [...]
With the Groovy Soap library (which seems to overload some of GroovyWS' functionality) in the classpath I've got:
Caught: java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL(Ljavax/wsdl/xml/WSDLLocator;Lorg/w3c/dom/Element;)Ljavax/wsdl/Definition; java.lang.NoSuchMethodError:
which looks very similar to the error I've got when I was using Groovy Soap in the first place.
So my question is: How can I communicate with an Axis2 web service using complexType parameters via ANT. I'm not limited to Groovy only, but for deployment reasons (~50 VM snapshots) I want something simple. A Java client worked, but since the deployment is quite some effort (especially if I want to change stuff in the future) I need something which is closer to ANT and easier to deploy.
Thanks in advance for suggestions of other technologies or fix ideas for my GroovyWS implementation.

I finally came up with a solution: groovy-wslight actually solved my problem and was finally able to deploy easily and access the web service without problems/exceptions.
The script:
#Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='0.7.1')
import wslite.soap.*
def client = new SOAPClient("http://127.0.0.1/axis2/services/ReleaseService")
def response = client.send {
body {
myFunction(xmlns:"http://my.namespace.com") {
stringParameter("6.3.0.0")
status() { value("default") }
mode() { value("full") }
}
}
}
Where status and mode are complexTypes which consist of one "value" attribute (as an example).
println(response.myFunctionResponse.return)
gives me the object returned by the web service. Of course the names of the tokens depend on the WSDL. In my case the response of the request is called myFunctionResponse, which has a field name="return" and gives me a complexType object. The fields of the object can be retrieved according to the names given in the WSDL:
println(response.myFunctionResponse.return.location) // gives me the field value of the field "location" for my complexType

I had a similar problem when using JDK 1.7. Switching to JDK 1.6 solved it for me.

Related

How do we use uri endpoint mapping in spring integration

I am trying to configure spring integration using annotation. Instead of payloadqnameendpoint mapping I would like to use URI endpoint mapping. I found many examples with default URI endpoint but I required an annotation example without default end point.
Let's take a look to the AnnotationActionEndpointMapping support in the Spring WS! As you see it is based on the division between POJO methods and annotations on the them. The POJO is a main word there. This kind of framework magic allow us to separate low-level protocol from end-application business logic. From other side Spring Integration's AbstractWebServiceInboundGateway implements MessageEndpoint meaning that the whole SOAP hard work will be done in this implementation. It isn't a POJO.
Of course this topic is a different story, but you should understand from here that MessageEndpoint and MethodEndpoint work a bit different. At least they do messaging logic from different levels of SOAP request.
So, we really can't map <int-ws:inbound-gateway> with #Action or similar just because it is a whole SOAP endpoint already.
From other side, having AnnotationActionEndpointMapping from Java config, you can fully get rid of <int-ws:inbound-gateway> and configure your Endpoint to delegate desired #Action to the methods of #MessagingGateway. And it will work beucase the hard SOAP work has been done already by Spring WS framework.
I don't know you that this code will work, but you can check or let me know and I'll test it and come back to again:
#Endpoint
#MessagingGateway
public interface OrderEndpoint {
#Action("http://samples/RequestOrder")
#Gateway(requestChannel = "getOrderChannel")
Order getOrder(OrderRequest orderRequest);
#Action("http://samples/CreateOrder")
#Gateway(requestChannel = "createOrderChannel")
void order(Order order);
}

Consuming web services with claims-based authentication - SoapServerException

We have an application that periodically pulls data from a SharePoint list and integrates with another application. We've been using it for more than a year without a problem. Recently, however, we switched our farm to use claims-based authentication... and there went the app.
My code, at a high level, does the following:
SPWebRefs.Lists spl = new SPWebRefs.Lists();
spl.Credentials = System.Net.CredentialCache.DefaultCredentials;
//Build request here
XmlNode listItems = spl.GetListItems("My list", view, query, viewFields, null, queryOptions, null);
I get an "Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown" exception right there.
I'm looking through Fiddler, and I get the 401 challenge, quickly followed by a 200 response, which I assume means I'm in. But then I get a 500 error as soon as the GetListItems method is invoked.
I've tried this against a 2010 instance as well as a 2013 farm that we're getting ready to deploy. Same situation.
I'm using the 4.0 Framework at this point, but I've considered testing it out against the 4.5 Framework, which includes some new APIs for claims authentication. Would that make any difference?
Any thoughts would be greatly appreciated. Thanks so much in advance!
You must call SharePoint's Authentication WebService first. You will get a cookie from it, which you can pass to the Lists WebService.
See a sample here: http://www.tonytestasworld.com/post/2009/06/04/How-To-Authenticate-and-Use-SharePoint-Web-Services-in-an-FBA-SharePoint-site.aspx

HTTP 404 error while invoking a local webservice in .NET MVC4

I am trying to learn webservices in .NET mvc4. I tried creating a new Internet application and adding a Web service (asmx) to the project.
By default, the VS adds a "HelloWorld" Webservice. When I try to run it in the browser, I do get the list of operations, service description(WSDL) and the details of the HellowWorld operation. However, when I try invoking the webservice, it gives the following error :
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its
dependencies) could have been removed, had its name changed, or is
temporarily unavailable. Please review the following URL and make
sure that it is spelled correctly.
I might be missing some basic step/setting I guess. Could some body help please. Thanks.
I got the answer from one of my colleagues :) .
When we invoke the service, the MVC tries to resolve the path as specified in RegisterRoutes.
Hence it tries to find a controller with that name and a method with the name same as that of the operation inside that controller. The resolution, ignore the paths with .asmx extension. You can do that by adding the following line in RouteConfig.cs :
routes.IgnoreRoute("{*x}", new { x = #".*\.asmx(/.*)?" });
and it worked. Thanks.

How to use Intersystem's session within web services

I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.

Deploying a SharePoint WebPart with its Web Service Reference

I'm trying to built a SharePoint Web Part that has as part of it a service reference to Another SharePoint server that I need to call from within vb code. However when I try to call the remote web service for the first time, I get the following in the log:
Could not find default endpoint element that references contract 'ListReference.ListsSoap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element. at System.ServiceModel.Description.ConfigLoader.LoadChannelBehaviors(ServiceEndpoint serviceEndpoint, String configurationName)
at System.ServiceModel.ChannelFactory.ApplyConfiguration(String configurationName)
at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
at System.ServiceModel.ChannelFactory1..ctor(String endpointConfigurationName, EndpointAddress remoteAddress)
at System.ServiceModel.EndpointTrait1.CreateSimplexFactory()
at System.ServiceModel.ClientBase1.CreateChannelFactoryRef(EndpointTrait1 endpointTrait)
at System.ServiceModel.ClientBase1.InitializeChannelFactoryRef()
at System.ServiceModel.ClientBase1..ctor()
at VSeWSS.ChangeRequestWorkflow.ChangeRequest.SubmitForm(Object sender, EventArgs e)
What is the proper way to deploy a Web Part with a Service Reference, could I be doing something wrong? Thanks!
You need to add the endpoint configuration into the web.config of the SharePoint site that is consuming the webservice.
I found this question that solved my problem.
Basically, I just needed to create a BasicHttpBinding object and populate its properties with the ones the SVC generator made in my app.config.
WCF Configuration without a config file
Actually I solved my problem. My application has many projects, and the config file was in the project calling the WebService, but it seems it has to be in the starting project...
Hm, if I'm understanding what you're asking correctly, I'm doing that. I just added the webservice from one of the correct endpoints to the project in VS, then before I call it in my actual code, I get the URL I want to connect to with this call from the hierarchical object store from Codeplex, then set the Url property. So:
MyService srv = new MyService();
srv.Url = SPContext.Current.Web.Properties["serviceurl"];
Its working like that fine.
hth.