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