Simon Nash wrote:
Simon Laws wrote:
On Thu, Sep 9, 2010 at 3:35 PM, Millies, Sebastian
<[email protected]> wrote:
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
Hi Sebastien
Unfortunately I don't think the @XmlJavaTypeAdapter JAXB annotation is
supported in the 1.x code base. If was added to the 2.x code base at
r743192 if you want to look it up. The interface test was extended
here [1]
[1]
http://svn.apache.org/repos/asf/tuscany/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/TestInterface.java
Regards
Simon
It looks like this code change (but not the test case?) was added to the
Tuscany 1.x codebase under r744091. This was marked as a fix for
TUSCANY-2840,
and there were additional commits to 1.x for this JIRA under r745778 and
r745779. I'll do some investigation to try to find out why this annotation
isn't working with 1.x.
Simon
After spending some time looking at this, I have come to the following
conclusions.
1. There isn't any difference between Tuscany 1.x and 2.x in how they handle
abstract classes, abstract exceptions and @XmlJavaTypeAdapter.
2. For Tuscany talking to Tuscany, abstract classes can be passed as method
parameters over Web Services if they are correctly annotated with
@XmlJavaTypeAdapter. This includes abstract exception classes passed as
method parameters.
3. For Tuscany services talking to non-Tuscany web service clients, using
@XmlJavaTypeAdapter for custom marshalling and unmarshalling of method
parameters doesn't work because of TUSCANY-3779. This bug causes Tuscany
to generate incorrect WSDL that isn't compatible with the data passed on
the wire.
4. It isn't possible to declare an abstract exception class as a checked
exception type in a service interface, pass a concrete subclass of the
declared exception type from a service to a client over a Web Services
binding, and have the exception unmarshalled by the client as the same
concrete subclass of the declared exception type. This is a JAX-WS
limitation, not a Tuscany limitation. Because SCA uses JAX-WS for mapping
from interface.java to WSDL and vice versa, it's also an SCA limitation.
I'm surprised and disappointed by point 4, which deserves a more detailed
explanation. In JAX-WS, service interface exceptions are converted to fault
beans and these fault beans are mapped to XML using JAXB. Because JAXB
never sees the original exception object, it isn't possible to use the
@XmlJavaTypeAdapter annotation to customize how this exception object is
mapped to an XML schema type on the wire, or vice versa.
When marshalling a thrown exception object, the mapping from the exception
object to the fault bean is described in section 3.7 of the JAX-WS 2.1 spec.
It's possible to control this mapping either by using the
@WebFault/getFaultInfo()
pattern in the declared Java exception class or by defining a getter method
in the declared Java exception class to extract runtime information from the
Java exception object, such as its concrete exception class name. This means
that we do have some flexibility and options on the marshalling side, though
these require some tweaking of the abstract exception class definition.
Unfortunately the same flexibility isn't available when unmarshalling the
WSDL fault information on the client side to create a Java exception.
The problem is that JAX-WS doesn't provide any way to control the class of
the unmarshalled exception based on information passed in the WSDL fault.
The steps are as follows:
1. JAX-WS uses JAXB to create a fault bean from the XML passed. The mapping
from XML to the fault bean could be customized using @XmlJavaTypeAdapter,
but this isn't particularly useful because of what happens next.
2. JAX-WS converts the fault bean to a Java exception whose class is the
declared exception type in the service interface, with no opportunity to
customise the exception class that JAX-WS instantiates. If the declared
exception type is abstract, this step fails. JAXB isn't involved in this
step, so no JAXB customization of this conversion is possible.
We could define some Tuscany-specific mechanism for adding flexibility to
step 2 above, but this wouldn't be interoperable when using Tuscany to talk
to non-Tuscany web services, which defeats the whole point of using an
interoperable Web Services binding.
Any suggestions for a solution would be most welcome.
Simon