You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@tuscany.apache.org by "Millies, Sebastian" <Se...@ids-scheer.com> on 2010/09/09 11:00:08 UTC

Abstract exception classes and web services

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.JAXWSFaultExceptionMapper

 

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 

 


Re: Abstract exception classes and web services

Posted by Simon Nash <na...@apache.org>.
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.JAXWSFaultExceptionMapper
> 
>  
> 
> 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
> 
>  
>