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/08/19 10:48:59 UTC
Error handling, bindings and business logic
Hello there,
one of the aims of SCA is to separate technology integration logic from business
logic. For example, you don’t want your business logic to depend on a
webservice provider API. In Tuscany, the wiring infrastructure is handled
by specifying a binding in the configuration, which in theory could be
switched from one communication protocol to another.
I wonder if not integration technologies may be so different as to make this
goal unattainable, or at least not quite attained yet in Tuscany. Consider the
case of exception handling as presented in the travelsample tutorial .
There is a CreditCardPayment service whose interface has been generated
from a wsdl according to JAX-WS 2.1. The generated service interface
interface contains an authorize- method that throws an
AuthorizeFault_Exception.
This CreditCardPayment interface is referenced by the Payment service.
Accordingly, the client code in the Payment implementation has
code like this:
try
{
creditCardPayment.authorize( … );
}
catch( AuthorizeFault_Exception e )
{
do_something_with( e.getFaultInfo().getErrorCode() );
}
Now, presumably the CreditcardPayment implementation on the service provider side
would really throw an AuthorizeException, which is mapped to an AuthorizeFault
in the wsdl, from which the client-side AuthorizeFault_Exception is generated.
Accordingly, if we switch to an ordinary Java binding, the Payment service would need
to reference a different interface containing an authorize-method that throws an
AuthorizeException, and the client code would look like something this:
try
{
creditCardPayment.authorize( … );
}
catch( AuthorizeException e )
{
do_something_with( e.getErrorCode() );
}
Clearly, both the referenced interface and the error handling code in the business logic
would need to be binding specific.
Does this not defeat one of the original purposes of using Tuscany SCA in the first place?
Or am I missing something?
-- Sebastian
Re: Error handling, bindings and business logic
Posted by Simon Nash <na...@apache.org>.
See comments below.
Simon
Millies, Sebastian wrote:
> From: Simon Nash [mailto:nash@apache.org]
> Sent: Thursday, August 19, 2010 4:59 PM
> To: user@tuscany.apache.org
> Subject: Re: Error handling, bindings and business logic
>
> [snip]
>> This is a tricky area and needs care to avoid pitfalls.
>>
>> In the general case, it is possible to end up with two interfaces with
>> equivalent semantics that aren't substitutable for each other. For example,
>> if a service CreditCardPayment1 were developed using a pure Java interface
>> (with exceptions thrown as AuthorizeException etc.) and another service
>> CreditCardPayment2 were developed using a WSDL interface using JAX-WS to
>> generate a Java interface from the WSDL (top down WSDL->Java), the services
>> CreditCardPayment1 and CreditCardPayment2 wouldn't be substitutable.
>>
>> If you want your services to have the greatest possible substitutability,
>> it's advisable to implement them using top-down WSDL interfaces as this
>> CreditCardPayment example shows. There's nothing to prevent a client and a
>> service from using a top-down WSDL interface (as shown in this example) and
>> being connected by a non-web services binding such as binding.sca.
>>
>> If you go the other way and use Java-specific interfaces with bottom-up
>> Java->WSDL generation, everything works OK as long as all your services
>> and clients are Java. You also have the convenience of being able to throw
>> and catch AuthorizeException. The downside is that this approach doesn't scale
>> beyond Java, so it can cause problems of the kind you are mentioning when
>> non-Java services or clients are introduced.
>>
>> Simon
>
> Thank you for that explanation. I have a follow-up question with regard to
> the default binding:
>
> The book states in section 2.5.2 that "Tuscany uses Web services over
> SOAP/HTTP for remote calls over the default binding" (within the same domain).
> How does the pure Java bottom-up approach work when I deploy the client and
> service in different JVMs in the same domain, e. g. on different servers in
> a cluster? Or will it break even then?
>
No, everything works fine in a pure Java environment using the default binding
to connect services running in different JVMs or on different computers
in a network. Under the covers the Tuscany runtime uses the JAX-WS and JAXB
Java-to-WSDL mapping to create WSDL from the Java service interfaces, then
uses this generated WSDL to create web service endpoints for the distributed
SCA services. All this is completely transparent to the Java business logic
which doesn't see any JAX-WS artifacts or APIs. However, the Java service
interfaces do need to be JAXB-friendly (e.g., no unannotated interface types
passed as method arguments).
> (When the client and service are within the same JVM, I assume there is no problem
> because this is not a remote call, and Java introspection would be used to discover
> and invoke the correct service method.)
>
Yes, this case is automatically optimized by the Tuscany runtime to make
direct in-process calls and avoid going through the Web Services runtime stack.
Simon
> -- Sebastian
>
>
RE: Error handling, bindings and business logic
Posted by "Millies, Sebastian" <Se...@ids-scheer.com>.
From: Simon Nash [mailto:nash@apache.org]
Sent: Thursday, August 19, 2010 4:59 PM
To: user@tuscany.apache.org
Subject: Re: Error handling, bindings and business logic
[snip]
>This is a tricky area and needs care to avoid pitfalls.
>
>In the general case, it is possible to end up with two interfaces with
>equivalent semantics that aren't substitutable for each other. For example,
>if a service CreditCardPayment1 were developed using a pure Java interface
>(with exceptions thrown as AuthorizeException etc.) and another service
>CreditCardPayment2 were developed using a WSDL interface using JAX-WS to
>generate a Java interface from the WSDL (top down WSDL->Java), the services
>CreditCardPayment1 and CreditCardPayment2 wouldn't be substitutable.
>
>If you want your services to have the greatest possible substitutability,
>it's advisable to implement them using top-down WSDL interfaces as this
>CreditCardPayment example shows. There's nothing to prevent a client and a
>service from using a top-down WSDL interface (as shown in this example) and
>being connected by a non-web services binding such as binding.sca.
>
>If you go the other way and use Java-specific interfaces with bottom-up
>Java->WSDL generation, everything works OK as long as all your services
>and clients are Java. You also have the convenience of being able to throw
>and catch AuthorizeException. The downside is that this approach doesn't scale
>beyond Java, so it can cause problems of the kind you are mentioning when
>non-Java services or clients are introduced.
>
> Simon
Thank you for that explanation. I have a follow-up question with regard to
the default binding:
The book states in section 2.5.2 that "Tuscany uses Web services over
SOAP/HTTP for remote calls over the default binding" (within the same domain).
How does the pure Java bottom-up approach work when I deploy the client and
service in different JVMs in the same domain, e. g. on different servers in
a cluster? Or will it break even then?
(When the client and service are within the same JVM, I assume there is no problem
because this is not a remote call, and Java introspection would be used to discover
and invoke the correct service method.)
-- Sebastian
Re: Error handling, bindings and business logic
Posted by Simon Nash <na...@apache.org>.
Simon Nash wrote:
> Comments inline.
>
> Simon
>
> Millies, Sebastian wrote:
>> From: Simon Nash [mailto:nash@apache.org]
>> [snip]
>>> In the general case, it is possible to end up with two interfaces with
>>> equivalent semantics that aren't substitutable for each other. For
>>> example,
>>> if a service CreditCardPayment1 were developed using a pure Java
>>> interface
>>> (with exceptions thrown as AuthorizeException etc.) and another service
>>> CreditCardPayment2 were developed using a WSDL interface using JAX-WS to
>>> generate a Java interface from the WSDL (top down WSDL->Java), the
>>> services
>>> CreditCardPayment1 and CreditCardPayment2 wouldn't be substitutable.
>>>
>>> If you want your services to have the greatest possible
>>> substitutability,
>>> it's advisable to implement them using top-down WSDL interfaces as this
>>> CreditCardPayment example shows. There's nothing to prevent a client
>>> and
>>> a service from using a top-down WSDL interface (as shown in this
>>> example)
>>> and being connected by a non-web services binding such as binding.sca.
>>>
>>> If you go the other way and use Java-specific interfaces with bottom-up
>>> Java->WSDL generation, everything works OK as long as all your services
>>> and clients are Java. You also have the convenience of being able to
>>> throw and catch AuthorizeException. The downside is that this approach
>>> doesn't scale beyond Java, so it can cause problems of the kind you are
>>> mentioning when non-Java services or clients are introduced.
>>
>> I've thought about this some more, but I must be obtuse. Please tell me
>> when I'm getting to be a nuisance...
>>
> Not at all. You're asking some excellent questions.
>
>> Anyway, suppose I have a top-down WSDL interface (or have edited my
>> original
>> Java interface after generating JAX-WS artifacts from it, I guess both
>> would
>> be possible). Now, I would also have to add webservice specific coding to
>> the code that throws the exception, e. g. like this:
>>
>> final String msg = "Unknown user: " + user;
>> AuthorizeFault faultBean = new AuthorizeFault();
>> faultBean.setMessage(msg);
>> throw AuthorizeFault_Exception("Basic Message", faultBean);
>>
>> What then if I also want to make this service available via RMI? I
>> guess I
>> would have to create a non-substitutable interface and a separate
>> service implementation to go with it.
>>
> Actually you might be able to use the RMI binding with a Java-from-WSDL
> substitutable interface. However, the WSDL-ness would show through
> (if only because of the unusual exceptions thrown), so if you were trying
> to interoperate with an unsuspecting RMI client then you would probably
> prefer to create a different service and interface for that purpose.
> However, you wouldn't need a different service implementation as it's
> perfectly fine for the same implementation class to support multiple
> services with different interfaces.
>
>> I also wonder how to organize my exception classes. When looking only
>> at interfaces
>> without exceptions, I can specify the interface name in the package
>> structure of
>> my client, and SCA will discover if its compatible with the interface
>> provided by
>> the service. Once exceptions come into play, this isn't so easy,
>> because in general
>> they'd have to sit in the same package on the client and service side,
>> forcing me to
>> adapt the client side interfaces depending on the service.
>> An example is the scatours.CurrencyConverterLauncher, which I view as
>> a client for the CurrencyConverter service. This class contains the
>> following line:
>>
>> scatours.currencyconverter.CurrencyConverter converter =
>> ((SCAClient) node).
>> getService( CurrencyConverter.class, "CurrencyConverter" );
>>
>> but methods in the interface
>> scatours.currencyconverter.CurrencyConverter couldn't throw
>> a hypothetical scatours.currencyconverter.CurrencyConverterException,
>> they would have
>> to use
>> com.tuscanyscatours.currencyconverter.CurrencyConverterException so as
>> to be
>> compatible with the interface
>> com.tuscanyscatours.currencyconverter.CurrencyConverter.
>>
>> Could SCA provide a way around this by relaxing the compatibility
>> rules? Or am I completely
>> on the wrong track? Perhaps I should see exception classes organized
>> orthogonally to services.
>>
>> -- Sebastian
>>
> This is a very good question. The SCA 1.1 assembly spec treats exception
> compatibility in the same way as it treats type compatibility for the
> parameters of the interface: by saying that the exceptions or parameters
> must be "the same". It also says that if there are different interface
> definition languages for the reference and service interfaces, the
> interfaces must be mapped to WSDL to determine compatibility. This means
> that Java classes would be mapped to XML types. Putting these together,
> I believe the right approach would be to convert exception types on the
> service and reference interfaces to XML and check whether the mapped XML
> types are the same, not to check whether the exception Java classes are
> in the same Java package.
>
> This is stretching the SCA spec a bit, but it feels plausible. However,
> we would need to go further down this path before declaring victory.
> If the Java exception classes are in different packages, the mapped XML
> types would be in different namespaces but otherwise identical. So we
> would also need SCA to define equivalence rules for XML types that only
> look at the contents of the type rather that its namespace or name.
> Again this feels plausible but it's too much of a stretch to assume
> these semantics without explicit clarification in the SCA specs, and
> this would need an OASIS spec issue to be raised.
>
> I'm not sure how Tuscany handles this. I'll try it out using 1.6 and
> post the results here.
>
Tuscany 1.6 doesn't allow the reference side to use a different exception
class than the service side. I think this is likely to be true for
classes passed as service method parameters as well, though I haven't
tried it. So the flexibility in interface matching extends only to the
interface definition itself, not to the types that the interface uses.
Simon
Re: Error handling, bindings and business logic
Posted by Simon Nash <na...@apache.org>.
Comments inline.
Simon
Millies, Sebastian wrote:
> From: Simon Nash [mailto:nash@apache.org]
>
> [snip]
>> In the general case, it is possible to end up with two interfaces with
>> equivalent semantics that aren't substitutable for each other. For example,
>> if a service CreditCardPayment1 were developed using a pure Java interface
>> (with exceptions thrown as AuthorizeException etc.) and another service
>> CreditCardPayment2 were developed using a WSDL interface using JAX-WS to
>> generate a Java interface from the WSDL (top down WSDL->Java), the services
>> CreditCardPayment1 and CreditCardPayment2 wouldn't be substitutable.
>>
>> If you want your services to have the greatest possible substitutability,
>> it's advisable to implement them using top-down WSDL interfaces as this
>> CreditCardPayment example shows. There's nothing to prevent a client and
>> a service from using a top-down WSDL interface (as shown in this example)
>> and being connected by a non-web services binding such as binding.sca.
>>
>> If you go the other way and use Java-specific interfaces with bottom-up
>> Java->WSDL generation, everything works OK as long as all your services
>> and clients are Java. You also have the convenience of being able to
>> throw and catch AuthorizeException. The downside is that this approach
>> doesn't scale beyond Java, so it can cause problems of the kind you are
>> mentioning when non-Java services or clients are introduced.
>
> I've thought about this some more, but I must be obtuse. Please tell me
> when I'm getting to be a nuisance...
>
Not at all. You're asking some excellent questions.
> Anyway, suppose I have a top-down WSDL interface (or have edited my original
> Java interface after generating JAX-WS artifacts from it, I guess both would
> be possible). Now, I would also have to add webservice specific coding to
> the code that throws the exception, e. g. like this:
>
> final String msg = "Unknown user: " + user;
> AuthorizeFault faultBean = new AuthorizeFault();
> faultBean.setMessage(msg);
> throw AuthorizeFault_Exception("Basic Message", faultBean);
>
> What then if I also want to make this service available via RMI? I guess I
> would have to create a non-substitutable interface and a separate service
> implementation to go with it.
>
Actually you might be able to use the RMI binding with a Java-from-WSDL
substitutable interface. However, the WSDL-ness would show through
(if only because of the unusual exceptions thrown), so if you were trying
to interoperate with an unsuspecting RMI client then you would probably
prefer to create a different service and interface for that purpose.
However, you wouldn't need a different service implementation as it's
perfectly fine for the same implementation class to support multiple
services with different interfaces.
> I also wonder how to organize my exception classes. When looking only at interfaces
> without exceptions, I can specify the interface name in the package structure of
> my client, and SCA will discover if its compatible with the interface provided by
> the service. Once exceptions come into play, this isn't so easy, because in general
> they'd have to sit in the same package on the client and service side, forcing me to
> adapt the client side interfaces depending on the service.
>
> An example is the scatours.CurrencyConverterLauncher, which I view as a client for the
> CurrencyConverter service. This class contains the following line:
>
> scatours.currencyconverter.CurrencyConverter converter = ((SCAClient) node).
> getService( CurrencyConverter.class, "CurrencyConverter" );
>
> but methods in the interface scatours.currencyconverter.CurrencyConverter couldn't throw
> a hypothetical scatours.currencyconverter.CurrencyConverterException, they would have
> to use com.tuscanyscatours.currencyconverter.CurrencyConverterException so as to be
> compatible with the interface com.tuscanyscatours.currencyconverter.CurrencyConverter.
>
> Could SCA provide a way around this by relaxing the compatibility rules? Or am I completely
> on the wrong track? Perhaps I should see exception classes organized orthogonally to services.
>
> -- Sebastian
>
This is a very good question. The SCA 1.1 assembly spec treats exception
compatibility in the same way as it treats type compatibility for the
parameters of the interface: by saying that the exceptions or parameters
must be "the same". It also says that if there are different interface
definition languages for the reference and service interfaces, the
interfaces must be mapped to WSDL to determine compatibility. This means
that Java classes would be mapped to XML types. Putting these together,
I believe the right approach would be to convert exception types on the
service and reference interfaces to XML and check whether the mapped XML
types are the same, not to check whether the exception Java classes are
in the same Java package.
This is stretching the SCA spec a bit, but it feels plausible. However,
we would need to go further down this path before declaring victory.
If the Java exception classes are in different packages, the mapped XML
types would be in different namespaces but otherwise identical. So we
would also need SCA to define equivalence rules for XML types that only
look at the contents of the type rather that its namespace or name.
Again this feels plausible but it's too much of a stretch to assume
these semantics without explicit clarification in the SCA specs, and
this would need an OASIS spec issue to be raised.
I'm not sure how Tuscany handles this. I'll try it out using 1.6 and
post the results here.
Simon
Re: Error handling, bindings and business logic
Posted by Simon Nash <na...@apache.org>.
Scott Kurz wrote:
> Simon,
>
> I know for the IBM Java 1.6 JDK I'm using, it works with:
>
> xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
> <jaxb:serializable uid="....."/>
>
> I believe the JAXB spec specifies this. Yes, it's definitely useful
> in SCA where we have both styles of serialization.
>
I looked at the JAXB 2.1 spec and it does specify <jaxb:serializable>.
The <xjc:serializable> tag is a vendor extension provided by the JAXB RI.
See [1] for details. Apparently this is historical: in JAXB 1.0 the
RI provided this as a nonstandard extension to the spec, and in JAXB 2.1
(or 2.0?) it was adopted as part of the official spec but in a different
namespace. Apologies for the confusion.
Simon
[1] http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/1.6/jaxb/vendorCustomizations.html
> Scott
>
> On Tue, Aug 24, 2010 at 2:45 PM, Simon Nash <na...@apache.org> wrote:
>> Scott Kurz wrote:
>>> Sebastian,
>>>
>>> Just wanted to jump in with a tip that will help you write an
>>> exception class that is both Java-serializable (for RMI) as well as
>>> XML-serializable (for binding.ws). This is to use the JAXB
>>> serializable customization.
>>>
>>> If you add something like this to the <schema> element containing the
>>> definition of the schema type of the element your fault bean maps to:
>>>
>>> <schema targetNamespace="http://my.company" jaxb:version="2.0"
>>> xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
>>> xmlns="http://www.w3.org/2001/XMLSchema">
>>> <annotation>
>>> <appinfo>
>>> <jaxb:globalBindings>
>>> <jaxb:serializable uid="....."/>
>>> </jaxb:globalBindings>
>>> </appinfo>
>>> </annotation>
>>>
>>> then I believe the default Java implementation of
>>> readObject()/writeObject() will allow you to serialize/deserialize the
>>> generated fault bean type just fine.
>>>
>>> I'd like to have tried it out before suggesting it, but I'm switching
>>> machines and don't have Tuscany set up at this instant.
>>>
>>> Another general point to make about exception handling is that, from
>>> the client catching the exception, you should only rely on the fault
>>> bean obtained via getFaultInfo(), rather than other regular Java
>>> exception features like getMessage() and getCause() which won't
>>> necessarily be preserved across all bindings. I think you already
>>> recognize this point though...
>>>
>>> Not sure I understand your second question about interface
>>> compatibility and package names so I wont' comment on that.
>>>
>>> Scott Kurz
>>>
>>>
>> Hi Scott,
>> I wasn't aware thar JAXB could generate Java classes that support
>> Java serialization. This could be very useful when designing interfaces
>> that are intended to be RMI-friendly as well as XML/Web Services-friendly.
>>
>> I did a bit of googling for more information about this and I found a
>> few web pages saying that the tag is <xjc:serializable> where the
>> xjc prefix corresponds to "http://java.sun.com/xml/ns/jaxb/xjc".
>>
>> Simon
>>
>>
>
>
Re: Error handling, bindings and business logic
Posted by Scott Kurz <sc...@gmail.com>.
Simon,
I know for the IBM Java 1.6 JDK I'm using, it works with:
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
<jaxb:serializable uid="....."/>
I believe the JAXB spec specifies this. Yes, it's definitely useful
in SCA where we have both styles of serialization.
Scott
On Tue, Aug 24, 2010 at 2:45 PM, Simon Nash <na...@apache.org> wrote:
> Scott Kurz wrote:
>>
>> Sebastian,
>>
>> Just wanted to jump in with a tip that will help you write an
>> exception class that is both Java-serializable (for RMI) as well as
>> XML-serializable (for binding.ws). This is to use the JAXB
>> serializable customization.
>>
>> If you add something like this to the <schema> element containing the
>> definition of the schema type of the element your fault bean maps to:
>>
>> <schema targetNamespace="http://my.company" jaxb:version="2.0"
>> xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
>> xmlns="http://www.w3.org/2001/XMLSchema">
>> <annotation>
>> <appinfo>
>> <jaxb:globalBindings>
>> <jaxb:serializable uid="....."/>
>> </jaxb:globalBindings>
>> </appinfo>
>> </annotation>
>>
>> then I believe the default Java implementation of
>> readObject()/writeObject() will allow you to serialize/deserialize the
>> generated fault bean type just fine.
>>
>> I'd like to have tried it out before suggesting it, but I'm switching
>> machines and don't have Tuscany set up at this instant.
>>
>> Another general point to make about exception handling is that, from
>> the client catching the exception, you should only rely on the fault
>> bean obtained via getFaultInfo(), rather than other regular Java
>> exception features like getMessage() and getCause() which won't
>> necessarily be preserved across all bindings. I think you already
>> recognize this point though...
>>
>> Not sure I understand your second question about interface
>> compatibility and package names so I wont' comment on that.
>>
>> Scott Kurz
>>
>>
> Hi Scott,
> I wasn't aware thar JAXB could generate Java classes that support
> Java serialization. This could be very useful when designing interfaces
> that are intended to be RMI-friendly as well as XML/Web Services-friendly.
>
> I did a bit of googling for more information about this and I found a
> few web pages saying that the tag is <xjc:serializable> where the
> xjc prefix corresponds to "http://java.sun.com/xml/ns/jaxb/xjc".
>
> Simon
>
>
Re: Error handling, bindings and business logic
Posted by Simon Nash <na...@apache.org>.
Scott Kurz wrote:
> Sebastian,
>
> Just wanted to jump in with a tip that will help you write an
> exception class that is both Java-serializable (for RMI) as well as
> XML-serializable (for binding.ws). This is to use the JAXB
> serializable customization.
>
> If you add something like this to the <schema> element containing the
> definition of the schema type of the element your fault bean maps to:
>
> <schema targetNamespace="http://my.company" jaxb:version="2.0"
> xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
> xmlns="http://www.w3.org/2001/XMLSchema">
> <annotation>
> <appinfo>
> <jaxb:globalBindings>
> <jaxb:serializable uid="....."/>
> </jaxb:globalBindings>
> </appinfo>
> </annotation>
>
> then I believe the default Java implementation of
> readObject()/writeObject() will allow you to serialize/deserialize the
> generated fault bean type just fine.
>
> I'd like to have tried it out before suggesting it, but I'm switching
> machines and don't have Tuscany set up at this instant.
>
> Another general point to make about exception handling is that, from
> the client catching the exception, you should only rely on the fault
> bean obtained via getFaultInfo(), rather than other regular Java
> exception features like getMessage() and getCause() which won't
> necessarily be preserved across all bindings. I think you already
> recognize this point though...
>
> Not sure I understand your second question about interface
> compatibility and package names so I wont' comment on that.
>
> Scott Kurz
>
>
Hi Scott,
I wasn't aware thar JAXB could generate Java classes that support
Java serialization. This could be very useful when designing interfaces
that are intended to be RMI-friendly as well as XML/Web Services-friendly.
I did a bit of googling for more information about this and I found a
few web pages saying that the tag is <xjc:serializable> where the
xjc prefix corresponds to "http://java.sun.com/xml/ns/jaxb/xjc".
Simon
Re: Error handling, bindings and business logic
Posted by Scott Kurz <sc...@gmail.com>.
Sebastian,
Just wanted to jump in with a tip that will help you write an
exception class that is both Java-serializable (for RMI) as well as
XML-serializable (for binding.ws). This is to use the JAXB
serializable customization.
If you add something like this to the <schema> element containing the
definition of the schema type of the element your fault bean maps to:
<schema targetNamespace="http://my.company" jaxb:version="2.0"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appinfo>
<jaxb:globalBindings>
<jaxb:serializable uid="....."/>
</jaxb:globalBindings>
</appinfo>
</annotation>
then I believe the default Java implementation of
readObject()/writeObject() will allow you to serialize/deserialize the
generated fault bean type just fine.
I'd like to have tried it out before suggesting it, but I'm switching
machines and don't have Tuscany set up at this instant.
Another general point to make about exception handling is that, from
the client catching the exception, you should only rely on the fault
bean obtained via getFaultInfo(), rather than other regular Java
exception features like getMessage() and getCause() which won't
necessarily be preserved across all bindings. I think you already
recognize this point though...
Not sure I understand your second question about interface
compatibility and package names so I wont' comment on that.
Scott Kurz
RE: Error handling, bindings and business logic
Posted by "Millies, Sebastian" <Se...@ids-scheer.com>.
From: Simon Nash [mailto:nash@apache.org]
[snip]
>In the general case, it is possible to end up with two interfaces with
>equivalent semantics that aren't substitutable for each other. For example,
>if a service CreditCardPayment1 were developed using a pure Java interface
>(with exceptions thrown as AuthorizeException etc.) and another service
>CreditCardPayment2 were developed using a WSDL interface using JAX-WS to
>generate a Java interface from the WSDL (top down WSDL->Java), the services
>CreditCardPayment1 and CreditCardPayment2 wouldn't be substitutable.
>
>If you want your services to have the greatest possible substitutability,
>it's advisable to implement them using top-down WSDL interfaces as this
>CreditCardPayment example shows. There's nothing to prevent a client and
>a service from using a top-down WSDL interface (as shown in this example)
>and being connected by a non-web services binding such as binding.sca.
>
>If you go the other way and use Java-specific interfaces with bottom-up
>Java->WSDL generation, everything works OK as long as all your services
>and clients are Java. You also have the convenience of being able to
>throw and catch AuthorizeException. The downside is that this approach
>doesn't scale beyond Java, so it can cause problems of the kind you are
>mentioning when non-Java services or clients are introduced.
I've thought about this some more, but I must be obtuse. Please tell me
when I'm getting to be a nuisance...
Anyway, suppose I have a top-down WSDL interface (or have edited my original
Java interface after generating JAX-WS artifacts from it, I guess both would
be possible). Now, I would also have to add webservice specific coding to
the code that throws the exception, e. g. like this:
final String msg = "Unknown user: " + user;
AuthorizeFault faultBean = new AuthorizeFault();
faultBean.setMessage(msg);
throw AuthorizeFault_Exception("Basic Message", faultBean);
What then if I also want to make this service available via RMI? I guess I
would have to create a non-substitutable interface and a separate service
implementation to go with it.
I also wonder how to organize my exception classes. When looking only at interfaces
without exceptions, I can specify the interface name in the package structure of
my client, and SCA will discover if its compatible with the interface provided by
the service. Once exceptions come into play, this isn't so easy, because in general
they'd have to sit in the same package on the client and service side, forcing me to
adapt the client side interfaces depending on the service.
An example is the scatours.CurrencyConverterLauncher, which I view as a client for the
CurrencyConverter service. This class contains the following line:
scatours.currencyconverter.CurrencyConverter converter = ((SCAClient) node).
getService( CurrencyConverter.class, "CurrencyConverter" );
but methods in the interface scatours.currencyconverter.CurrencyConverter couldn't throw
a hypothetical scatours.currencyconverter.CurrencyConverterException, they would have
to use com.tuscanyscatours.currencyconverter.CurrencyConverterException so as to be
compatible with the interface com.tuscanyscatours.currencyconverter.CurrencyConverter.
Could SCA provide a way around this by relaxing the compatibility rules? Or am I completely
on the wrong track? Perhaps I should see exception classes organized orthogonally to services.
-- Sebastian
Re: Error handling, bindings and business logic
Posted by Simon Nash <na...@apache.org>.
See comments inline below.
Simon
Millies, Sebastian wrote:
> Hello there,
>
>
>
> one of the aims of SCA is to separate technology integration logic from
> business
>
> logic. For example, you don’t want your business logic to depend on a
>
> webservice provider API. In Tuscany, the wiring infrastructure is handled
>
> by specifying a binding in the configuration, which in theory could be
>
> switched from one communication protocol to another.
>
>
>
> I wonder if not integration technologies may be so different as to make this
>
> goal unattainable, or at least not quite attained yet in Tuscany.
> Consider the
>
> case of exception handling as presented in the travelsample tutorial .
>
This is an excellent question about a rather tricky area of SCA.
In the specific case you are mentioning, I don't think there's a problem.
See my comments inline below for clarification of how this case would
be handled. I've also added some thoughts on the more general issue of
interface substitutability.
>
>
> There is a CreditCardPayment service whose interface has been generated
>
> from a wsdl according to JAX-WS 2.1. The generated service interface
>
> interface contains an authorize- method that throws an
>
> AuthorizeFault_Exception.
>
>
>
> This CreditCardPayment interface is referenced by the Payment service.
>
> Accordingly, the client code in the Payment implementation has
>
> code like this:
>
>
>
> * try*
>
> {
>
> creditCardPayment.authorize( … );
>
> }
>
> *catch*( AuthorizeFault_Exception e )
>
> {
>
> *do_something_with(* e.getFaultInfo().getErrorCode() );
>
> }
>
>
>
> Now, presumably the CreditcardPayment implementation on the service
> provider side
>
> would really throw an AuthorizeException, which is mapped to an
> AuthorizeFault
>
> in the wsdl, from which the client-side AuthorizeFault_Exception is
> generated.
>
Actually the service provider code would throw AuthorizeFault_Exception
because this is what the interface declares for the authorize method.
It's unfortunate that the service-side code in CreditCardPaymentImpl.java
in the travel sample code doesn't declare or throw this exception, which
would have clarified this point.
>
> Accordingly, if we switch to an ordinary Java binding, the Payment
> service would need
>
> to reference a different interface containing an authorize-method that
> throws an
>
> AuthorizeException, and the client code would look like something this:
>
>
>
> * try*
>
> {
>
> creditCardPayment.authorize( … );
>
> }
>
> *catch*( AuthorizeException e )
>
> {
>
> *do_something_with(* e.getErrorCode() );
>
> }
>
By "an ordinary Java binding" I presume you mean binding.sca. In this
case the interface wouldn't need to change and the client and server
could continue to catch and throw AuthorizeFault_Exception.
>
> Clearly, both the referenced interface and the error handling code in
> the business logic
>
> would need to be binding specific.
>
>
>
> Does this not defeat one of the original purposes of using Tuscany SCA
> in the first place?
>
> Or am I missing something?
>
>
>
> -- Sebastian
>
This is a tricky area and needs care to avoid pitfalls.
In the general case, it is possible to end up with two interfaces with
equivalent semantics that aren't substitutable for each other. For example,
if a service CreditCardPayment1 were developed using a pure Java interface
(with exceptions thrown as AuthorizeException etc.) and another service
CreditCardPayment2 were developed using a WSDL interface using JAX-WS to
generate a Java interface from the WSDL (top down WSDL->Java), the services
CreditCardPayment1 and CreditCardPayment2 wouldn't be substitutable.
If you want your services to have the greatest possible substitutability,
it's advisable to implement them using top-down WSDL interfaces as this
CreditCardPayment example shows. There's nothing to prevent a client and
a service from using a top-down WSDL interface (as shown in this example)
and being connected by a non-web services binding such as binding.sca.
If you go the other way and use Java-specific interfaces with bottom-up
Java->WSDL generation, everything works OK as long as all your services
and clients are Java. You also have the convenience of being able to
throw and catch AuthorizeException. The downside is that this approach
doesn't scale beyond Java, so it can cause problems of the kind you are
mentioning when non-Java services or clients are introduced.
Simon