You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Glen Mazza <gl...@verizon.net> on 2008/03/07 10:05:22 UTC

Handling internal errors via SOAP faults

Hello, I have a general question for WSDL design regarding internal web
service errors not the fault of the SOAP client request, such as
"database unavailable" or "system down" or whatever.

For example, let's say I have a simple "GetCapital" web service that
takes a country and returns the name of its capital.  One obvious
user-instigated error is providing a country name that doesn't exist.
Such a wsdl operation might be:

      <wsdl:operation name="GetCapital">
         <wsdl:input message="tns:GetCapitalRequest" />
         <wsdl:output message="tns:GetCapitalResponse" />
         <wsdl:fault message="tns:InvalidCountryNameFault"
            name="InvalidCountryNameFault" />
      </wsdl:operation>

But what about exceptions due to the internal service-side errors not
the fault of the SOAP client request (e.g., database being down, JNDI
lookup not functioning, etc.)  In this case, do I add an additional
wsdl:fault (perhaps "InternalServiceErrorFault") to each wsdl:operation
or is there a generic error handling mechanism in JAX-WS that would not
require me to burden each wsdl:operation with this additional fault?

Thanks,
Glen



Re: Handling internal errors via SOAP faults

Posted by Glen Mazza <gl...@gmail.com>.

dkulp wrote:
> 
> In general, the "jaxws" way of doing this is to map the runtime 
> exceptions to a very generic soap fault that is fault code SERVER and 
> just the message (ex.getMessage()) is set into the fault message.
> 
> On the client side, this ends up throwing the generic SOAPFaultException 
> (but with the correct message set).
> 
 
Thanks for the tip.  I used the convenience function in our systests that
did that:

private SOAPFaultException createSOAPFaultException(String faultString) {
        try {
            SOAPFault fault = SOAPFactory.newInstance().createFault();
            fault.setFaultString(faultString);
            fault.setFaultCode(new QName("http://example.org/faultcode",
"Server"));
            return new SOAPFaultException(fault);
        } catch (SOAPException e) {
            // do nothing
        }
        return null;
}

A full sample is here: http://www.jroller.com/gmazza/date/20080308#MTstep6

Glen

-- 
View this message in context: http://www.nabble.com/Handling-internal-errors-via-SOAP-faults-tp15892864p15919990.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Handling internal errors via SOAP faults

Posted by Daniel Kulp <dk...@apache.org>.
In general, the "jaxws" way of doing this is to map the runtime 
exceptions to a very generic soap fault that is fault code SERVER and 
just the message (ex.getMessage()) is set into the fault message. 

On the client side, this ends up throwing the generic SOAPFaultException 
(but with the correct message set).

Basically, if you use a declared exception (wsdl:fault), you can have a 
properly typed exception on both sides.    If you don't use a declared 
exception, you basically just get very generic stuff on the wire and on 
the client side.

Dan



On Friday 07 March 2008, Glen Mazza wrote:
> Hello, I have a general question for WSDL design regarding internal
> web service errors not the fault of the SOAP client request, such as
> "database unavailable" or "system down" or whatever.
>
> For example, let's say I have a simple "GetCapital" web service that
> takes a country and returns the name of its capital.  One obvious
> user-instigated error is providing a country name that doesn't exist.
> Such a wsdl operation might be:
>
>       <wsdl:operation name="GetCapital">
>          <wsdl:input message="tns:GetCapitalRequest" />
>          <wsdl:output message="tns:GetCapitalResponse" />
>          <wsdl:fault message="tns:InvalidCountryNameFault"
>             name="InvalidCountryNameFault" />
>       </wsdl:operation>
>
> But what about exceptions due to the internal service-side errors not
> the fault of the SOAP client request (e.g., database being down, JNDI
> lookup not functioning, etc.)  In this case, do I add an additional
> wsdl:fault (perhaps "InternalServiceErrorFault") to each
> wsdl:operation or is there a generic error handling mechanism in
> JAX-WS that would not require me to burden each wsdl:operation with
> this additional fault?
>
> Thanks,
> Glen



-- 
J. Daniel Kulp
Principal Engineer, IONA
dkulp@apache.org
http://www.dankulp.com/blog

Re: Handling internal errors via SOAP faults

Posted by Scott Anderson <sc...@gmail.com>.
I use a fault called OperationFailedFault, and set its payload to the root
exception's message:

        try {
            context.commitChanges();
        } catch(Exception e) {
            context.rollbackChanges();
            throw new OperationFailedFault(e.getMessage(), "Commit failed",
e);
        }

On Fri, Mar 7, 2008 at 4:05 AM, Glen Mazza <gl...@verizon.net> wrote:

