Reading Ivan Kriznan's notes, section 9.6, I got the impression that a service annotated with @WebServiceProvider should not throw exceptions. Instead, it should return a SOAPFault in the message body and the client is responsible for checking by calling hasFault on the SOAPBody.
Is that a correct understanding? I'm also curious in knowing the best practices for throwing exceptions on the server side, as I didn't find any good documentation about that. Should you throw checked exceptions and make the client handle it? The industry seems to be moving away from checked exceptions, which IMHO as well, unnecessarily clutters the client code. How does exception handling differ between @WebServiceProvider and @WebService classes?
After some research, I think I can answer my own question.
If the service publishes a WSDL, it can throw service exceptions (ones mapped in the WSDL) or unmapped exceptions (RuntimeException or it's subclass). Service exceptions are wrapped in a SOAPFaultException and the service exception becomes the detail. If the service does not publish a WSDL, it should only throw RuntimeException or it's subclass because it's clients will have no knowledge of any checked exceptions even if it throws one. It may also not throw any exception and just set the body of the response to a SOAPFault, but in IMHO, it's a good programming practice to throw exceptions explicitly rather than leaving it up to the client to check for faults.
On the client side, if the client is a dynamic proxy type, it will see service exceptions in the form of the generated exception class and unmapped exceptions as a ProtocolException subclass, which almost always is SOAPFaultException class.
If the client is a dispatch type, regardless of how the service is implemented, it'll see the exception in the form of a ProtocolException subclass, which almost always is SOAPFaultException class.
In Ivan's StringProcessor example on p.161 of his notes, Ivan provides us a wsdl first. Then, from the WSDL, we generate the JAXB elements.
Next, Ivan create a service with @WebServiceProvider (wsdlLocation="stringProcessorService.wsdl")
In this case, the client (with SEI generated from the wsdl) uses the URL of endpoint address to invoke the service.
So, I think the client can still know what exception will be thrown.
posted 6 years ago
Himai Minh wrote:I think the client can still know what exception will be thrown.
If it's a dynamic proxy client, it'll have a client side exception class generated by wsimport. The client will not know what actual exception the service threw - the JAX-WS runtime will map the SOAP fault to the client side exception. The point to be noted is, the client may not even be written in Java so transmitting server side Java exceptions is useless. Not the least of concerns is tight coupling; if a Web Service gives out server side information to the client, we might as well use an EJB as was done in the 2000.
To comment my own post, the Provider<T> implemented by the service only provides invoke(T source) method. But this method does not throw any checked exception. So, the client can only get RuntimeException.
posted 6 years ago
Is there any way to change the faultcode to "Client" while using WSDL mapped service specific faults and @WebFault annotation?