I posted this and it probably got lost in the midst of releasing 1.0 ...
let me resend now.
Thanks,
Scott
On 9/15/07, Scott Kurz <[EMAIL PROTECTED]> wrote:
>
> In doing some work trying to leverage the Tuscany databinding framework to
> transform business exceptions across a binding, I noticed a couple issues
> relating to the need to handle both exception and fault DataType(s) .
>
> Basically, I'd like to discuss:
>
> * getting rid of the exception DataType and replacing it with simply a
> fault DataType.
> * decoupling the fault databinding from the way that the exception maps to
> a fault.
>
> Let me explain:
>
> Today, for Java interfaces, we build exception DataTypes during
> theintrospection phase
> and we set a databinding upon it. This DB identifies an exceptionHandler
> which can (via getFaultType()) construct a fault DataType from the exc
> DataType.
>
> Different exception patterns result in different mappings between
> exception and fault data types. For example, we have the pattern defined
> by JAX-WS Sec 2.5 in which the Java exception class wrappers a "fault
> bean" returned by the exception's getFaultInfo(). I'm thinking we also
> want to support POJO exceptions as well in certain contexts.
>
> Today we would support the JAX-WS Sec. 2.5 pattern by constructing an
> DataType wrappering the exception, introspecting the exception to find
> thefault
> and its databinding. This databinding's exception handler would, at
> transform time, be used to construct a fault DataType representing thefault
> bean, distinct from
> the exception DataType. This more or less works the same for JAXB andSDO,
> except that for SDO we have
> the Tuscany-ism of looking at FAULT_ELEMENT instead of @WebFault ( which I
> mention below I'd like to change).
>
> For the POJO exception pattern, on the other hand, the fault DataType
> andexception DataType collapse into one as we see in
> the logic of JavaBeansExceptionHandler.
>
> I don't think we need the complexity of the two DataTypes; I think all we
> really need from the exception DataType is its "physical', i.e. the Java
> Class of the exception type. We use this to match the exception we have
> in-hand from the Java runtime with the DataType on the operation. It is
> only the fault that gets transformed by the Tuscany databinding framework.
>
>
> Perhaps what would be better, instead of an exception DataType and fault
> DataType, would be to simply have the fault DataType with an additional
> "exceptionPhysical" member. (We still need ExceptionHandler
> withgetFaultInfo()
> and createFaultException() as well).
>
> This would let us get the exception handlers out of the introspection
> business.
>
> If we look at DataBindingJavaInterfaceProcessor.processInterface() today,
> and see how the various databindings' exception handlers' getFaultType()s
> are called in order to find the right databinding to set on the exception
> DataType, it does seem messy to have to rely on this same getFaultType()
> method to work in a certain way and introspection time and transform
> time.
>
> The best reason, I think is elegance: if it is the actual fault DataType
> which is interesting at transform time, and if we have an introspect step,
> let's have the introspect step set up this interesting fault
> DataType. As an example, in working on some binding impl code in
> thepast, I found myself calling this same getFaultType() method to get
> the fault from the exc... making for at least three times this same
> getFaultType() method was called (Java introspect, my binding construction,
> and transform time).
>
> Then there is also performance to consider...
>
> ---------
>
> In addition, (and to some degree this is a separate point), I think we
> should recognize certain patterns in which a Java exception relates to both
> the Java type of the "fault bean" and to a logical type and decouple these
> patterns from association with one of the various databinding impls we
> support.
>
> So, as an example, if you take the pattern in JAX-WS Sec. 2.5, you can
> have an exception with @WebFault(<fault elem>) with a getFaultInfo()
> method returning a fault bean of any of the simple, SDO, or JAXB
> databindings. I don't see the rationale for using FAULT_ELEMENT to
> denote the logical type when the fault bean is an SDO vs. using [EMAIL
> PROTECTED] for a JAXB; I think this pattern should be decoupled from
> the choice of databinding, and we don't want the same algorithm (looking
> for @WebFault and using reflection to find the type returned by
> getFaultInfo(), etc.) to be re-coded for each databinding.
>
> (Though I don't think Tuscany has it presently, I coded a Simple DB
> ExceptionHandler which is largely just a copy of the SDOExceptionHandler,
> wihch illustrates my point. Someone please correct me if Tuscany can
> already handle simple-typed fault beans in the JAX-WS Sec 2.5 pattern).
>
>
> In addition we'd have other patterns like POJO exception and maybe theAxis2
> exception which Simon Nash recently did some work regarding.
>
>
> At this point I'd like to show some sample code, which is part of some
> changes I've run with successfully (some of my own tests in my own sandbox
> - not Tuscany tests yet).
>
>
> public DataType<?> getFaultFromExceptionDataType(DataType<?>
> excDataType) {
>
> //
> // 1. Find the Java type of the fault bean, construct fault DT andset
> exc physical
> //
> Object excPhysical = excDataType.getPhysical();
> if (!(excPhysical instanceof Class)) {
> return null; // Should we be throwing exc instead?
> }
> Class excClass = (Class)excPhysical;
> Class faultBeanClass = null;
> try {
> Method method = excClass.getMethod("getFaultInfo",
> EMPTY_CLASS_ARRAY);
> faultBeanClass = method.getReturnType();
> } catch (NoSuchMethodException e) {
> faultBeanClass = null;
> }
> if (faultBeanClass == null) {
> return null;
> }
>
> // Only the physical is set here.
> DataType faultDataType = new DataTypeImpl(null, faultBeanClass,
> null);
> faultDataType.setExceptionPhysical(excClass);
>
> //
> // 2. Send through already-existing introspection routine
> //
>
> // Don't try to propagate annotations yet. Note the DB on
> thefaultDataType
> // is set by the databinding according to the implied contract we
> have going.
> dataBindingRegistry.introspectType(faultDataType, null);
>
> //
> // 3) instantiate an exception handler for this fault from
> theappropriate DB
> and
> // set in the fault DT
> //
>
> DataBinding faultDataBinding = dataBindingRegistry.getDataBinding(
> faultDataType.getDataBinding());
> ExceptionHandler excHandler = faultDataBinding.getExceptionHandler();
> faultDataType.setExceptionHandler(excHandler);
>
> //
> // 4) set the logical from the @WebFault (FAULT_ELEMENT for now)
> //
> QName faultElement = null;
> try {
> Field field = excClass.getField("FAULT_ELEMENT");
> faultElement = (QName)field.get(null);
> } catch (NoSuchFieldException e) {
> // Ignore
> } catch (Throwable e) {
> // Ignore
> }
> if (faultElement == null) {
> // Should we be responsible for calculating a default
> fault_elem
> // or leave this to someone else???
> return null;
> }
>
> // Having set the physical and DB already, we now set the logical
> of the fault
> faultDataType.setLogical(new XMLType(faultElement, null));
>
> return faultDataType;
>
> }
>
>
> The above is code that would be called in some form from
> DataBindingJavaInterfaceProcessor.processInterface(), passing in the
> exception DataType.
>
> In this code, I'm finding the fault bean class through a databinding-neutral
> look at the getFaultInfo() return type. I'm then setting the DB on this
> based on the normal DB.introspect() routine (i.e. the same introspection
> of input and output types to find the databinding).
> Step 4 is to set the logical, again in a databinding-neutral way.
>
> I also have a step 3 where the ExceptionHandler is now stored in theDataType.
> This is a non-trivial change which could probably
> really use some improvement (it brings up build and intra-project
> dependency issues). I wanted to have a working prototype before
> posting this, however, and this is how I did it. The ExceptionHandler
> still has the job of implementing createException() and getFaultInfo() but
>
> not getFaultType() any more
>
> I also have a simple routine to do something similar for "POJO exceptions"
> which do not have a fault bean and which have a Java, not an XML
> logical type.
>
> public DataType<?> getFaultFromExceptionDataType(DataType<?>
> excDataType) {
>
> //
> // 1. Fault physical and Exception physical are one and the same
> //
> Object excPhysical = excDataType.getPhysical();
> if (!(excPhysical instanceof Class)) {
> return null; // Should we be throwing exc instead?
> }
> Class excClass = (Class)excPhysical;
>
> // Only the physical is set here.
> DataType faultDataType = new DataTypeImpl(null, excClass, null);
> faultDataType.setExceptionPhysical(excClass);
>
> //
> // 2. Send through already-existing introspection routine
> //
>
> // Don't try to propagate annotations yet. Note the DB on
> thefaultDataType
> // is set by the databinding according to the implied contract we
> have going.
> dataBindingRegistry.introspectType(faultDataType, null);
>
> //
> // 3) instantiate an exception handler for this fault from
> theappropriate DB
> and
> // set in the fault DT
> //
>
> DataBinding faultDataBinding = dataBindingRegistry.getDataBinding(
> faultDataType.getDataBinding());
> ExceptionHandler excHandler = faultDataBinding.getExceptionHandler();
> faultDataType.setExceptionHandler(excHandler);
>
> //
> // 4) set the logical to be the exc class as well
> //
>
> // Having set the physical and DB already, we now set the logical
> of the fault
> faultDataType.setLogical(excClass);
>
> return faultDataType;
>
> }
>
> Assuming it gets that far, I'm not sure whether it would be better to have
> these pieces of code in classes which are added to some registry
> (like the databinding registry), or whether it would be better to have
> one, master, order in which the exception to fault
> mapping is assumed to take place in Tuscany.
>
> I coded up a parallel modification in WSDL introspection in the class:
> org.apache.tuscany.sca.interfacedef.wsdl.introspect.WSDLOperation.
> Basically I just need to set "FaultException" as the exceptionPhysical on
> top of what had been done, as the "logical" was being set just fine
> already.
>
>
> ------------------------------------------------------------------------------
>
> So, this is getting long........
>
> Where I see this going from here is.. if this sounds interesting to
> people, it would be interesting to try incorporating
> the Axis2 exc->fault mapping pattern with the example from the recent JIRA
> Simon worked on into this new view I'm working on.
>
> Another pattern I could imagine would be the one mentioned in JAX-WS Sec.
> 3.7 in cases in which the exceptions don't conform to the Sec 2.5 pattern.
>
> And it might be that my point about "decoupling" is only partially
> right. Maybe the POJO exception case will always be associated
> withJavaBeans DB
> and maybe the JAX-WS Sec 3.7 case will always be associated withJAXB.
>
> However, I wanted to get this posted before thinking through all those
> permutations.
>
> Thanks,
> Scott
>
>
>
>
>
>