> Hello, I have a general question for WSDL design regarding internal web
> service errors not the fault of the SOAP client request, such as
> "database unavailable" or "system down" or whatever.
>
> For example, let's say I have a simple "GetCapital" web service that
> takes a country and returns the name of its capital.  One obvious
> user-instigated error is providing a country name that doesn't exist.
> Such a wsdl operation might be:
>
>      <wsdl:operation name="GetCapital">
>         <wsdl:input message="tns:GetCapitalRequest" />
>         <wsdl:output message="tns:GetCapitalResponse" />
>         <wsdl:fault message="tns:InvalidCountryNameFault"
>            name="InvalidCountryNameFault" />
>      </wsdl:operation>
>
> But what about exceptions due to the internal service-side errors not
> the fault of the SOAP client request (e.g., database being down, JNDI
> lookup not functioning, etc.)  In this case, do I add an additional
> wsdl:fault (perhaps "InternalServiceErrorFault") to each wsdl:operation
> or is there a generic error handling mechanism in JAX-WS that would not
> require me to burden each wsdl:operation with this additional fault?
>
> Thanks,
> Glen
>
>
>

Re: Handling internal errors via SOAP faults

Posted by Glen Mazza <gl...@gmail.com>.
My example here: http://www.jroller.com/gmazza/date/20080308#MTstep10 does
display error details.

HTH,
Glen


