My question is similar to the one in the following post: Consume XML SOAP Webservice in Java. Basically my problem is that generating client code with wsimport does not really fail but generates a warning "[WARNING] Port "reqReplyEndpoint" does not contain any usable operations". This leads to incomplete code generation, e.g. i'm missing parameters in the generated request/reqponse classes. It's a WCF Service hosted on IIS that uses WCF message routing service. IIS routes all service requests to the endpoint. I have no control over this Service, i just have to comsume it. Any idea how to achieve this without a working wsimport, e.g. the approach mentioned by aksappy? Are the any frameworks, samples available? As well for the mentioned solution approach of using a schema validator to check WSDL during runtime and then based on that have separate parsing mechanisms?
-
Is the WSDL usable at all? Did you try to import it into another tool like soapUI for checking its integrity? – Aydin K. Jan 08 '16 at 11:57
-
Yes WSDL is usable. I can consume it with basic C# Console Application and adding a Service reference. Using SoapUI: Error loading WSDL (org.apache.xmlbeans.XmlException: error: Reference to undefined entity raquo). WSDL is importing schema from different namespaces, both simple and complex type – tinu73 Jan 11 '16 at 08:30
-
Hmm if soapUI complains about the WSDL during the import, I don't think that the WSDL is correct. If possible, you could post the WSDL content here (including the referenced XSDs) and we can fix the WSDL. Afterwards, wsimport should then also work. – Aydin K. Jan 11 '16 at 14:10
-
You can download all files from here: https://onedrive.live.com/redir?resid=12C30179487E9366!6375&authkey=!ABCyag_z7tu9FNg&ithint=folder%2czip. What do you mean by "we can fix the WSDL". Generating WSDL is out of my control. It's automatically generated by the system from that i try to consume the service. – tinu73 Jan 11 '16 at 16:17
1 Answers
just checked your package.
Your WSDL contains two services, one is named reqReplyEndpoint and the other one is named BasicHttpBinding_TestTableService. I'm quite sure, you want to proceed with the BasicHttpBinding_TestTableService because the other one has empty definition in it (no operations etc defined, see xppservice-wsdl0.xml)
Therefore:
"[WARNING] Port "reqReplyEndpoint" does not contain any usable operations"
is not the reason for the empty TestTableServiceGetListRequest. These are two separate wsdl:services with no direct relationship between. This warning is thrown, because a binding with name "reqReplyEndpoint" points to a porttype named "IRequestReplyRouter" which has empty definition in it (just compare content xppservice-wsdl0.xml to xppservice-wsdl1.xml).
The reason for this must be somewhere in your code, I'm not an C# WSDL expert (but am quite experienced in WSDLs/Webservices in general).
Next: Your WSDL contains three operations with names: createMember deleteMember getList
The WSDL-result (SOAP env) for getList is according to soapUI:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dat="http://schemas.microsoft.com/dynamics/2010/01/datacontracts" xmlns:arr="http://schemas.microsoft.com/2003/10/Serialization/Arrays" xmlns:ser="http://ax.bernina.com/01/services">
<soapenv:Header>
<dat:CallContext>
<!--Optional:-->
<dat:Company>?</dat:Company>
<!--Optional:-->
<dat:Language>?</dat:Language>
<!--Optional:-->
<dat:LogonAsUser>?</dat:LogonAsUser>
<!--Optional:-->
<dat:MessageId>?</dat:MessageId>
<!--Optional:-->
<dat:PropertyBag>
<!--Zero or more repetitions:-->
<arr:KeyValueOfstringstring>
<arr:Key>?</arr:Key>
<arr:Value>?</arr:Value>
</arr:KeyValueOfstringstring>
</dat:PropertyBag>
</dat:CallContext>
</soapenv:Header>
<soapenv:Body>
<ser:TestTableServiceGetListRequest/>
</soapenv:Body>
</soapenv:Envelope>
You see, ser:TestTableServiceGetListRequest is empty, because the underlying base xsd (xppservice-xsd3.xml) contains an empty definition there:
<xs:element name="TestTableServiceGetListRequest">
<xs:complexType>
<xs:sequence/>
</xs:complexType>
</xs:element>
If you expect some more parameters in TestTableServiceGetListRequest, you should checked the corresponding source code (which is responsible for the WSDL result - I am not talking about the wsimport result) if there is something missing (annotation or similar).
Also: I'd suggest to to rather contract-first design (create WSDL first, then generate code from it) than code-first design because as you see, the result from the code might be not like expected and searching the root cause in the code can be difficult.
Edit 1 Regarding question 1 from comments:
If you want to move the CallContext from the soap:header into the soap:body, following needs to be changed in the wsdl (xppservice-wsdl.xml):
Before:
<wsdl:operation name="getList">
<soap:operation soapAction="http://ax.bernina.com/01/services/TestTableService/getList" style="document"/>
<wsdl:input name="TestTableServiceGetListRequest">
<soap:header message="i1:TestTableServiceGetListRequest_Headers" part="context" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="TestTableServiceGetListResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="AifFaultFault">
<soap:fault name="AifFaultFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
After:
<wsdl:operation name="getList">
<soap:operation soapAction="http://ax.bernina.com/01/services/TestTableService/getList" style="document"/>
<wsdl:input name="TestTableServiceGetListRequest">
<soap:body message="i1:TestTableServiceGetListRequest_Headers" part="context" use="literal"/>
</wsdl:input>
<wsdl:output name="TestTableServiceGetListResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="AifFaultFault">
<soap:fault name="AifFaultFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>

