WSClient soap client in grails/groovy - grails

I have a few problems with the cxf + WSClient in soap.
I am writing a small tool in grails that must make SOAP calls to an existing service.
WSClient (groovyws-0.5.3-20100521.062225-1.jar) seemed like the perfect solution to my problem.
However when i tried to implement a call to one of the actions i get two problems.
Problem #1 NullPointerException when making a call to some of the actions.
I have tracked down the code that is throwing the exception inside of
AbstractCXFWSClient.invokeMethod(String methodName, Object args)
if (!operationToBeInvoked.isUnwrapped()){
//Operation uses document literal wrapped style.
inputMessageInfo = operationToBeInvoked.getWrappedOperation().getInput();
} else {
inputMessageInfo = operationToBeInvoked.getUnwrappedOperation().getInput();
}
specifically operationToBeInvoked.getWrappedOperation() I have isolated the code in a unit test and find that both operationToBeInvoked.getWrappedOperation() and operationToBeInvoked.getWrappedOperation() result in null objects. I have tried to figure out what is causing it however i think i have gotten to the end of my knowledge.
Problem #2 WSClient.create(String classname) is eating a ClassNotFoundException (and then throwing a NullPointerException)
Basicly when I make the following call
def event = client.create("com.mypackage.MyBean");
Same bean that i can see by browsing the services from the browser.
<xs:complexType name="myBean">
<xs:sequence>
<xs:element minOccurs="0" name="id" type="xs:long"/>
<xs:element maxOccurs="unbounded" minOccurs="0" name="facets" nillable="true" type="tns:beanBean"/>
<xs:element minOccurs="0" name="sortId" type="xs:string"/>
<xs:element minOccurs="0" name="itemId" type="xs:string"/>
<xs:element minOccurs="0" name="preview" type="xs:boolean"/>
</xs:sequence>
</xs:complexType>
I get a NPE. When i drill down to figure out why i get an NPE, I find that its because the classloader on the WSClient can't find "com.mypackage.MyBean" eats the ClassNotFoundException and then inevitably throws an NPE.
Edit: Should I be using a different client the WSClient/cxf ? I really wanted to avoid having to roll my own.....

Basicly I didn't find the answer. I basicly was forced to uninstall the two plugins and cxf and not using the groovy WSClient.
What i did was install the ws-client plugin for grails and that worked.
http://www.grails.org/plugin/ws-client

Try to remove the jaxen's jar in .grails lib cxf plugin folder in your project. It should solve your problem.

Related

Biztalk 2010 : Not able to Query SalesForece through Enterprise WSDL.Illegal Header issue

