This forum is now a read-only archive. All commenting, posting, registration services have been turned off. Those needing community support and/or wanting to ask questions should refer to the Tag/Forum map, and to http://spring.io/questions for a curated list of stackoverflow tags that Pivotal engineers, and the community, monitor.

SoapFault

I need that because i want to create custom exceptions codes (for example Client.AuthFail).
A client ws technology like Axis should get my faultcode and throw an exception (something like AuthFailException).

I need that because i want to create custom exceptions codes (for example Client.AuthFail).
A client ws technology like Axis should get my faultcode and throw an exception (something like AuthFailException).

Well, fault subcodes only exists in SOAP 1.2, not SOAP 1.1. In SOAP 1.1, you can add a faultcode with your own namespace, and that's perfectly fine. You are right about the dot-subcodes though: don't use them (see the examples at http://www.ws-i.org/Profiles/BasicPr...m_Fault_Codes).

The fact of the matter is that SOAP 1.1 and SOAP 1.2 are different on so many accounts, that it's hard to define a common interface. This is especially true for the faults. SOAP 1.1 allows you to define a single custom fault code as a QName, whereas SOAP 1.2 does not. Instead SOAP 1.2 allows you to use multiple custom fault subcodes, while the fault codes can only be Sender, Receiver, MustUnderstand, etc. I guess the W3C guys never heard of backwards compatibility.

There are four possible solutions to this:

Define specific SoapFault interfaces for SOAP 1.1 and SOAP 1.2. I don't like this solution that much, because it basically requires instanceofs everywhere.

Combine SOAP 1.1 and 1.2 methods in the SoapFault interface, and ignore methods which are not suitable for the SOAP version in use. This is the approach Axiom takes: internally, Axiom uses a SOAP 1.2 model, and basically changes that on the fly to SOAP 1.1 when saving (though not without error). I don't like this approach, because there's no way to tell whether the methods you call have any effect.

Combine SOAP 1.1 and 1.2 methods in the SoapFault interface, and throw exceptions when an method is called that is not suitable for the SOAP version in use. This is the approach SAAJ 1.3 takes. I don't like this approach either, because it requires you to catch exceptions everywhere.

Expose a single SoapFault interface, which defines the common denominator. If using SOAP 1.1, define a custom <faultcode>, if 1.2 define a custom <SubCode>. This is the approach I've picked for SWS. You lose some of the power (i.e. you cannot add multiple subcodes in SOAP 1.2), but at least you have a single, consistent interface.

I'm currently working on SAAJ 1.3 support, so this is stuff is very much on my mind. That said, I'm open for suggestions on this. If you require some missing functionality, just say so.

Comment

First, a bit of architectural advice. A SOAP Fault is not the same as an exception, both on server and client-side. A SOAP 1.1 fault has a QName faultcode, a faultString, and possibly a role and details elements. These elements don't map directly to an exception. That's why the EndpointExceptionResolver exists: it allows you to map your application exceptions to Soap Fault messages. An additional benefit is that you create a layer between your inner exceptions and your faults, allowing the two to change independently. Just like you don't want to expose your domain objects, you don't want to expose your exceptions. Once you have exposed them, you basically cannot change them that easily any more.

If you really want to let people use your Web service in a RPC-like fashion, you should play by the rules of the JAX-RCP or JAX-WS specs. This basically means (in SOAP 1.1) that you should create a fault with:

a soapenv:Server faultCode,

a faultString that is equal to the exception's message

a fault details element that contains the JavaBean properties of the exception

Note that this is basically what the SimpleSoapExceptionResolver does, except for the last bullet, which is hard without a marshaller.

Thus, in the example you gave, that means you should put the ObjectDoesNotExistFault in the details element, not the (sub)code.

As you can see, i have an LoginFault with constants. Nearly the same as my example before.

I simply doesn't find information about how that works in Axis or XFire on client side.
My defined xml schema fault content will be placed in the details element. I think this is the correct way. But how does Axis or XFire know, that it should generate a LoginFault an not a generic AxisFault? Somewhere i have to place a link to "{myFaultNamespac}LoginFault" in my Soap fault body. Do you know where?
The ideal way would be a solution which works in xfire as well as in axis or dotNet.

R1004: When an ENVELOPE contains a faultcode element, the content of that element SHOULD be either one of the fault codes defined in SOAP 1.1 (supplying additional information if necessary in the detail element), or a Qname whose namespace is controlled by the fault's specifying authority (in that order of preference).

Look at the first 'Correct' example. They use a custom fault code there.

Originally posted by res1st

Someone told me once that web services are an easy technology...

I never said that . It's not without reason that the W3C dropped the "Simple" from the SOAP acronym in SOAP 1.2. With SWS, I try to make it as simple as possible though, without losing any power.

If i return my fault, i doesn't see a logging message of the validating interceptor. Something like this:

Code:

endpoint.PayloadValidatingInterceptor - Response message validated

Why are soap fault messages not validated? Is there any reason?

I never said that . It's not without reason that the W3C dropped the "Simple" from the SOAP acronym in SOAP 1.2. With SWS, I try to make it as simple as possible though, without losing any power.

You are really doing a good job.

I have another questions regarding SoapFaultMappingExceptionResolver.
I doesn't like it that it only returns predefined strings.
If my business logic throws an exception with an useful exception message, the client will never see it. Is there any trick? Or should i write a new SoapFaultMappingExceptionResolver which (for example) copy all exception properties to the detail tag.

If i return my fault, i doesn't see a logging message of the validating interceptor. Something like this:

Code:

endpoint.PayloadValidatingInterceptor - Response message validated

Why are soap fault messages not validated? Is there any reason?

Fault are not validated because they consist of elements in your schema and elements in the SOAP schema. This makes it harder to validate. Also, the fault codes are not defined in the WSDL, only the detail can be. So theoretically, I could validate the detail. If you really want that, create an issue .

Originally posted by res1st

I have another questions regarding SoapFaultMappingExceptionResolver.
I doesn't like it that it only returns predefined strings.
If my business logic throws an exception with an useful exception message, the client will never see it. Is there any trick? Or should i write a new SoapFaultMappingExceptionResolver which (for example) copy all exception properties to the detail tag.

There is no trick (yet). So that basically means write your own for now. You could also use the SimpleSoapFaultExceptionResolver. This takes the
exception message, but you lose the code, since that's fixed to soap-env:Server (in SOAP 1.1).

Note that the interface for creating SoapFaults will change somewhat either today or tomorrow. The current API allows you to define faults which are invalid in SOAP 1.2. The problem is that SOAP 1.2 doesn't allow you to define custom faults at the top-level, only as subcode of a set of fixed codes. See http://www.idealliance.org/papers/xm...tml#faultcodes for more info.

The new API, which I will check in shortly, will only allow to create messages which are valid in either SOAP 1.1 of SOAP 1.2. Let me know how that works out for you.

I just saw in subversion your comment: "custom code, only supported for SOAP 1.1".
Does my application needs to use SOAP 1.1 if i want to use custom fault codes?
What are the consequences?
What are the disadvantages/drawbacks?

Cheers,

Ingo

Comment

Yeah, the API has changed so that it reflects the common denominator between SOAP 1.1 and SOAP 1.2. SOAP 1.1 supports custom faults codes, which SOAP 1.2 does not. In SOAP 1.2, you can only add you custom fault subcode to one of the standard error codes (MustUnderstand, VersionMismatch, Sender, or Receiver, see addSubcode in Soap12Fault). So you have to cast the SoapBody to Soap11Body, and then you can add your fault.

Basically, you probably want to use SOAP 1.1 anyway. SOAP 1.2 is not supported by many clients yet. Unless you know you really need it, it's best to use SOAP 1.1.