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

Reply via email to