I am implementing BizTalk 2010 Saleforce integration where I am purely using enterprise wsdl for calling its methods. No C# code for any operation.
I am successfully able to call login method and getting result back with all details. Now at the subsequent request where I am calling query method which does not take additional parameter for taking header. It is only taking query string as parameter shown below.
<element name='query'>
<complexType>
<sequence>
<element name='queryString' type='string' />
</sequence>
</complexType>
</element>
Now the problem is when I am calling this method it is giving me error for "Invalid Session and Illegal Session Header" because no header getting passed.
Alternative that I tried is constructing message and passing header with session id (taking from login result) explicitly as shown below.
Option 1.
varXMLDocument = new System.Xml.XmlDocument();
varXMLDocument.LoadXml("<ns0:Envelope xmlns:ns0='http://QuerySFDCVIAWSDL.QueryRequestSchema'><Body><query><queryString>SELECT "some fields xyz..." FROM Quote</queryString></query></Body></ns0:Envelope>");
msgSendQryToSalesforce = varXMLDocument;
//Setting Header
msgSendQryToSalesforce(WCF.Headers) = "<ns0:SessionHeader xmlns:ns0=\"urn:enterprise.soap.sforce.com\"><ns0:sessionId>" + SessionId + "</ns0:sessionId></ns0:SessionHeader>";
Option 2.
//Creating session header in same xml.
varXMLDocument.LoadXml("<ns0:Envelope xmlns:ns0='http://QuerySFDCVIAWSDL.QueryRequestSchema'><Header><SessionHeader><sessionId>"+SessionId+"</sessionId></SessionHeader></Header><Body><query><queryString>SELECT "some fields xyz..." FROM Quote</queryString></query></Body></ns0:Envelope>");
The problem with these approach is SessionHeader getting removed at runtime and only querystring getting passed to SFDC. Hence getting same result "Invalid Session and Illegal Session Header".
//Request From Orchestration Debugger where there is no session header after been passed explicitly, it is only taking querystring.
//Final Request
<ns0:query xmlns:ns1="urn:sobject.enterprise.soap.sforce.com" xmlns:ns0="urn:enterprise.soap.sforce.com"><ns0:queryString>SELECT "some fields xyz..." FROM Quote</ns0:queryString></ns0:query>
Can anybody please help me and assist me in finding out the appropriate solution so that at all subsequent request have session ids passed in session header.
From SoapUI tool when I am passing same xml with session header it is getting me result back.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:enterprise.soap.sforce.com">
<soapenv:Header>
<urn:SessionHeader> <urn:sessionId>some id.......</urn:sessionId>
</urn:SessionHeader>
</soapenv:Header>
<soapenv:Body>
<urn:query>
<urn:queryString>Select "some fields xyz..." from Quote</urn:queryString>
</urn:query>
</soapenv:Body>
</soapenv:Envelope>
Not able to understand why from BizTalk it is not working.
Just FYI my queryRequestSchema
Just FYI my queryRequestSchema
<?xml version="1.0"?>
<xs:schema targetNamespace="http://QuerySFDCVIAWSDL.QueryRequestSchema" xmlns="http://QuerySFDCVIAWSDL.QueryRequestSchema" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Envelope">
<xs:complexType>
<xs:sequence>
<xs:element name="Header">
<xs:complexType>
<xs:sequence>
<xs:element name="SessionHeader">
<xs:complexType>
<xs:sequence>
<xs:element name="sessionId" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Body">
<xs:complexType>
<xs:sequence>
<xs:element name="query">
<xs:complexType>
<xs:sequence>
<xs:element name="queryString" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Thanks in Advance.
Use the (WCF.CustomOutboundHeaders) context property.
Replace this line:
//Setting Header
msgSendQryToSalesforce(WCF.Headers) = "<ns0:SessionHeader xmlns:ns0=\"urn:enterprise.soap.sforce.com\"><ns0:sessionId>" + SessionId + "</ns0:sessionId></ns0:SessionHeader>";
With this
// Setting Header
msgSendQryToSalesforce(WCF.OutboundCustomHeaders) = "<ns0:SessionHeader xmlns:ns0=\"urn:enterprise.soap.sforce.com\"><ns0:sessionId>" + SessionId + "</ns0:sessionId></ns0:SessionHeader>";
If you're using a utilities class, it might be a good idea to store that header template in a public const string variable, or write a method to format it for you - assuming you'll be sending multiple messages to Salesforce, you'll be able to reuse it more easily:
msgSendQryToSalesforce(WCF.OutboundCustomHeaders) = Utilities.GetSalesforceHeader(SessionId);
and in your utilities class, have a method like
public static string GetSalesforceHeader(string sessionId)
{
return "<ns0:SessionHeader xmlns:ns0=\"urn:enterprise.soap.sforce.com\"><ns0:sessionId>" + sessionId + "</ns0:sessionId></ns0:SessionHeader>";
}
More information on setting SOAP headers in Orchestrations:
https://msdn.microsoft.com/en-us/library/bb246026.aspx (but note that you don't actually have to use an XmlDocument for this); this applies to 2010 even though it says its for 2013.

Modifying Wsdl2Apex Generated Classes to Handle xs:extension and imported namespaces