- 3,309
- 36
- 44
-
If you expect some definition within the TestTableServiceGetList-Request, you will need to fix it in the code, which is responsible for the server side service and the WSDL. Afterwards, you can proceed with the client side. – Aydin K. Jan 11 '16 at 20:21
-
If server side is done (expected parameters existing in WSDL+XSD) and worst comes to worst and you're forced to make progress on the client side,you could still bypass all the wsimport wsdl generation step and do following quite rude workaround:Generate soap-envelopes with soapUI (like I did above) and send the resulting soap-envelope via a simple http-client (apache httpclient for instance - even curl from command line will do it) as http-payload to the server.Yes, this skips all the advantages of the webservice-technology(contracts, types, ..) but as I said: If worst comes to the worst.. – Aydin K. Jan 11 '16 at 20:24
-
Thank you very much for this very good answer. Your explanation is very detailed and clear to me. I have some further questions and would appreciate if you could help me: – tinu73 Jan 11 '16 at 21:34
-
1) Actually what i'm struggling with is CallContext in Soap Envelope Header. I was expecting this as a parameter in the TestTableServiceGetList-Request (as in C#). But when i capture Soap request from my C# application (fiddler) i see that it is part of the header. So far I haven't managed to get CallContext in my Soap Header. I tried everything, searching blogs for solutions, Stackoverflow, etc. May i ask you to have a look at my uploaded project in TestTable.zip? – tinu73 Jan 11 '16 at 21:36
-
2) I need to include NLTM authentication into the generated Client Stub. For testing purposes i created another project NTLMTest.zip. It basically works but i do not really know how to make this working for the generated client stub from wsimport. – tinu73 Jan 11 '16 at 21:39
-
3) I was just wondering how you managed soapUI to generate Envelope for TestTableServiceGetListRequest? I tried with xppservice-wsdl1.xml but i failed. Could you please give me a tip how to do this? – tinu73 Jan 11 '16 at 21:43
-
lets start with the easiest one, 3) I uploaded the wsdl package to: http://www81.zippyshare.com/v/yNe0TX7d/file.html (private link). I did not change the wsdl, just the location of the wsdl+xsd because before the file references where pointing to one of your server. I changed the path locatoin so that the import point to my local folder and not to your server, which expects user+pass. – Aydin K. Jan 11 '16 at 21:47
-
4) Another one is. How i get rid of messages like: Jan 11, 2016 10:48:40 PM [com.sun.xml.ws.policy.EffectiveAlternativeSelector] selectAlternatives WARNING: WSP0075: Policy assertion "{http://schemas.microsoft.com/ws/06/2004/policy/http}NegotiateAuthentication" was evaluated as "UNKNOWN". Jan 11, 2016 10:48:40 PM [com.sun.xml.ws.policy.EffectiveAlternativeSelector] selectAlternatives WARNING: WSP0019: Suboptimal policy alternative selected on the client side with fitness "UNKNOWN". [com.sun.xml.ws.policy.EffectiveAlternativeSelect – tinu73 Jan 11 '16 at 21:51
-
Regarding 2) Sorry, I've no experience in combining a webservice with NLTM but maybe this link can help: https://dmdaa.wordpress.com/2012/10/10/ntlm-v2-support-for-java-web-service-clients-wsimport-or-axis2-stubs-for-sharepoint-server/ – Aydin K. Jan 11 '16 at 21:56
-
or http://stackoverflow.com/questions/4865165/jax-ws-sharepoint-401-unauthorized-ntlm – Aydin K. Jan 11 '16 at 21:57
-
Thanks for 1) but i was more looking fo a solution to set CallContext in the soap:header not moving into soap:body. I mean how to invoke the service that CallContext will be send in soap:header. Do you know how to achive this if you look at my code in TestTable.zip?. And Thanks for the links for 2) – tinu73 Jan 11 '16 at 22:20