But that spec extract says nothing about how to handle exceptions, the key bit being line 227 which explicitly leaves this out, as does the current OASIS versions of the spec. I did ask the spec guys about this once a while back (not on any mailing list so I can't provide a link) the answer was that as JMS doesn't have any standard definition of fault messages so the SCA JMS spec doesn't define anything here either and how to handle this is SCA runtime specific. (as a slight aside, line 227 already makes the JMS spec inconsistent with JAXWS as a return value is unwrapped XML not wrapped, not sure our current wireformat is doing that correctly). I'm missing the reason this could be considered a "backdoor", its not like doing this would open up any vulnerabilities that i can see so a backdoor to where?
Anyway, what to do for 1.4? We did support non-JAXWS exceptions in previous releases so wouldn't it be better to continue doing that in 1.x and perhaps if we really do want to change this then to do it only in 2.x? ...ant On Wed, Jan 7, 2009 at 9:14 PM, Raymond Feng <[email protected]> wrote: > IMO, the wire format controls how business data and/or fault are > represented in the JMSMessage. The following is quoted from the OSOA JMS > binding spec 1.0: > > 217 1.5.2 Default Data Binding > 218 The default data binding behavior maps between a JMSMessage and the > object(s) expected by > 219 the component implementation. We encourage component implementers to > avoid exposure of > 220 JMS APIs to component implementations, however in the case of an > existing implementation that > 221 expects a JMSMessage, this provides for simple reuse of that as an SCA > component. > 222 The message body is mapped to the parameters or return value of the > target operation as > 223 follows: > 224 . If there is a single parameter or return value that is a JMSMessage, > then the JMSMessage is > 225 passed as is. > 226 . Otherwise, the JMSMessage must be a JMS text message containing XML. > 227 . If there is a single parameter, or for the return value, the JMS text > XML payload is the XML > 228 serialization of that parameter according to the WSDL schema for the > message. > 229 . If there are multiple parameters, then they are encoded in XML using > the document wrapped > 230 style, according to the WSDL schema for the message. > > And the SCA java spec says: > > 1715 1.9. WSDL to Java and Java to WSDL > 1716 The SCA Client and Implementation Model for Java applies the WSDL to > Java and Java to WSDL mapping > 1717 rules as defined by the JAX-WS specification [4] for generating > remotable Java interfaces from WSDL > 1718 portTypes and vice versa. > > Based on this, my assumption is for text/xml wire format, we follow the > Java to WSDL mapping rules defined by JAXWS. It should also apply to fault > data. Passing exceptions as Objects in JMSMessage seems to be a backdoor and > it is not consistent with the wire format. It requires both client and > service side have the same CheckedException class. > > Thanks, > Raymond > > From: ant elder > Sent: Wednesday, January 07, 2009 12:02 PM > > To: [email protected] > Subject: Re: [1.4] Change in Exception handling behaviour for binding.jms > > > Ok, looks like we are getting to the bottom of this, those two points are > exactly what and why it worked in previous releases ;) > > The JMS spec doesn't define how to handle exceptions so there's nothing > that says the exception needs to follow the JAXWS pattern and ideally it > shouldn't need to. The TransportServiceInterceptor creates a > JMSObjectMessage to return the exception as in the previous releases thats > how this was able to work - it didn't delegate everything to the databinding > framework so the on the client side the invoke spotted the response was an > exception and didn't use the databinding framework to do any transformations > but just returned the received exception. > > As we know the exception response wont be XML so wont need a databinding > framework transformation could we prevent the transformation happening by > changing the WireFormatJMSTextXMLReferenceProvider constructor around line > 82 to not reset the datatype of the fault types to OMElement? > > ...ant > > > On Wed, Jan 7, 2009 at 7:37 PM, Raymond Feng <[email protected]> wrote: > > Hi, > > 1) The org.apache.tuscany.sca.binding.jms.ExceptionService interface is > remotable but the CheckedException is a plain java exception and it doesn't > follow the JAXWS pattern to represent a fault. In this case, the > construction of the ChjeckedException is heuristic. > > 2) I further debugged the root cause of the null faultInfo. On the > following stack, it seems that WireFormatJMSTextXMLServiceInterceptor is not > doing its job to correctly marshal the fault data into the response JMS > message. Even though the wireFormat is textXML, the > TransportServiceInterceptor catches the exception, creates a > JMSObjectMessage, sets the exception as an Object and sends it back as a > response. The WireFormatJMSTextXMLServiceInterceptor doesn't have a chance > to format the fault JMSMessage as textXML. > > Thanks, > Raymond > > Thread [ActiveMQ Session Task] (Suspended (breakpoint at line 25 in > ExceptionServiceImpl)) > ExceptionServiceImpl.throwChecked() line: 25 > NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not > available [native method] > NativeMethodAccessorImpl.invoke(Object, Object[]) line: 79 > DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43 > Method.invoke(Object, Object...) line: 618 > JavaImplementationInvoker.invoke(Message) line: 132 > DataTransformationInterceptor.invoke(Message) line: 78 > > RuntimeWireInvoker.invoke(InvocationChain, Message, RuntimeWire) line: 129 > RuntimeWireInvoker.invoke(RuntimeWire, Operation, Message) line: 104 > RuntimeWireInvoker.invoke(Operation, Message) line: 98 > RuntimeWireInvoker.invoke(Message) line: 86 > WireFormatJMSTextXMLServiceInterceptor.invoke(Message) line: 68 > OperationSelectorJMSDefaultServiceInterceptor.invoke(Message) line: 78 > TransportServiceInterceptor.invoke(Message) line: 77 > RuntimeWireImpl.invoke(Message) line: 149 > RRBJMSBindingListener.invokeService(Message) line: 100 > RRBJMSBindingListener.onMessage(Message) line: 76 > ActiveMQMessageConsumer.dispatch(MessageDispatch) line: 1021 > ActiveMQSessionExecutor.dispatch(MessageDispatch) line: 122 > ActiveMQSessionExecutor.iterate() line: 192 > PooledTaskRunner.runTask() line: 122 > PooledTaskRunner$1.run() line: 43 > > ThreadPoolExecutor$Worker.runTask(Runnable) line: 665 > ThreadPoolExecutor$Worker.run() line: 690 > Thread.run() line: 810 > > > > From: ant elder > Sent: Wednesday, January 07, 2009 10:30 AM > To: [email protected] > Subject: Re: [1.4] Change in Exception handling behaviour for binding.jms > > > To show what I mean i've committed some fixes in r732415 and r732416 which > get the testcase working, this isn't a finished fix it just to show where > the code is going wrong. I haven't looked at the JAXWSFaultExceptionMapper > code in any detail, should it be dealing with a null faultInfo is is the bug > that faultInfo isn't getting setup correctly? > > ...ant > > > On Wed, Jan 7, 2009 at 6:16 PM, ant elder <[email protected]> wrote: > > It turns out its a bit more complicated that that, i think it is the > FaultException that needs to be returned up the chain so that the > databinding can transform that back into the user exception, and there is a > bug in AbstractMessageProcessor either the createFaultMessage or > extractPayloadMessage needs to pull the FaultException out of the > InvocationTargetException, but then fixing that the > JAXWSFaultExceptionMapper gets an NPE on line 129 as faultInfo is null. > > Does that all sound plausible? > > ...ant > > > On Wed, Jan 7, 2009 at 5:39 PM, Raymond Feng <[email protected]> wrote: > > IIRC, we intentionally return a FaultException to wrap the user exception > from the transformation to indicate there is a user fault. The > extractPayloadMessage should extract the user exception from the > FaultException. > > Thanks, > Raymond > > > From: ant elder > Sent: Wednesday, January 07, 2009 9:33 AM > To: Raymond Feng > Cc: [email protected] > Subject: Re: [1.4] Change in Exception handling behaviour for binding.jms > > > OK that helps, but also debugging there you see its too late at that point > as the service response message sent back from the service already contains > the wrong exception. Debugging on the service side this is the stack from > where it goes wrong: > > Thread [ActiveMQ Session Task] (Suspended) > DataTransformationInterceptor.invoke(Message) line: 159 > RuntimeWireInvoker.invoke(InvocationChain, Message, RuntimeWire) line: > 129 > RuntimeWireInvoker.invoke(RuntimeWire, Operation, Message) line: 104 > RuntimeWireInvoker.invoke(Operation, Message) line: 98 > RuntimeWireInvoker.invoke(Message) line: 86 > WireFormatJMSTextXMLServiceInterceptor.invoke(Message) line: 68 > OperationSelectorJMSDefaultServiceInterceptor.invoke(Message) line: 78 > TransportServiceInterceptor.invoke(Message) line: 77 > RuntimeWireImpl.invoke(Message) line: 149 > RRBJMSBindingListener.invokeService(Message) line: 100 > RRBJMSBindingListener.onMessage(Message) line: 76 > ActiveMQMessageConsumer.dispatch(MessageDispatch) line: 1021 > ActiveMQSessionExecutor.dispatch(MessageDispatch) line: 122 > ActiveMQSessionExecutor.iterate() line: 192 > PooledTaskRunner.runTask() line: 122 > PooledTaskRunner$1.run() line: 43 > ThreadPoolExecutor$Worker.runTask(Runnable) line: not available > ThreadPoolExecutor$Worker.run() line: not available > Thread.run() line: not available > > Before DataTransformationInterceptor.invoke(Message) line: 159 is run the > "result" variable contains the correct original application exception and > thats what we'd like gets sent back to the clinet, but after > transformException is called at line 160 "newResult" is a > org.apache.tuscany.sca.interfacedef.util.FaultException instance and that is > whats returned to the client. > > Is this related to the value of sourceFaultType which is: > > sourceFaultType DataTypeImpl<L> (id=265) > dataBinding "org.apache.axiom.om.OMElement" (id=282) > genericType Class<T> (java.lang.Object) (id=9) > logical XMLType (id=298) > metaDataMap null > physical Class<T> (java.lang.Object) (id=9) > > perhaps thats not correct with the way all the wireformats and databindings > are working now for JMS where really is just wanting to send back the > application exception in the response message? > > ...ant > > > > On Wed, Jan 7, 2009 at 4:40 PM, Raymond Feng <[email protected]> wrote: > > Hi, > > I debugged the test case and found the code on the following stack is > problematic: > > org.osoa.sca.ServiceRuntimeException: remote service exception, see nested > exception > at > org.apache.tuscany.sca.binding.jms.provider.AbstractMessageProcessor.extractPayloadFromJMSMessage(AbstractMessageProcessor.java:92) > at > org.apache.tuscany.sca.binding.jms.wireformat.jmstextxml.runtime.WireFormatJMSTextXMLReferenceInterceptor.invokeResponse(WireFormatJMSTextXMLReferenceInterceptor.java:107) > at > org.apache.tuscany.sca.binding.jms.wireformat.jmstextxml.runtime.WireFormatJMSTextXMLReferenceInterceptor.invoke(WireFormatJMSTextXMLReferenceInterceptor.java:82) > at > org.apache.tuscany.sca.binding.jms.provider.RRBJMSBindingInvoker.invoke(RRBJMSBindingInvoker.java:201) > at > org.apache.tuscany.sca.core.databinding.wire.DataTransformationInterceptor.invoke(DataTransformationInterceptor.java:78) > at > org.apache.tuscany.sca.core.invocation.JDKInvocationHandler.invoke(JDKInvocationHandler.java:287) > at > org.apache.tuscany.sca.core.invocation.JDKInvocationHandler.invoke(JDKInvocationHandler.java:154) > at $Proxy21.throwChecked(Unknown Source) > at > org.apache.tuscany.sca.binding.jms.ExceptionServiceClient.throwChecked(ExceptionServiceClient.java:38) > > When the JMSMessage contains a fault (user exception), the > AbstractMessageProcessor.extractPayloadFromJMSMessage() method should not > throw a ServiceRuntimeException, instead it should call Message.setFaultBody > with the user exception extracted from the FaultException. > > public Object extractPayloadFromJMSMessage(Message msg) { > try { > if (msg.getBooleanProperty(JMSBindingConstants.FAULT_PROPERTY)) { > // ----------------- [rfeng] This is wrong > ---------------------- > throw new ServiceRuntimeException("remote service exception, > see nested exception", (Throwable)((ObjectMessage)msg).getObject()); > } > } catch (JMSException e) { > throw new JMSBindingException(e); > } > return extractPayload(msg); > } > > Thanks, > Raymond > > > From: ant elder > Sent: Wednesday, January 07, 2009 4:24 AM > To: [email protected] > Subject: Re: [1.4] Change in Exception handling behaviour for binding.jms > > > > > > > On Wed, Jan 7, 2009 at 11:12 AM, Dave Sowerby <[email protected]> > wrote: > > Hey guys, > > I'm trying to upgrade an application from Tuscany 1.3.2 to 1.4 RC4, > the application uses binding.jms and I've noticed a marked change in > behaviour for Exception handling - could someone tell me if this is > expected and if there is any means of getting a handle on the original > Exception? > > Basically, the service throws a UserException with a message, but on > the client side I get the following Exception hierarchy: > > org.osoa.sca.ServiceRuntimeException > -> org.osoa.sca.ServiceRuntimeException > -> java.lang.reflect.InvocationTargetException > -> org.apache.tuscany.sca.interfacedef.util.FaultException > > Where the FaultException contains the original message from the > UserException. > > Back in 1.3.2, for Exceptions the client would have a reconsituted > equivilant of the original Exception thrown. > > Any guidance would be greatly appreciated, > > Cheers, > > Dave. > > > That sounds like http://issues.apache.org/jira/browse/TUSCANY-2593 which > sadly although marked as a blocker didn't get fixed in the 1.4 RC. > > The problem is due to the way the DataTransformationInterceptor handles the > exception is different now so the way the JMS binding returns the service > exception doesn't get returned to the client as before. Tracing through the > code i can get it to DataTransformationInterceptor line 147 where the > sourceDataType gets set to > org.apache.tuscany.sca.interfacedef.util.FaultException which is what the > transform on line 159 produces so the original exception from the remote > service is lost. > > There's quite a few FIXME comments around here in the > DataTransformationInterceptor so i'm not sure how this is supposed to work, > you'd think it must be common across all bindings - does any one know is > there a fixed way a binding can return an application checked exception > object and have the data binding framework just return that to the client? > > ...ant >