I am having trouble with wsdl2apex code generation, mainly due to the use of xs:import namespace and xs:extension in my WSDL.
In particular, I am seeing the error System.CalloutException: Web service callout failed: Unable to parse callout response. Apex type not found for element . . .. The raw SOAP response returned by the web service looks as I would expect.
I would like to modify the generated Apex classes to work around this issue, as server-side changes to the web service is not an option.
The SOAP response looks like the below:
<ns:getAccountsResponse>
<ns:return xsi:type="ax1:AccountReturn">
<ax2:successful>true</ax2:successful>
<ax2:transactionId>1000</ax2:transactionId>
<ax1:Accounts xsi:type="ax1:Account">
And the WSDL looks like this for the ax1 target namespace:
<xs:complexType name="AccountReturn">
<xs:complexContent>
<xs:extension base="ax100:BaseReturnObject">
<xs:sequence>
<xs:element maxOccurs="unbounded" minOccurs="0" name="Accounts" nillable="true" type="ax1:Account"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
And for the ax2 target namespace:
<xs:complexType name="BaseReturnObject">
<xs:sequence>
<xs:element minOccurs="0" name="successful" type="xs:boolean"/>
<xs:element minOccurs="0" name="transactionId" nillable="true" type="xs:integer"/>
</xs:sequence>
</xs:complexType>
The generated Apex Class which maps to AccountReturn only contains the fields for Accounts in ax1, but not the BaseReturnObject fields in ax2, since the wsdl2apex generation does not respect the use of xs:extension or the importing of namespaces (based on my research).
Is there anyway to modify the Apex Class to make this work? I tried adding the fields from BaseReturnObject to AccountReturn, and modifying field_order_type_info. However, it appears that apex_schema_type_info can only point to one namespace, and this may be the reason that the parsing of the callout response is still failing.
I've built a tool for automating the creation of the Apex classes. It includes support for xs:extension and xs:import (among other things).
In the case of an ex:extension, the tool will pull the required fields from the base class into the subclass and correctly configure the _type_info members.
You can get it for free - FuseIT SFDC Explorer. Currently in only runs directly in Windows. I've had reports of people running it successfully using Wine. (Disclosure: I work for the company that releases this tool).
Incidentally, the salesforce.stackexchange.com site is a great place to ask Salesforce specific questions.

Duplicate attributes generated in WSDL using #XmlMimeType() on CXF, Why?

