I'd like to validate the response of a Soap Spring Webservice against XSD on server side.
The validation result should not lead to a soap fault.
For client compatiblity reason the webservice response contains
the validation error e.g. like
<SOAP-ENV:Body>
<ns:eltResponse>
<errCode>the error code</errorCode>
<errMessage>the error message</errMessage>
</ns:eltResponse>
</SOAP-ENV:Body>
I tried it with the PayloadValidatingInterceptor and a custom ValidationErrorHandler.
But this lead to soap faults. Is it possible to create a response like above mentioned, e.g. with an exception resolver?
Related
How to disable Verbose Error Messages of soap web services?
I have one web method with some para.
Example Req:
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<GenerateTestRequest xmlns="http://tempuri.org/">
<sId>1#!aB</sId>
<mobileNum>12345678</mobileNum>
<srcType>1</srcType>
</GenerateTestRequest>
</Body>
</Envelope>
When an unexpected input was supplied into sId para instead of Int32, Then the web service returned an exception within the response content.
Example Res:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:DeserializationFailed</faultcode>
<faultstring xml:lang="en-SG">The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:sId. The InnerException message was 'There was an error deserializing the object of type System.Int32. The value '1#!aB' cannot be parsed as the type 'Int32'.'. Please see InnerException for more details.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
I don't want to display response content of exception message. Is there any way to turn off stack trace or exception details?
Is there any way to turn off stack trace or exception details?
Yes, by doing proper error handling for the SOAP web service.
A SOAP request can receive back a successful SOAP response or can receive back an unsuccessful response in the form of a SOAP Fault. People unfortunately focus on the successful cases only and let the framework they are using handle other problems.
Because SOAP is a protocol any exception on the server needs to be converted to a proper Fault response. This needs to be done by the developer by catching any exception and building appropriate Fault responses out of them, with only the needed data inside. For security reasons of course that data can't contain stacktraces or others sensitive information. But like I said, people often neglect to handle the error cases, and the framework can't build custom Faults, it can only build a SOAP fault with details from the exception that occurred, exposing it to the client.
You didn't tag this WCF but the schema namespace on the error code says windowscommunicationfoundation so I'll assume that's the web service framework. You can replace all exception messages with a generic error message by setting IncludeExceptionDetailInFaults to false (I think for your service it is set to true right now). See here for details: either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server
Or, you can do proper error handling and define and document the possible Faults a client can receive and convert any exception to one of those Faults. You can start reading here: Specifying and Handling Faults in Contracts and Services
If you are using any other web service framework or library, the idea is the same, the documentation to read will be different.
Is SOAP end-point over HTTP expected to return any status code except 200 and 500? I have a SOAP end-point that has some business logic to reject requests when there are too many of them. I wonder what is the correct HTTP response code in this case - 500 or 429? The SOAP specification seems vague to me:
SOAP HTTP follows the semantics of the HTTP Status codes for
communicating status information in HTTP. For example, a 2xx status
code indicates that the client's request including the SOAP component
was successfully received, understood, and accepted etc.
In case of a SOAP error while processing the request, the SOAP HTTP
server MUST issue an HTTP 500 "Internal Server Error" response and
include a SOAP message in the response containing a SOAP Fault element
(see section 4.4) indicating the SOAP processing error.
In short SOAP uses HTTP/HTTPS as a transport. It is not bound to HTTP/S. SOAP can also use SMTP and JMS as a transport. Yes you can do SOAP via email.
The 200 and 500 error codes mentioned is just the standard way of letting SOAP know that the message contains a successful or failed SOAP request. Thus I would use 500 with the error logged in the standard SOAP fault.
have a wsdl link and I know the soap request what to send and lso the response format through the membrane soap ui client
I have written a simple html page having 3 fields which i pass through request format of soap and then i get a response based on it. This passing of request and validations are done in servlet which i call through action in form. Now i have a wsdl file link.
How should I use it to make request response from the servlet .please help me with code.
EDIT : THE WSDL CONTAINS WCF BASED SOAP SERVICE .
You have to build a web service client from wsdl using wsimport java utility, then you will get a webservice handle, using that you can build a request, send a request and get a response.
for more details: http://docs.oracle.com/javaee/6/tutorial/doc/bnayn.html
I'm using jboss fuse 6.1-final:
here is my simple route:
<route>
<from uri="cxf:bean:synchronousEndpoint"/>
<log message="Service invoked." />
<process ref="simpleProcessor"/>
</route>
and in the simpleProcessor I'm putting correct response(i.e corresponding JAXB object) to the context. But, it responds with fault:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Marshalling Error: java.lang.Object cannot be cast to org.w3c.dom.Element</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
here is stack trace:
Caused by: java.lang.ClassCastException: java.lang.Object cannot be cast to org.w3c.dom.Element
is there any hints or suggestions?
Bit hard to say without seeing some more code from the simpleProcessor. However it seems like you are using the wrong dataFormat parameter.
The cxf component has a dataFormat parameter which can be any of the following:
POJO: POJOs (Plain old Java objects) are the Java parameters to the
method being invoked on the target server. Both Protocol and Logical
JAX-WS handlers are supported.
PAYLOAD: PAYLOAD is the message payload (the contents of the
soap:body) after message configuration in the CXF endpoint is
applied. Only Protocol JAX-WS handler is supported. Logical JAX-WS
handler is not supported.
MESSAGE: MESSAGE is the raw message that is received from the
transport layer. It is not suppose to touch or change Stream, some of
the CXF interceptors will be removed if you are using this kind of
DataFormat so you can't see any soap headers after the camel-cxf
consumer and JAX-WS handler is not supported.
CXF_MESSAGE: New in Camel 2.8.2, CXF_MESSAGE allows for invoking the
full capabilities of CXF interceptors by converting the message from
the transport layer into a raw SOAP message
The default is POJO which means there is no XML being passed as a message Camel is passing objects. I suspect you might be trying to manipulate the response as XML and this is causing problems.
I ran into something similiar to this a while back where I was trying to convert the POJO into XML by trying to do a XPATH query on the XML when I was receiving a POJO.
From doing some testing on SOAP requests to a webservice I created in Salesforce I note the response returned is of the following format.
Note my request function I called is GetMsgRQ
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://soap.sforce.com/schemas/class/MyIntegrationServices">
<soapenv:Body>
<GetMsgRQResponse>
<result>
<acctId>001J000000leVpEIAU</acctId>
<acctName>MyTest</acctName>
</result>
</lGetMsgRQResponse>
</soapenv:Body>
</soapenv:Envelope>
Relating to this I wonder is it possible to add a SOAP:Header?
Also I note the response has created an element "GetMsgRQResponse" (adding "Response" to "GetMsgRQ". Is it possible to create/specify the SOAP:Body without this occuring? Can I just set what the whole SOAP body response will be or will Salesforce always add such additional elements as the "GetMsgRQResponse" here and "result"?
Thanks in advance for any help on this. I know I can use a HTTP Request to send a full SOAP envelope but for my requirement I need to just provide a response instead of doing so.
I don't believe you can directly add any kind SOAP headers in an Apex defined WebService methods.
If you have absolutely no other option you could construct your own custom SOAP response via a REST web service (via #RestResource annotation) but that is a pretty ugly solution.