I am using CXF JAXWS Client for retrieving some information from an external web services. So, basically, we have .xsd and .wsdl files from the external and try to implement our ws consumer by generating the client stubs using cxf-codegen-plugin. We cannot change the .xsd and .wsdl files. Everything works fine, we are able to send and retrieve soap messges from the external services.
However, when I look into the soap request message from the log, I find a lot of unused namespaces in the soap (body) message sent from our ws client.
Below is an example
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:aheaderns="http://xxx.xxx.xxx.xxx/header.xsd">
<soap:Header>
...
</soap:Header>
<soap:Body>
<ns7:requestQuery xmlns:ns15="http://xxx.xxx.xxx.xxx/AAA" xmlns:ns14="http://xxx.xxx.xxx.xxx/BBB" xmlns:ns13="http://xxx.xxx.xxx.xxx/DDD" xmlns:ns12="http://xxx.xxx.xxx.xxx/CCC" xmlns:ns11="http://xxx.xxx.xxx.xxx/EEE" xmlns:ns10="http://xxx.xxx.xxx.xxx/FFF" xmlns:ns9="http://xxx.xxx.xxx.xxx/GGG" xmlns:ns8="http://xxx.xxx.xxx.xxx/HHH" xmlns:ns7="http://xxx.xxx.xxx.xxx/III" xmlns:ns6="http://xxx.xxx.xxx.xxx/JJJ" xmlns:ns5="http://xxx.xxx.xxx.xxx/KKK">
<ns7:sample>
<ns7:type>A</ns7:type>
<ns7:ref>1</ns7:ref>
</ns7:sample>
</ns7:requestQuery>
</soap:Body>
Is there any way to remove the unused namespaces from the outbound soap message sending from the client?
You could move your client proxy classes to the same package and map it to the proposed namespace specified in the wsdl.
Put this code into the package-info.java class:
#XmlSchema(xmlns = { #XmlNs(prefix = "ns1", namespaceURI = "http://xxx.xxx.xxx") },
namespace = "http://xxx.xxx.xxx")
package clinet.sample.proxy;
import javax.xml.bind.annotation.XmlNs;
Hope this helps.
After digging into this problem for quite sometime, I found the solution. However, I think my solution is not to solve the problem at the root cause but it works for now.
Basically, I use XSLTOutInterceptor from CXF to apply the XSL to the out message. However, the default PRE_STEAM phase is not working for me. Then, I decide to extend the XSLTOutInterceptor so as to change its PHASE to WRITE. So that, the unused namespaces will be removed during the writing of the protocol message before sending it out.
The XSL I use is from how to remove unused namespaces from source xml
By the way, I still have no idea why those unused namespaces have been generated. If anyone could give me a suggestion, I would appreciate it.
Thanks :)
Related
I am using ws:outbound-gateway to invoke soap service. I have added interceptor as well.
<int-ws:outbound-gateway id="wsOutboundGateway"
request-channel="requestChannel"
uri="{soapURI}"
message-sender="httpMessageSender"
message-factory="messageFactory"
interceptor="myInterceptor"
marshaller="jaxbMarshaller" unmarshaller="jaxbMarshaller">
<int-ws:uri-variable name="soapURI" expression="headers.soapURI"/>
</int-ws:outbound-gateway>
myInterceptor is a class which implements ClientInterceptor.
Query: I have the information in message header which needs to be intercepted. Is there any way to receive the message header in the interceptor.
Note : I am setting the header value in thread local and getting back in the interceptor now.
Any better solution, please suggest.
It depends of the premise and context.
Sorry, but you have to share more info. What is the header? What do you do with that? Maybe there is no need to intercept it in the ClientInterceptor, but would be better even before <int-ws:outbound-gateway>?
UPDATE
I have the info in message header where I have to pass it in the soap header.
Actually ClientInterceptor is fully for different purpose and its intention do not modify the message.
There is WebServiceMessageCallback abstraction for message modification before sending.
But having your requirements like pass SOAP header I can suggest you to take a look into out-of-the-box component like DefaultSoapHeaderMapper. Its populateStandardHeaders deal only with SoapAction and populateUserDefinedHeader populates only as soapHeader.addAttribute(). So, consider some extension of that class to insert custom tags into soapHeader. And already without any ThreadLocal hacks.
I am trying to intercept SOAP message of a JWS webservice using SOAPHandlerJax-ws SoapHandler.
Below is the snapshot of what I have done.
Wrote a class JwsSoapRequestValidationHandler which extends SOAPHandler
Created HandlerConfig.xml with the below entry:
<jws:handler-chain>
<jws:handler>
<jws:handler-name>SoapRequestValidator</jws:handler-name>
<jws:handler-class>com.service.ws.jws.JwsSoapRequestValidationHandler</jws:handler-class>
</jws:handler>
</jws:handler-chain>
I have placed the xml in the same folder as my webservice.
I have annotated my webservice with #HandlerChain(file = "HandlerConfig.xml")
But strangly anf frustratingly, my handler is not invoked. I have deployed my war file in Weblogic 10.3.2
Please help me resolve this issue. I have spent 2 days without any result.......
Thanks a lot for your help.
At last, I got the solution to this problem. We need to make sure that the HandlerConfig.xml file is present in the generated artifact as well.
As soon as I included the xml in my war file, it started invoking the handler. So easy at the end :) ...
Thanks to all. Hope this will be helpful to others.
I'm writing a SOAP client. I'm using gSOAP version 2.7.17 and I have to stick to that version as the server is using this one and I cannot modify it as it is already running in the field.
When I do my SOAP call, I always receive empty answer! However, when I sniff the network, the XML answer seems correct:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:Supervisor="urn:Supervisor"
xmlns:ActiveLogin="urn:ActiveLogin" xmlns:TechLogin="urn:TechLogin"
xmlns:UMSLogin="urn:UMSLogin">
<SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<unitCallResponse>
<szServerName>UMS_DEV_LANCC2 (2)</szServerName>
<dResponse>cUNITRETURNCODE_RESTARTIMMEDIATE</dResponse>
<dDetail>cBla</dDetail>
</unitCallResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Here is a simplified code snippet about how I perform the SOAP call with the proxy generated with soapcpp2:
UMSLogin::unitCallResponse response; // Response from SOAP
UMSLogin::UMSLoginProxy* m_soapProxy = // The SOAP proxy
new UMSLogin::UMSLoginProxy(SOAP_IO_KEEPALIVE, SOAP_IO_KEEPALIVE);
callRes = m_soapProxy->unitCall(m_eUnitType, serial, m_dInterfaceVersion,
xl2CallTypeToUmsLoginCallType(m_pSoapEndPoint->getCallType()),
xl2CommTypeToUmsLoginCommType(m_pSoapEndPoint->getComType()),
response);
logDebug(LOG_COM_DEVICE, "SOAP call done to %s, SOAP code %i, central code %i",
response.szServerName.c_str(), callRes, response.dResponse);
m_soapProxy->soap_close_socket();
m_soapProxy->destroy();
delete m_soapProxy;
The actual output:
SOAP call done to , SOAP code 0, central code 0
When I expect
SOAP call done to UMS_DEV_LANCC2 (2), SOAP code 0, central code 5
/* 5 -> cUNITRETURNCODE_RESTARTIMMEDIATE */
There was an old implementation that was working previously, this must be working! Where am I wrong? Did anyone has already had this kind of problem? Any pointer is strongly appreciated!
EDIT:
Problem was "solved" by using an earlier version of SOAP (2.7.14) without changing a single line of code from the original version of my program. However, I have the feeling I miss something important again! I should probably tweak a little my header file giving the SOAP "definitions" to make things working ...
Looking at your code you declare response and then reference the elements of it as response.dResponse. This seems to imply that response is a struct rather than a pointer to a struct so after you call m_soapProxy->unitCall the version of response that you then report on hasn't changed, only the copy in m_soapProxy->unitCall will have changed.
I'd try tracing this call through in the debugger and see what is actually happening in m_soapProxy->unitCall. BTW is it you code or generated by GSOAP?
I'm calling a .Net Web Service which takes a complex type as a parameter (using KSoap2). I've done this before successfully so I decided to just copy my old code and paste it into a new method, replacing some code with code relevant to the current web service of course.
The only real difference I can see is that the URL to the new web service's .asmx is different.
The thing is I keep getting the following error:
(I get the following when SoapEnvelope.VER11)
org.xmlpull.v1.XmlPullParserException: expected: END_TAG {http://schemas.xmlsoap.org/soap/envelope/}Body (position:END_TAG </{http://schemas.xmlsoap.org/soap/envelope/}soap:Fault>#1:338 in java.io.InputStreamReader#199cb474)
(And the following when SoapEnvelope.VER12)
org.xmlpull.v1.XmlPullParserException: expected: START_TAG {http://www.w3.org/2001/12/soap-envelope}Envelope (position:START_TAG <{http://schemas.xmlsoap.org/soap/envelope/}soap:Envelope>#1:207 in java.io.InputStreamReader#5b209e72
Why would the error message change like this depending on the version of SOAP I use?
I also tried printing out my envelope with HttpTransport.requestDump and I get the following:
xmlns:v="http://schemas.xmlsoap.org/soap/envelope/">
<v:Header />
<v:Body>
<postMessage xmlns="http://www.magnatech.com/" id="o0" c:root="1">
<myMessage i:type="n0:Message" xmlns:n0="http://www.magnatech.com/">
<messageContent i:type="d:string">HEY</messageContent>
<userName i:type="d:string">TEST USERNAME</userName>
<agentName i:type="d:string">TEST AGENT NAME</agentName>
<userID i:type="d:string">0</userID>
<agentID i:type="d:string">0</agentID>
<fromAgent i:type="d:string">false</fromAgent>
<messageID i:type="d:string"></messageID>
<accountNumber i:type="d:string">TEST ACCOUNT</accountNumber>
</myMessage>
</postMessage>
</v:Body>
Which looks fine, I actually did the same thing with the envelope from my other "WORKING" web service call and they are the same, except for the element names of course.
And finally, here is the output from HttpTransport.responseDump:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><soap:Fault><faultcode>soap:Client</faultcode><faultstring>Could not deserialize Soap message</faultstring></soap:Fault></soap:Body></soap:Envelope>
So obviously there is something wrong with the envelope as I'm sending it, yet I see nothing wrong with it.
What could be the problem? I've tried everything possible and am running out of ideas.
Any help at all will be greatly appreciated.
Thanks
I'm deploying a StatelessSessionBean annotated with #WebService to JBoss. I'm taking the WSDL generated by JBoss to generate client stubs. My problem is in calling a method which returns a list of objects. If the list is empty the call succeeds however if the list is not empty then I get the following exception:
com.sun.xml.ws.encoding.soap.DeserializationException: Failed to read a response: javax.xml.bind.UnmarshalException
- with linked exception:
[javax.xml.bind.UnmarshalException: Unable to create an instance of com.companyname.api.ws.DataItemType
- with linked exception:
[java.lang.InstantiationException]]
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:124)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)
at $Proxy34.getWorkflows(Unknown Source)
at com.companyname.api.SimpleClient.go(SimpleClient.java:48)
Searching the web led me to this discussion here: http://forums.java.net/jive/message.jspa?messageID=281780
However I have set the #XmlSeeAlso stuff correctly and it is present on the generated stub classes. I can confirm that the DataItemType class is abstract so it is not surprising that an attempt to instantiate it causes a problem. I'm not at all clear on why the DataItemType class is being instantiated at all (as it is abstract). This is the XML that is returned from the server (it looks about right to me):
<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>
<env:Header></env:Header>
<env:Body>
<ns2:getWorkflowsResponse xmlns:ns2="http://ws.api.companyname.com/">
<return>
<id>
<identifier>1</identifier>
<version>0</version>
</id>
<goal>ENROLL</goal>
<dataItemType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="DataItemTypeText">
<attributeName>email</attributeName>
<displayName>Email Address</displayName>
</dataItemType>
...
</return>
</ns2:getWorkflowsResponse>
</env:Body>
</env:Envelope>
Does anyone know what I'm doing wrong?
There were a number of issues with the generated WSDL (note that it wasn't a handcrafted one). There was nothing specific that I changed which indicated why this particular exception was thrown (or why, for example, there wasn't a failure when generating the incorrect WSDL).
Once I adjusted the annotations so that a valid WSDL was created then I had further issues which the JAX-WS versions I was using. I ended up upgrading the version used by JBoss which, in turn, led to me needing put the newer JAX-WS jars in my JRE endorsed directory.
I'm not going to detail what I did in any more detail as there was no specific thing that I did that addressed this problem. If anyone else sees it I would suggest being very specific in the annotations you use to generate your WSDL and taking a careful look at your WSDL.