I've developed a CXF web services with MTOM enabled. I've added an annotation to my DTO to tell JAXB the field candidate for MTOM optimization:
#XmlType
public class FileDTO {
private String Name;
private String FileType;
#XmlMimeType("application/octet-stream")
private DataHandler Dfile;
...
when deploying the webservice, the DTO definition in the WSDL looks like:
<xs:complexType name="fileDTO">
<xs:sequence>
<xs:element name="Dfile" type="xs:base64Binary" minOccurs="0" xmime:expectedContentTypes="application/octet-stream"/>
<xs:element name="dfile" type="xs:base64Binary" minOccurs="0"/>
<xs:element name="fileType" type="xs:string" minOccurs="0"/>
<xs:element name="name" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
somehow the private member DFile seems to be DUPLICATED !!
why does it happen?
when I try to generate a java client with
wsdl2java -client d:\service.wsdl
I get the following error:
WSDLToJava Error: d:\service.wsdl [26,1]: Two declarations cause a collision in the ObjectFactory class.
Thank you !!
By default JAXB treats all public properties as being mapped. Since you be annotated a field and its name doesn't match the property you get a second mapping.
Solution
Move the annotation from the field to the property (getter).
Specify #XmlAceesorType(XmlAccessType.FIELD) on the class so that JAXB bases the mappings on the fields.

Is this wsdl fragment illegal?

I'm scratching my head. This WSDL is generated by CXF. It liked the input WSDL and schema files but SOAPUI is complaining when I try to create a test project. The whole wsdl is too long but here is the part that matches up with the error messages:
<xs:complexType name="RelatedResourcesType">
<xs:sequence>
<xs:element minOccurs="0" name="RelatedResource">
<xs:complexType>
<xs:complexContent>
<xs:extension base="tns:CompoundResourceIdentifierType">
<xs:sequence>
<xs:element minOccurs="0" name="link">
<xs:complexType>
<xs:sequence/>
<xs:attribute ref="ns3:type" xmlns:ns3="http://www.w3.org/1999/xlink"/>
<xs:attribute ref="ns4:href" use="required" xmlns:ns4="http://www.w3.org/1999/xlink"/>
<xs:attribute ref="ns5:role" xmlns:ns5="http://www.w3.org/1999/xlink"/>
<xs:attribute ref="ns6:title" xmlns:ns6="http://www.w3.org/1999/xlink"/>
<xs:attribute ref="ns7:label" xmlns:ns7="http://www.w3.org/1999/xlink"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
...
...
Error: Could not find attribute 'type#http://www.w3.org/1999/xlink' Do you mean to refer to the attribute named type#http://dws.sec?
Error: attribute 'href#http://www.w3.org/1999/xlink' not found
Error: Could not find attribute 'role#http://www.w3.org/1999/xlink' Do you mean to refer to the attribute named role#http://www.w3.org/2003/05/soap-envelope?
Error: Could not find attribute 'title#http://www.w3.org/1999/xlink' Do you mean to refer to the attribute named title#http://metadata.esd.com/?
Error: Could not find attribute 'label#http://www.w3.org/1999/xlink' Do you mean to refer to the attribute named title#http://metadata.esd.com/?
So these should all be coming from the xlink definition and I'm not sure why it's not seeing it. Any thoughts? or suggestions for what to try next?
I had success making changes that allowed Visual Studio 2008 to retrieve the WSDL from the server and to generate code. The steps were
1) Configure CXF to display the original WSDL files instead of its generated version
2) Change imported schemas to be inline in the WSDL until Visual Studio is happy
Details:
1) In the CXF configuration file add the wsdlLocation attribute
<jaxws:endpoint xmlnse="urn:discovery.services.sec.com"
id="DiscoveryImpl"
endpointName="e:discovery"
serviceName="e:DiscoveryService"
address="discovery"
implementor=com.sec.services.discovery.DiscoveryImpl"
wsdlLocation="WEB-INF\discovery.wsdl
>
There are several ways to specify the WSDL location. Google Code Search was helpful.
2) The original WSDL started off
...
Removing the import above, the result is
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions ...>
<wsdl:types>
<xsd:schema ..> <!-- Discovery.xsd contents here -->
...
</xsd:schema>
</xsd:types>
<xsd:schema ..>
<!-- import of Discovery.xsd removed from here -->
...
</xsd:schema>
</xsd:types>
<wsdl:message ...>
I hope this saves some else a little bit of time.

svcutil generated unneccesary wrapper classes

I am working on a project that uses the contract first approach. I was given a WSDL and three xsd's. When I use svcutil it generates a wrapper around the response class like so:
public partial class getDataByIdResponse1 {
public getDataByIdResponse getDataByIdResponse;
public getDataByIdResponse1() {
}
public getDataByIdResponse1(getDataByIdResponse getDataByIdResponse) {
this.getDataByIdResponse = getDataByIdResponse;
}
}
The getDataByIdResponse is wrapped inside a getDataByIdResponse1 object. This is done by svcutil and I have no idea why. The getDataByIdResponse1 object does not exist in the WSDL:
<wsdl:message name="getDataById">
<wsdl:part name="response" element="tns:getDataByIdResponse"/>
</wsdl:message>
<xs:element name="getDataByIdResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="data" type="sbc:DataType" minOccurs="1" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
Why is the type getDataByIdResponse wrapped in getDataByIdResponse1? Is there a switch for svcutil I should have used?
I'm in the same boat as you but I don't just want to live with it. I want to generate clean (unwrapped) contracts. If the wsdl and xsd's were given to you then there are some rules that your schema and wsdl need to follow in order for svc util to generate unwrapped code. These links helped me understand the issue a little better
http://pzf.fremantle.org/2007/05/handlign.html
http://mharbauer.wordpress.com/2007/10/19/wcf-datacontract-serializer-and-documentwrapped/
For now my schema and wsdl are small enough that I can tweak them to adhere to this rules.
However, like Ron, I've also been in situations where the easiest thing is just to live with it.
Hope this helps.
I am in the same situation (contract-first) and svcutil is generating this same kind of code for me but I just closed my eyes took a deep breath and accepted it :-)
Just use the types without the numeric postfix and it just works.

Resources