thanks for the explanation. However, when I tested this just now, it didn't 
work. Perhaps I misunderstood, or there's a bug in Tuscany.

What I did was annotate the abstract exception class as follows

@XmlJavaTypeAdapter(CurrencyConverterExceptionAdapter.class)
public abstract class CurrencyConverterException extends Exception

and implement the adapter class in the same server-side package, so it can
get imported by the client together with the exception. The adapter simply
serializes the exception to and from a string in the format
"concreteClassName#message".

On the client side I changed nothing. When I ran this code in Tuscany 1.6
(calling the server from a different node to make sure the ws-binding is used),
the unmarshal/marshal methods in the adapter do not even get called. Is there
anything more I have to do except implement the adapter class? I'm sorry if
this is a naive question, but it really sounded so simple in your post.

-- Sebastian

> -----Original Message-----
> From: Simon Nash [mailto:[email protected]]
> Sent: Thursday, September 09, 2010 2:13 PM
> To: [email protected]
> Subject: Re: Abstract exception classes and web services
> 
> I think it's important to establish general principles for these
> interoperability cases, and then look at specific cases to see
> how the general principles are applied.
> 
> The general principle for SCA components communicating over the
> Web Service binding is:
> 
> 1. The service interface is mapped to WSDL (if not already WSDL).
> 2. The client interface is mapped to WSDL (if not already WSDL).
> 3. If either interface can't be mapped to WSDL, interoperability
>     isn't possible and an error should be reported.
> 4. The SCA compatibility rules are applied to the mapped WSDL
>     interfaces.  If the mapped WSDL interfaces don't pass the
>     compatibility test, interoperability isn't possible and an
>     error should be reported.
> 5. If no errors were reported by steps 3 and 4, the client and
>     service should interoperate correctly at runtime.
> 
> The implication here is that every Java interface and implementation
> that passes steps 3 and 4 will also pass step 5.  However this isn't
> always the case for JAX-WS and JAXB.  In some cases it's necessary to
> add custom marshalling/unmarshalling code using the @XmlJavaTypeAdapter
> annotation to enable the JAXB runtime to successfully marshal and
> unmarshal certain object types.  In some cases (e.g., interface types)
> the need for such customization is detected by the Java-WSDL mapping.
> In other cases (e.g., abstract class types), the Java-WSDL mapping
> doesn't produce any error message, but it's still necessary to add
> custom unmarshalling code to get things to work.
> 
> I don't think there's anything special about using an abstract class
> as a thrown exception rather than using an abstract class as a passed
> or returned parameter.  In all these cases the Java-WSDL mapping
> works OK without errors, but runtime unmarshalling doesn't work
> unless @XmlJavaTypeAdapter is used.
> 
> If you want to be able to throw and catch any of a number of concrete
> exception classes when using an abstract exception class on the
> service interface, you'll need to write a JAXB custom marshalling/
> unmarshalling adapter that stores the desired concrete class name
> in the XML data passed across the wire for the WSDL fault and uses
> this information on the client side to create the correct concrete
> subclass.  This is effectively what the RMI runtime is doing
> automatically for you.
> 
> The bottom line is that if using abstract exception classes you need
> to write some extra marshalling/unmarshalling adapter code and you
> need to design your abstract exception classes to hold the necessary
> information to enable custom unmarshalling.  If you do this, the same
> business exception logic will work over both Web Services and RMI.
> 
>    Simon
> 
> Millies, Sebastian wrote:
> > Hello there,
> >
> >
> >
> > in Tuscany SCA 1.6, it seems not to be possible to have a remote
> method
> > that declares
> >
> > an abstract exception class in its interface, and access that method
> > from a remote node
> >
> > over a webservice binding.
> >
> >
> >
> > For example, say CurrencyConverterException is an abstract base class
> > for my checked
> >
> > exceptions, and it has UnknownCurrencyException as an immediate
> concrete
> > subclass.
> >
> > Then my service interface and implementation may look like this.
> >
> >
> >
> > @Remotable
> >
> > *public* *interface* CurrencyConverter
> >
> > {
> >
> >   *double* getExchangeRate( String fromCurrencyCode, String
> > toCurrencyCode ) *throws* CurrencyConverterException;
> >
> > }
> >
> >
> >
> > @Service(interfaces =
> >
> >   { CurrencyConverter.*class* })
> >
> > *public* *class* CurrencyConverterImpl *implements* CurrencyConverter
> >
> > {
> >
> >
> >
> >   *public* *double* getExchangeRate( String fromCurrencyCode, String
> > toCurrencyCode ) *throws* CurrencyConverterException
> >
> >   {
> >
> >     *if*( true )
> >
> >     {
> >
> >       *throw* *new* UnknownCurrencyException( "Unknown source
> currency:
> > " + fromCurrencyCode );
> >
> >     }
> >
> >   }
> >
> > }
> >
> >
> >
> > The client component has a reference to the CurrencyConverter
> service:
> >
> > <sca:component name=/"ClientComponent"/>
> >
> >     <sca:reference name=/"converter"/>
> >
> >       <sca:binding.ws
> uri=/"http://localhost:8080/CurrencyConverter"//>
> >
> >     </sca:reference>
> >
> >   </sca:component>
> >
> >
> >
> > When running the client in its own node, calling getExchangeRate on
> the
> > injected CurrencyConverter reference,
> >
> >  I will get a  _java.lang.InstantiationException _in the class
> >
> org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSFaultExceptionMappe
> r
> >
> >
> >
> > Of course, the wsdl didn’t change a bit when I changed my service
> > implementation and made CurrencyConverterException abstract.
> >
> > A normal JAX-WS Java client can continue to use the JAX-WS artefacts
> as
> > it always did and will not encounter this InstantiationException,
> >
> > because it doesn’t even try to reconstruct a server side exception.
> >
> >
> >
> > And of course, when using the webservice binding, the client should
> not
> > have to rely on technical
> >
> > implementation details of the server (after all, the whole idea is
> they
> > may be implemented in different technologies). So
> >
> > Tuscany shouldn’t try to give me the original exception, but the
> > corresponding web fault. Which would force the client
> >
> > to use different exception handling code for a webservice than say
> for
> > an RMI binding. The technologies are just too different
> >
> > to be handled in a uniform fashion.
> >
> >
> >
> > We had this point before. I find it interesting that I keep running
> up
> > against it in the context of exceptions.
> >
> >
> >
> > -- Sebastian
> >
> >
> >

Reply via email to