Wow...but now you are stucked with XFire..even inside your busines logic...
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.

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


Reply via email to