Milan Doshi wrote:
> 
> We have defined a :
> <br>
> 1. User Defined Exception.<br>
> 2. There is a Fault element defined in WSDL.<br>
> 3. The WSDL2Java geneartes a valid anotations.<br>
> 
> HOWEVER, when we send back a Fault to the client, it is ONLY a SOAPFault
> with errorMessage. No DETAIL ELEMENT is present...:(. hence our user
> specific info is completely missing!!!
> <br><br>
> Can you please guide ?<br>
> <br>
> We are using :<br>
> Document / Literal.<br>
> CXF2.1.2<br>
> JDK1.5_16<br>
> <br><br>
> Any help appreciated!<br>
> 
> Thanks,<br>
> Milan
> 
> 
> 
> 
> dkulp wrote:
>> 
>> On Friday 07 March 2008, David Castañeda wrote:
>>> Glen, I have been fighting against this sort of questions from several
>>> weeks now,
>>>
>>> I start a sample project that is on Jira about correct handling,
>>> unfortunately I haven't found an answer from someone who know, neither
>>> I have found the way to produce correct code for server, client
>>> faults.
>>>
>>> Anyway my idea, is to only expose the exception that can be handled by
>>> the client, like InvalidCountryNameFault or
>>> MaxRequestQuantityOverLimit, mark these as Client Fault, and any other
>>> exception like (RuntimeException), DBNotAvailable, etc (things client
>>> can't handle, ServiceException) as a general exception marked as
>>> Server Fault, but as I said, I haven't found the way to do this.
>> 
>> That's probably because the spec specifically does not allow for them.  
>> I've looked at the sample in the JIRA and there will be no way to do it, 
>> per spec.  Basically, undeclared exceptions are all to be treated as 
>> generic runtime exceptions and mapped, per spec, to a relatively 
>> generice soap:fault on the wire and then to a SOAPFaultException on the 
>> client side.  If you want properly typed exceptions, you HAVE to put 
>> them on the SEI interface methods.  
>> 
>> Using some JAX-WS/JAXB "tricks", you can control the on-the-wire 
>> representation of the exception a little more, but that won't stop it 
>> from being mapped to a generic SOAPFaultException on the client side.  
>> 
>> For example, if we take your sample from CXF-1434 and change the 
>> UncheckedWrongTextException to look like:
>> 
>> @WebFault(name = "UncheckedWrongTextException")
>> public class UncheckedWrongTextException extends RuntimeException {
>>     UncheckedWrongText i;
>>     public UncheckedWrongTextException(String msg) {
>>         super(msg);
>>         i = new UncheckedWrongText();
>>         i.setMessage(msg);
>>     }
>>     public UncheckedWrongTextException(String msg, int t) {
>>         super(msg);
>>         i = new UncheckedWrongText();
>>         i.setMessage(msg);
>>         i.setIdx(t);
>>     }
>>     public UncheckedWrongText getFaultInfo() {
>>         return i;
>>     }
>> 
>>     @XmlRootElement
>>     public static class UncheckedWrongText {
>>         int idx;
>>         String msg;
>>         public int getIdx() {
>>             return idx;
>>         }
>>         public void setIdx(int i) {
>>             idx = i;
>>         }
>>         public void setMessage(String m) {
>>             msg = m;
>>         }
>>         public String getMessage() {
>>             return msg;
>>         }
>> 
>>     }
>> }
>> 
>> And then add to HelloWorld.java:
>> @XmlSeeAlso({UncheckedWrongTextException.UncheckedWrongText.class})
>> 
>> Then the on-the-wire fault would look like:
>> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
>>     <soap:Body>
>>         <soap:Fault>
>>             <faultcode>soap:Server</faultcode>
>>             <faultstring>Only characters are allowed</faultstring>
>>             <detail>
>>                 <ns2:uncheckedWrongText xmlns:ns2="http://spring.demo/">
>>                     <idx>0</idx>
>>                     <message>Only characters are allowed</message>
>>                 </ns2:uncheckedWrongText>
>>             </detail>
>>         </soap:Fault>
>>     </soap:Body>
>> </soap:Envelope> 
>> 
>> 
>> However, the client will still only get a SOAPFaultException.  In this 
>> case, though, the SOAPFaultException will have a getDetail() element 
>> that contains the detail.  Thus, it IS more information to the user.
>> 
>> 
>> --- 
>> J. Daniel Kulp
>> Principal Engineer, IONA
>> dkulp@apache.org
>> http://www.dankulp.com/blog
>> 
>> 
> 
> 

-- 
View this message in context: http://www.nabble.com/Handling-internal-errors-via-SOAP-faults-tp15892864p19967156.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: Handling internal errors via SOAP faults

Posted by Milan Doshi <mi...@gmail.com>.
We have defined a :

1. User Defined Exception.
2. There is a Fault element defined in WSDL.
3. The WSDL2Java geneartes a valid anotations.

HOWEVER, when we send back a Fault to the client, it is ONLY a SOAPFault
with errorMessage. No DETAIL ELEMENT is present...:(. hence our user
specific info is completely missing!!!

Can you please guide ?

We are using :
Document / Literal.
CXF2.1.2
JDK1.5_16

Any help appreciated!

Thanks,
Milan




dkulp wrote:
> 
> On Friday 07 March 2008, David Castañeda wrote:
>> Glen, I have been fighting against this sort of questions from several
>> weeks now,
>>
>> I start a sample project that is on Jira about correct handling,
>> unfortunately I haven't found an answer from someone who know, neither
>> I have found the way to produce correct code for server, client
>> faults.
>>
>> Anyway my idea, is to only expose the exception that can be handled by
>> the client, like InvalidCountryNameFault or
>> MaxRequestQuantityOverLimit, mark these as Client Fault, and any other
>> exception like (RuntimeException), DBNotAvailable, etc (things client
>> can't handle, ServiceException) as a general exception marked as
>> Server Fault, but as I said, I haven't found the way to do this.
> 
> That's probably because the spec specifically does not allow for them.  
> I've looked at the sample in the JIRA and there will be no way to do it, 
> per spec.  Basically, undeclared exceptions are all to be treated as 
> generic runtime exceptions and mapped, per spec, to a relatively 
> generice soap:fault on the wire and then to a SOAPFaultException on the 
> client side.  If you want properly typed exceptions, you HAVE to put 
> them on the SEI interface methods.  
> 
> Using some JAX-WS/JAXB "tricks", you can control the on-the-wire 
> representation of the exception a little more, but that won't stop it 
> from being mapped to a generic SOAPFaultException on the client side.  
> 
> For example, if we take your sample from CXF-1434 and change the 
> UncheckedWrongTextException to look like:
> 
> @WebFault(name = "UncheckedWrongTextException")
> public class UncheckedWrongTextException extends RuntimeException {
>     UncheckedWrongText i;
>     public UncheckedWrongTextException(String msg) {
>         super(msg);
>         i = new UncheckedWrongText();
>         i.setMessage(msg);
>     }
>     public UncheckedWrongTextException(String msg, int t) {
>         super(msg);
>         i = new UncheckedWrongText();
>         i.setMessage(msg);
>         i.setIdx(t);
>     }
>     public UncheckedWrongText getFaultInfo() {
>         return i;
>     }
> 
>     @XmlRootElement
>     public static class UncheckedWrongText {
>         int idx;
>         String msg;
>         public int getIdx() {
>             return idx;
>         }
>         public void setIdx(int i) {
>             idx = i;
>         }
>         public void setMessage(String m) {
>             msg = m;
>         }
>         public String getMessage() {
>             return msg;
>         }
> 
>     }
> }
> 
> And then add to HelloWorld.java:
> @XmlSeeAlso({UncheckedWrongTextException.UncheckedWrongText.class})
> 
> Then the on-the-wire fault would look like:
> 
>     
>         
>             soap:Server
>             Only characters are allowed
>             
>                 
>                     0
>                     Only characters are allowed
>                 
>             
>         
>     
>  
> 
> 
> However, the client will still only get a SOAPFaultException.  In this 
> case, though, the SOAPFaultException will have a getDetail() element 
> that contains the detail.  Thus, it IS more information to the user.
> 
> 
> --- 
> J. Daniel Kulp
> Principal Engineer, IONA
> dkulp@apache.org
> http://www.dankulp.com/blog
> 
> 

-- 
View this message in context: http://www.nabble.com/Handling-internal-errors-via-SOAP-faults-tp15892864p19965827.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: Handling internal errors via SOAP faults

Posted by Daniel Kulp <dk...@apache.org>.
On Friday 07 March 2008, David Castañeda wrote:
> Glen, I have been fighting against this sort of questions from several
> weeks now,
>
> I start a sample project that is on Jira about correct handling,
> unfortunately I haven't found an answer from someone who know, neither
> I have found the way to produce correct code for server, client
> faults.
>
> Anyway my idea, is to only expose the exception that can be handled by
> the client, like InvalidCountryNameFault or
> MaxRequestQuantityOverLimit, mark these as Client Fault, and any other
> exception like (RuntimeException), DBNotAvailable, etc (things client
> can't handle, ServiceException) as a general exception marked as
> Server Fault, but as I said, I haven't found the way to do this.

That's probably because the spec specifically does not allow for them.  
I've looked at the sample in the JIRA and there will be no way to do it, 
per spec.  Basically, undeclared exceptions are all to be treated as 
generic runtime exceptions and mapped, per spec, to a relatively 
generice soap:fault on the wire and then to a SOAPFaultException on the 
client side.  If you want properly typed exceptions, you HAVE to put 
them on the SEI interface methods.  

Using some JAX-WS/JAXB "tricks", you can control the on-the-wire 
representation of the exception a little more, but that won't stop it 
from being mapped to a generic SOAPFaultException on the client side.  

For example, if we take your sample from CXF-1434 and change the 
UncheckedWrongTextException to look like:

@WebFault(name = "UncheckedWrongTextException")
public class UncheckedWrongTextException extends RuntimeException {
    UncheckedWrongText i;
    public UncheckedWrongTextException(String msg) {
        super(msg);
        i = new UncheckedWrongText();
        i.setMessage(msg);
    }
    public UncheckedWrongTextException(String msg, int t) {
        super(msg);
        i = new UncheckedWrongText();
        i.setMessage(msg);
        i.setIdx(t);
    }
    public UncheckedWrongText getFaultInfo() {
        return i;
    }

    @XmlRootElement
    public static class UncheckedWrongText {
        int idx;
        String msg;
        public int getIdx() {
            return idx;
        }
        public void setIdx(int i) {
            idx = i;
        }
        public void setMessage(String m) {
            msg = m;
        }
        public String getMessage() {
            return msg;
        }

    }
}

And then add to HelloWorld.java:
@XmlSeeAlso({UncheckedWrongTextException.UncheckedWrongText.class})

Then the on-the-wire fault would look like:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>Only characters are allowed</faultstring>
            <detail>
                <ns2:uncheckedWrongText xmlns:ns2="http://spring.demo/">
                    <idx>0</idx>
                    <message>Only characters are allowed</message>
                </ns2:uncheckedWrongText>
            </detail>
        </soap:Fault>
    </soap:Body>
</soap:Envelope> 


However, the client will still only get a SOAPFaultException.  In this 
case, though, the SOAPFaultException will have a getDetail() element 
that contains the detail.  Thus, it IS more information to the user.


--- 
J. Daniel Kulp
Principal Engineer, IONA
dkulp@apache.org
http://www.dankulp.com/blog

Re: Handling internal errors via SOAP faults

Posted by David Castañeda <da...@gmail.com>.
Glen, I have been fighting against this sort of questions from several
weeks now,

I start a sample project that is on Jira about correct handling,
unfortunately I haven't found an answer from someone who know, neither
I have found the way to produce correct code for server, client
faults.

Anyway my idea, is to only expose the exception that can be handled by
the client, like InvalidCountryNameFault or
MaxRequestQuantityOverLimit, mark these as Client Fault, and any other
exception like (RuntimeException), DBNotAvailable, etc (things client
can't handle, ServiceException) as a general exception marked as
Server Fault, but as I said, I haven't found the way to do this.


Regards,

-- 
David Castañeda R.

Re: Handling internal errors via SOAP faults

Posted by Daniel Kulp <dk...@apache.org>.
You could write a new frontend to the wsdl2java stuff to handle #2 if you 
wanted.    Basicially, you could subclass the SEIGenerator and override the 
    protected void doWrite(String templateName, Writer outputs) throws 
ToolException {

method to change the templateName to a new template name where you can 
customtomize whatever you want.    You would need a jar with your subclass 
in it, your template in it, and a META-INF/tools-plugin.xml that would look 
something like:

<plugin name="mygen" version="" 
provider="cxf.apache.org" xmlns="http://cxf.apache.org/tools/plugin">
    <frontend name="mygen"          
package="org.apache.cxf.tools.wsdlto.frontend.jaxws" 
profile="JAXWSProfile">
           <container name="JAXWSContainer" toolspec="jaxws-toolspec.xml"/>
           <processor name="WSDLToJavaProcessor" 
package="org.apache.cxf.tools.wsdlto.frontend.jaxws.processor"/>
           <builder name="JAXWSDefinitionBuilder" 
package="org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11"/>
           <generators 
package="org.apache.cxf.tools.wsdlto.frontend.jaxws.generators">
               <generator name="AntGenerator"/>
               <generator name="ClientGenerator"/>
               <generator name="FaultGenerator"/>
               <generator name="ImplGenerator"/>
               <generator name="SEIGenerator" package="my.package"/>
               <generator name="ServerGenerator"/>
               <generator name="ServiceGenerator"/>
           </generators>
    </frontend>
</plugin>

or similar where the SEIGenerator is your subclass.

Dan




On Tuesday, July 03, 2012 02:34:34 AM nicola.tu wrote:
> Hi all,
> 
> I'm reopening this thread because in the meanwhile there may have been
> some updates that I've missed.
> 
> The original problem (and for me still open) is that if the called service
> returns a SOAPFaultException (or a javax.xml.ws.WebServiceException), the
> client needs explicitely to add the catch() clause.
> In axis, any ws call was throwing a RemoteException, so my client was
> obliged to catch it. In CXF these are all RuntimeException, so I need to
> remember to catch them and send back to the caller some graceful error
> message.
> 
> try {
> 	ServiceDataInfoResponse resp = client.getServiceDataInfo(req);
> 	return resp;
> } catch (javax.xml.ws.WebServiceException e) {
> 	// I need to remember to add this catch all the times!!
> 	throw new MyBusinessException("We are sorry, the service is currently 
not
> available.");
> }
> 
> I see 2 possible solutions, but none fully satisfying:
> 1. Add a custom SoapInterceptor to the list of client's
> InFaultInterceptors() and implement my handleFault(). Here I still don't
> know how to notify the fault in a graceful way to the caller.
> 2. Manipulate the @WebService interface and let the methods throw a
> non-runtime exception (like java.rmi.RemoteException in axis), which I'm
> obliged to catch.
> 
> Has anyonw already faced this issue?
> 
> --
> View this message in context:
> http://cxf.547215.n5.nabble.com/Handling-internal-errors-via-SOAP-faults-
> tp559600p5710576.html Sent from the cxf-user mailing list archive at
> Nabble.com.
-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com

Re: Handling internal errors via SOAP faults

Posted by "nicola.tu" <ni...@logobject.ch>.
Hi all,

I'm reopening this thread because in the meanwhile there may have been some
updates that I've missed.

The original problem (and for me still open) is that if the called service
returns a SOAPFaultException (or a javax.xml.ws.WebServiceException), the
client needs explicitely to add the catch() clause.
In axis, any ws call was throwing a RemoteException, so my client was
obliged to catch it. In CXF these are all RuntimeException, so I need to
remember to catch them and send back to the caller some graceful error
message.

try {
	ServiceDataInfoResponse resp = client.getServiceDataInfo(req);
	return resp;
} catch (javax.xml.ws.WebServiceException e) {
	// I need to remember to add this catch all the times!!
	throw new MyBusinessException("We are sorry, the service is currently not
available.");
}

I see 2 possible solutions, but none fully satisfying:
1. Add a custom SoapInterceptor to the list of client's
InFaultInterceptors() and implement my handleFault(). Here I still don't
know how to notify the fault in a graceful way to the caller.
2. Manipulate the @WebService interface and let the methods throw a
non-runtime exception (like java.rmi.RemoteException in axis), which I'm
obliged to catch.

Has anyonw already faced this issue?

--
View this message in context: http://cxf.547215.n5.nabble.com/Handling-internal-errors-via-SOAP-faults-tp559600p5710576.html
Sent from the cxf-user mailing list archive at Nabble.com.