Hello, On 11/27/06, Andres Bernasconi <[EMAIL PROTECTED]> wrote:
Wow...but now you are stucked with XFire..even inside your busines logic...
Nope. My DAO's don't catch any exceptions including Spring's JDBC RuntimeExceptions. It's the service implementation that's traps Spring's RuntimeException and then rethrows this new exception extended from XFireFault.
We are using Wrappers in our project. I guess it suits us just fine because we always return the same type of object for all operations, so we only have one wrapper. Still I'm no fanatic of either approach...just use what suits you best... Still, I guess that this particular case (extending your exceptions from XFireException) is something I would not have done.
If it would have made the C# developer's job significantly easier or if it was a third-party application that couldn't be changed, then I'd consider a wrapper class as a compromise but it appears catching the faults will be easy in C#. One problem I found was that because I'm extending org.codehaus.xfire.fault.XFireFault, the Aegis default mapping is generating corresponding properties including one for faultCode with has a QName type. This caused the schema validation to fail so I added the following Aegis mapping file to hide most of the exception's properties: RecordNotFound.aegis.xml: <?xml version="1.0" encoding="UTF-8"?> <mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xfire.codehaus.org/schemas/1.0/mapping.xsd"> <mapping> <property name="faultCode" ignore="true"/> <property name="detail" ignore="true"/> <property name="namespaces" ignore="true"/> <property name="subCode" ignore="true"/> </mapping> </mappings> XFire is still setting the faultcode and faultstring properly so there doesn't seem to be any need for these properties. -Bill
On 11/27/06, Bill Burton <[EMAIL PROTECTED]> wrote: > > 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
