Hello, Thanks everyone for the helpful responses.
Although it would be possible to create a wrapper class, I'd really rather not given that I think it should be easy to check for the fault in the C# client. If the client was a third-party application in which I had absolutely no control, that would be a different matter. What I would like to do is find some happy medium that works well with an XFire service and C# clients. Here's what I found so far using an XFire Aegis mapped service and by writing my own C# client: * Throwing a checked exception (that's specified in your service interface) causes XFire to generate a SOAP fault where the faultcode == "soap:Server" and faultstring contains the exception text message. * In C#, a SOAP fault from XFire translates into a SoapException where: - SoapException.Message contains the message text specified to the Java Exception. - SoapException.Code.Name contains the faultcode "Server" (soap: is stripped off) - SoapException.Details.FirstChild.Name is the name of the Java Exception, i.e. "RecordNotFoundException". Although it's trivial for the C# application to check the exception message, I'd rather specify a meaningful code that's easy to check. Right now, the faultcode shows up as: <faultcode>soap:Server</faultcode> which provides no indication of the problem. I'd like to change it to something like: <faultcode>soap:Server.RecordNotFound</faultcode> as from what I've read in the SOAP specs, this is how error codes can be specified (http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383510). So my question now is, how do I specify my own error code for the SOAP fault code? Well, that was my question. It turned out to by very easy to customize the fault code--just have my exception class extend XFireFault instead of something else and then specify the fault code in a QName. My Exception class now looks like this: public class RecordNotFoundException extends XFireFault { public RecordNotFoundException() { super(); } public RecordNotFoundException(String message) { super(message, new QName(null, "soap:Server.RecordNotFound")); } } The service interface is: public interface PersonService { public Person findByLoginId(String id) throws RecordNotFoundException; } which generates (slightly abbreviated): <soap:Fault> <faultcode>soap:Server.RecordNotFound</faultcode> <faultstring>No record with id 123100782F was found by the findByLoginId method!</faultstring> </soap:Fault> which is exactly what I wanted. The C# SOAP fault checking is now very easy: try { person = personService.findByLoginId("123100782F"); } catch (System.Web.Services.Protocols.SoapException se) { if (!se.Code.IsEmpty && se.Code.Name.Equals("Server.RecordNotFound")) { Console.WriteLine("Record was not found: " + se.Message); } } Thanks! -Bill On 11/22/06, Tomek Sztelak <[EMAIL PROTECTED]> wrote:
Hi On 11/21/06, Bill Burton <[EMAIL PROTECTED]> wrote: > Hello, > > I've written a simple service that provides a way to lookup Person objects > by id or email address. The Person object just has some name and address > information. When a record is not found, I'm catching the runtime exception > from the Spring JDBC API, and rethrowing a checked exception which causes > XFire to generate a SOAP fault as follows: > > <soap:Envelope > xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" > xmlns:xsd="http://www.w3.org/2001/XMLSchema " > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> > <soap:Body> > <soap:Fault> > <faultcode>soap:Server</faultcode> > <faultstring>No record with id 000123005 was found by the findById > method!</faultstring> > <detail> > <RecordNotFoundException xmlns=" http://webservice.teds.pms"/> > </detail> > </soap:Fault> > </soap:Body> > </soap:Envelope> > > Right now, I'm just using the default generated bindings in my Spring > applicationContext.xml > > <bean name="PersonService" > class="org.codehaus.xfire.spring.ServiceBean"> > <property name="serviceBean" ref="PersonServiceImpl"/> > <property name="serviceClass" > value="pms.teds.webservice.PersonService"/> > </bean> > > but plan to switch to Aegis to have better control over the mapping for > other reasons. Aegis is a default binding, so you are already using it:) > However, the person who's writing a C# .NET client to handle this complains > that it's hard to check for a fault whereas if I were to return an error > code and error text in my Person object, he would have no problem. As the > Person object is supposed to be a reflection of the database columns, I > really don't want to change it in this manner. > > What are the best practices for generating an error such as "record not > found" or "database not available" cases? I think that adding error codes to your data model object is a bad idea. You should use exception ( SOAP fault ), as you do now. > Thanks for any assistance, > -Bill > -- > Bill Burton < bburton ayht mail daht com> >
--------------------------------------------------------------------- To unsubscribe from this list please visit: http://xircles.codehaus.org/manage_email
