You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Gary Gregory <GG...@seagullsoftware.com> on 2009/12/18 10:13:29 UTC

Inflexible fault interceptor chain?

Hi All:

I need to apply an XSL transformation to messages coming out of CXF (our users configure what the XSL looks like.) For a normal (successful) message, I have an interceptor (during Phase.PRE_MARSHAL) that uses the DOM aspect of a message. That works great. BTW, I get to the DOM like this:

Node node = (Node) message.getContent(List.class).get(0);

That seems brittle, is there a safer way to get to an aspect of the message I can feed to javax.xml.transform?

The real issue comes with fault messages because the fault chain uses an XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html>. The fault chain looks like this:

Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current flow:
  setup [ServerPolicyOutFaultInterceptor]
  prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
  pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*, StaxOutInterceptor]
  pre-protocol [WebFaultOutInterceptor, SOAPHandlerFaultOutInterceptor]
  write [SoapOutInterceptor]
  pre-marshal [LogicalHandlerFaultOutInterceptor]
  marshal [Soap11FaultOutInterceptorInternal]
  pre-stream-ending [StaxOutEndingInterceptor, TransformOutFaultInterceptor*]
  prepare-send-ending [MessageSenderEndingInterceptor]

FYI, the interceptors marked with * are our own:

*         XmlDeclOutInterceptor forces an XML declaration to be written.

*         TransformOutFaultInterceptor is where I thought I could transform the fault XML message.

The XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> looks like this:

[StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter, underlying outputter: com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<ma...@1125cf44>

The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a org.apache.cxf.io.CachedOutputStream, which in turns wraps:

*         currentStream - LoadingByteArrayOutputStream

*         flowThroughStream - AbstractHTTPDestination$WrappedOutputStream

All of this to say that when the chain's interceptors are working with the message's XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html>, the bytes are cached and written to the wire. It is not possible to catch the fault XML message and change it.

The only thing I've come up with but not implemented yet would be to insert an interceptor before the XML declaration is written and put the XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> into a temp spot in the message content map, then put a new XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> on a byte array in its place. A pre-stream-ending interceptor can take those bytes, apply XSL to them and then write them to the original XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html>, before putting the original XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> back in it original slot in the message content map.

That seems like big old hack.

Any ideas on a cleaner solution?

Thank you,
Gary Gregory
Seagull Software
ggregory@seagullsoftware.com
www.seagullsoftware.com


Re: Inflexible fault interceptor chain?

Posted by Daniel Kulp <dk...@apache.org>.
On Tue December 22 2009 4:30:30 pm Gary Gregory wrote:
> Hi All:
> 
> I am trying to build SVN 2.2.x (I just updated from SVN) to test a patch (I
>  do not have a test yet) just to see what happens if SAAJOutInterceptor
>  uses a W3CDOMStreamWriter even if the local variable is null. Since that
>  caused a test to hang I thought I'd try to build an unchanged 2.2.6 as a
>  baseline. I get the errors below when I run:
> 
> mvn clean install -Peverything
> 
> Does 2.2.x build ok for anyone out there?

The automatic builds we have running in Hudson seem to be fine:

http://hudson.zones.apache.org/hudson/view/CXF/

They also just worked for me.   Not sure what to suggest.   :-(



Dan


> 
> Results :
> 
> Failed tests:
>  
>  testExcludeNSWithPackageName(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugT
> est)
>  testBug305924ForNestedBinding(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBug
> Test)
>  testParameterOrderNoOutputMessage(org.apache.cxf.tools.wsdlto.jaxws.CodeGe
> nBugTest)
>  testParameterOrderDifferentNS(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBug
> Test)
> 
> Tests in error:
>  
>  testHelloWorldExternalBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGe
> nOptionTest)
>  testFlagForGenStandAlone(org.apache.cxf.tools.wsdlto.jaxws.CodeGenOptionTe
> st)
>  testFlagForGenAdditional(org.apache.cxf.tools.wsdlto.jaxws.CodeGenOptionTe
> st)
>  testHeaderFromAnotherMessage1(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTes
> t)
>  testHeaderFromAnotherMessage2(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTes
> t)
>  testHeaderFromAnotherMessage3(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTes
> t)
>  testHeaderFromAnotherMessage4(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTes
> t)
>  testHeaderFromAnotherMessage5(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTes
> t) testRPCLit(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testAsyncMethod(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testAsyncMethodNoService(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testHelloWorldSoap12(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testHelloWorld(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>  
>  testHelloWorldWithDummyPlugin(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTes
> t) testDocLitHolder(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testSchemaImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testExceptionNameCollision(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testAllNameCollision(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testImportNameCollision(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testSoapHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testHolderHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testWSAddress(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testVoidInOutMethod(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testWsdlImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testWebFault(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testMultiSchemaParsing(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testDefaultParameterOrder(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testSupportXMLBindingBare(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>  
>  testSupportXMLBindingWrapped(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest
> ) testRouterWSDL(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>  
>  testWSDLContainsJavaKeywords(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest
> ) testWSDLWithEnumType(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>  testSWAMime(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testRPCHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testRefTNS(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testWebFaultAnnotaion(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testGlobalBinding(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testXmlSeeAlso(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testWSAction(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testHandlerAnnotation(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testGenerateXmlListAnno(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testWrapperWithWildcard(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testCXF1950(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
>   testLogicalOnlyWSDL(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testBug305729(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testBug305773(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testBug305700(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  
>  testNamespacePackageMapping1(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugT
> est)
>  testNamespacePackageMapping2(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugT
> est)
>  testNamespacePackageMapping3(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugT
> est) testBug305772(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCommandLine(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  
>  testLocatorWithJaxbBinding(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTes
> t) testWsdlNoService(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  testNoServiceImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  testServiceNS(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testNoServiceNOPortType(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testDefatultNsMap(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  
>  testDefatultNsMapExclude(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  testHelloWorldExternalBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGe
> nBugTest) testWebResult(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCXF627(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testRecursiveImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCXF804(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testDefinieServiceName(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testAntFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testAsyncImplAndClient(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  
>  testZeroInputOutOfBandHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugT
> est)
>  testBindingForImportWSDL(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  testReuseJaxwsBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest
> ) testBindingXPath(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  testJaxbCatalog(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>  testCatalog2(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCatalog3(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testServer(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testTwoJaxwsBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testJaxwsBindingJavaDoc(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testWSAActionAnno(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCXF964(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCXF1620(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testCXF1048(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
>   testJaxbNpa(org.apache.cxf.tools.wsdlto.jaxb.JAXBCodeGenOptionTest)
> 
> Tests run: 124, Failures: 4, Errors: 82, Skipped: 1
> 
> > -----Original Message-----
> > From: Daniel Kulp [mailto:dkulp@apache.org]
> > Sent: Tuesday, December 22, 2009 10:06
> > To: users@cxf.apache.org
> > Cc: Gary Gregory
> > Subject: Re: Inflexible fault interceptor chain?
> >
> >
> > Can you create a small test case and attach to a jira?
> >
> > This definitely sounds like bug of some sort.   When I redid the
> > Provider
> > based services, I noticed that strange code in the StaxOutInterceptor
> > as well
> > and tried to remove it.   However, that broke some of the JAX-WS tck
> > tests.
> > I don't remember the exact reason.   I think it has something to do
> > with
> > faults thrown from the logical or soap handlers on the outgoing chain
> > needed
> > some strange and wacky processing.     Don't really remember.
> >
> > If we can get your test case, we may be able to get it to work better.
> >
> > That said, you could probably write your own interceptor (you seem to
> > be good
> > at that :-)  that would run on the fault chain prior to the SAAJOut and
> > have
> > it remove the SAAJ model from the message.   You may need to trace
> > through a
> > couple other interceptors (like SoapOutInterceptor) to see if other
> > properties
> > need to be removed/reset.
> >
> > Dan
> >
> > On Mon December 21 2009 8:12:50 pm Gary Gregory wrote:
> > > Hello Dan and all,
> > >
> > > Ok, the SAAJOutInterceptor solution almost worked. The behavior I
> >
> > describe
> >
> > >  below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of Saturday's
> > >  build). I am not on 2.2.5 due to some bugs that are fixed in 2.2.6.
> >
> > The
> >
> > >  debugging information I gathered for this message is with 2.2.4.
> > >
> > > I have two scenarios, one works and one does not with the
> > >  SAAJOutInterceptor solution.
> > >
> > > If a Fault is thrown by a custom interceptor at a certain point in
> >
> > the
> >
> > >  output chain, the wrong SOAP XML is generated, specifically no SOAP
> >
> > fault
> >
> > >  XML elements are generated. Let me start by showing what works and
> >
> > why
> >
> > >  before showing what does not and why.
> > >
> > > In the first scenario, which works, a SoapFault is thrown by our
> >
> > provider's
> >
> > >  invoke(SOAPMessage) method under certain conditions, basically if
> >
> > our
> >
> > >  server detects certain errors. Our provider looks like this:
> > >
> > > @WebServiceProvider
> > > @ServiceMode(value = Service.Mode.MESSAGE)
> > > public static class LdeWebServiceProvider implements
> >
> > Provider<SOAPMessage>
> >
> > >  { @Override
> > >    public SOAPMessage invoke(SOAPMessage soapRequest) {
> > >       ...
> > >       throw new SoapFault("Our message",
> > >  Soap11.getInstance().getReceiver()); }
> > > }
> > >
> > > In SAAJOutInterceptor.handleMessage, the local variable saaj is null,
> >
> > so
> >
> > >  the code path taken builds a SOAP message from scratch and plugs in
> >
> > a
> >
> > >  W3CDOMStreamWriter. All of the interceptors then write to
> > >  W3CDOMStreamWriter instead of the default XMLStreamWriter which
> >
> > normally
> >
> > >  caches and writes to the HTTP wire. The W3CDOMStreamWriter allows me
> >
> > to
> >
> > >  transform the DOM before it gets on the wire. Great stuff, it works.
> > >
> > > In the second scenario, I test our output feature where in addition
> >
> > to an
> >
> > >  optional transformation, we have custom interceptors to do optional
> >
> > XML
> >
> > >  validation before and after the XML transformation. After our
> >
> > provider
> >
> > >  successfully processed a message, the output chain processing kicks
> >
> > in and
> >
> > >  looks like this:
> > >
> > > Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current
> >
> > flow:
> > >   setup [PolicyOutInterceptor]
> > >   pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
> > >   post-logical [SoapPreProtocolOutInterceptor]
> > >   prepare-send [MessageSenderInterceptor, MessageModeOutInterceptor]
> > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > >  AttachmentOutInterceptor, StaxOutInterceptor] pre-protocol
> > >  [MessageModeOutInterceptorInternal, SAAJOutInterceptor,
> > >  SOAPHandlerInterceptor, OurWSS4JOutInterceptor] write
> >
> > [SoapOutInterceptor]
> >
> > >   pre-marshal [LogicalHandlerOutInterceptor,
> >
> > ValidatingOutInterceptor*,
> >
> > >  TransformOutInterceptor*, ValidatingOutInterceptor*] marshal
> > >  [BareOutInterceptor]
> > >   write-ending [SoapOutEndingInterceptor]
> > >   pre-protocol-ending [SAAJOutEndingInterceptor]
> > >   pre-stream-ending [StaxOutEndingInterceptor]
> > >   prepare-send-ending [MessageSenderEndingInterceptor]
> > >
> > > The interceptors marked with * are mine:
> > > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > > - ValidatingOutInterceptor validates XML
> > > - TransformOutInterceptor transforms XML
> > > - ValidatingOutInterceptor validates XML
> > >
> > > The problem occurs if XML validation fails (the first validation in
> >
> > this
> >
> > >  test).
> > >
> > > When the XML validation fails, an exception thrown, caught, and re-
> >
> > thrown
> >
> > >  as a fault.
> > >
> > > At the start of fault processing, the chain when SAAJOutInterceptor
> >
> > is
> >
> > >  called looks like this:
> > >
> > >   Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f. Current
> >
> > flow:
> > >   setup [ServerPolicyOutFaultInterceptor]
> > >   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
> > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > >  SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor] write
> > >  [SoapOutInterceptor]
> > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > >   marshal [Soap11FaultOutInterceptorInternal]
> > >   pre-protocol-ending [TransformOutFaultInterceptor*]
> > >   prepare-send-ending [MessageSenderEndingInterceptor]
> > >
> > > The interceptors marked with * are mine:
> > > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > > - TransformOutFaultInterceptor validates XML
> > >
> > > When I step through this SAAJOutInterceptor invocation, the saaj
> >
> > variable
> >
> > >  is NOT null, so the code path taken is different from what I
> >
> > described
> >
> > >  above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is
> >
> > created
> >
> > >  that throws away whatever is written to it:
> > >
> > >             //as the SOAPMessage already has everything in place, we
> >
> > do not
> >
> > >  need XMLStreamWriter to write //anything for us, so we just set
> > >  XMLStreamWriter's output to a dummy output stream. XMLStreamWriter
> > >  origWriter = message.getContent(XMLStreamWriter.class);
> > >  message.put(ORIGINAL_XML_WRITER, origWriter);
> > >
> > >             XMLStreamWriter dummyWriter =
> > >  StaxUtils.createXMLStreamWriter(new OutputStream() { public void
> >
> > write(int
> >
> > >  b) throws IOException {
> > >                     }
> > >                     public void write(byte b[], int off, int len)
> >
> > throws
> >
> > >  IOException { }
> > >                 });
> > >             message.setContent(XMLStreamWriter.class, dummyWriter);
> > >
> > > No wonder I get no SOAP fault information back, I get:
> > >
> > > <?xml version='1.0' encoding='ISO-8859-1'?>
> > > <SOAP-ENV:Envelope
> > >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
> > >  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-
> >
> > ENV:Header
> >
> > >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
> >
> > <ais:requestID
> >
> > xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80
> > 102
> >
> > > -00ce16ad0000010e75da25398002}</ais:requestID> </SOAP-ENV:Header>
> > >     <SOAP-ENV:Body xmlns:SOAP-
> >
> > ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >
> > >  /> </SOAP-ENV:Envelope>
> > >
> > > Is this a bug? Why would there be a dummy writer put in place? Is
> >
> > there
> >
> > >  another CXF way to do this?
> > >
> > > Thank you,
> > > Gary
> > >
> > > > -----Original Message-----
> > > > From: Gary Gregory
> > > > Sent: Friday, December 18, 2009 18:11
> > > > To: 'Daniel Kulp'; users@cxf.apache.org
> > > > Subject: RE: Inflexible fault interceptor chain?
> > > >
> > > > Ok, that worked!
> > > >
> > > > Thank you Dan,
> > > > Gary
> > > >
> > > > > -----Original Message-----
> > > > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > > > Sent: Friday, December 18, 2009 07:33
> > > > > To: users@cxf.apache.org
> > > > > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > > > > Subject: Re: Inflexible fault interceptor chain?
> > > > >
> > > > >
> > > > > Honestly, the EASIEST way to accomplish this, since you are using
> > > >
> > > > soap,
> > > >
> > > > > is to
> > > > > add the SAAJOutInterceptor to the fault chain.  Then, your
> > > >
> > > > interceptor
> > > >
> > > > > would
> > > > > live right before it's "ending" interceptor and do:
> > > > >
> > > > > message.getContext(SOAPMessage.class)
> > > > >
> > > > > to get the SAAJ model out.   Since the SAAJ model implements the
> >
> > DOM
> >
> > > > > interfaces, you can then feed that into an XSLT processor or
> >
> > similar
> >
> > > > to
> > > >
> > > > > transform it and then set a new version back with the setContent
> > > >
> > > > call.
> > > >
> > > > > Dan
> > > > >
> > > > > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > > > > Hi All:
> > > > > >
> > > > > > I need to apply an XSL transformation to messages coming out of
> >
> > CXF
> >
> > > > > (our
> > > > >
> > > > > >  users configure what the XSL looks like.) For a normal
> > > >
> > > > (successful)
> > > >
> > > > > >  message, I have an interceptor (during Phase.PRE_MARSHAL) that
> > > >
> > > > uses
> > > >
> > > > > the
> > > > >
> > > > > >  DOM aspect of a message. That works great. BTW, I get to the
> >
> > DOM
> >
> > > > > like
> > > > >
> > > > > >  this:
> > > > > >
> > > > > > Node node = (Node) message.getContent(List.class).get(0);
> > > > > >
> > > > > > That seems brittle, is there a safer way to get to an aspect of
> >
> > the
> >
> > > > > message
> > > > >
> > > > > >  I can feed to javax.xml.transform?
> > > > > >
> > > > > > The real issue comes with fault messages because the fault
> >
> > chain
> >
> > > > uses
> > > >
> > > > > an
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html>. The fault chain looks like this:
> > > > > >
> > > > > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303.
> >
> > Current
> >
> > > > > flow:
> > > > > >   setup [ServerPolicyOutFaultInterceptor]
> > > > > >   prepare-send [MessageSenderInterceptor,
> > > >
> > > > Soap11FaultOutInterceptor]
> > > >
> > > > > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > > > > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > > > > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > > > > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > > > > >   marshal [Soap11FaultOutInterceptorInternal]
> > > > > >   pre-stream-ending [StaxOutEndingInterceptor,
> > > > > >  TransformOutFaultInterceptor*] prepare-send-ending
> > > > > >  [MessageSenderEndingInterceptor]
> > > > > >
> > > > > > FYI, the interceptors marked with * are our own:
> > > > > >
> > > > > > *         XmlDeclOutInterceptor forces an XML declaration to be
> > > > >
> > > > > written.
> > > > >
> > > > > > *         TransformOutFaultInterceptor is where I thought I
> >
> > could
> >
> > > > > transform
> > > > >
> > > > > >  the fault XML message.
> > > > > >
> > > > > > The
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> looks like this:
> > > > > >
> > > > > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> > > >
> > > > underlying
> > > >
> > > > > >  outputter:
> >
> > com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> >
> > > > > ati
> > > > >
> > > > > > n1XmlWriter@1125cf44>
> > > > > >
> > > > > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > > > > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > > > > >
> > > > > > *         currentStream - LoadingByteArrayOutputStream
> > > > > >
> > > > > > *         flowThroughStream -
> > > > >
> > > > > AbstractHTTPDestination$WrappedOutputStream
> > > > >
> > > > > > All of this to say that when the chain's interceptors are
> >
> > working
> >
> > > > > with the
> > > > >
> > > > > >  message's
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html>, the bytes are cached and written to the
> >
> > wire.
> >
> > > > It
> > > >
> > > > > is not
> > > > >
> > > > > >  possible to catch the fault XML message and change it.
> > > > > >
> > > > > > The only thing I've come up with but not implemented yet would
> >
> > be
> >
> > > > to
> > > >
> > > > > insert
> > > > >
> > > > > >  an interceptor before the XML declaration is written and put
> >
> > the
> >
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> into a temp spot in the message content map,
> > > >
> > > > then
> > > >
> > > > > put a
> > > > >
> > > > > >  new
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> on a byte array in its place. A pre-stream-
> > > >
> > > > ending
> > > >
> > > > > >  interceptor can take those bytes, apply XSL to them and then
> >
> > write
> >
> > > > > them to
> > > > >
> > > > > >  the original
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html>, before putting the original
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> back in it original slot in the message
> >
> > content
> >
> > > > > map.
> > > > >
> > > > > > That seems like big old hack.
> > > > > >
> > > > > > Any ideas on a cleaner solution?
> > > > > >
> > > > > > Thank you,
> > > > > > Gary Gregory
> > > > > > Seagull Software
> > > > > > ggregory@seagullsoftware.com
> > > > > > www.seagullsoftware.com
> > > > >
> > > > > --
> > > > > Daniel Kulp
> > > > > dkulp@apache.org
> > > > > http://www.dankulp.com/blog
> >
> > --
> > Daniel Kulp
> > dkulp@apache.org
> > http://www.dankulp.com/blog
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
Hi All:

I am trying to build SVN 2.2.x (I just updated from SVN) to test a patch (I do not have a test yet) just to see what happens if SAAJOutInterceptor uses a W3CDOMStreamWriter even if the local variable is null. Since that caused a test to hang I thought I'd try to build an unchanged 2.2.6 as a baseline. I get the errors below when I run:

mvn clean install -Peverything

Does 2.2.x build ok for anyone out there?

Results :

Failed tests:
  testExcludeNSWithPackageName(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBug305924ForNestedBinding(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testParameterOrderNoOutputMessage(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testParameterOrderDifferentNS(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)

Tests in error:
  testHelloWorldExternalBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenOptionTest)
  testFlagForGenStandAlone(org.apache.cxf.tools.wsdlto.jaxws.CodeGenOptionTest)
  testFlagForGenAdditional(org.apache.cxf.tools.wsdlto.jaxws.CodeGenOptionTest)
  testHeaderFromAnotherMessage1(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHeaderFromAnotherMessage2(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHeaderFromAnotherMessage3(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHeaderFromAnotherMessage4(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHeaderFromAnotherMessage5(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testRPCLit(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testAsyncMethod(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testAsyncMethodNoService(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHelloWorldSoap12(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHelloWorld(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHelloWorldWithDummyPlugin(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testDocLitHolder(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testSchemaImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testExceptionNameCollision(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testAllNameCollision(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testImportNameCollision(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testSoapHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHolderHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWSAddress(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testVoidInOutMethod(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWsdlImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWebFault(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testMultiSchemaParsing(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testDefaultParameterOrder(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testSupportXMLBindingBare(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testSupportXMLBindingWrapped(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testRouterWSDL(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWSDLContainsJavaKeywords(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWSDLWithEnumType(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testSWAMime(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testRPCHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testRefTNS(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWebFaultAnnotaion(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testGlobalBinding(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testXmlSeeAlso(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWSAction(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testHandlerAnnotation(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testGenerateXmlListAnno(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testWrapperWithWildcard(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testCXF1950(org.apache.cxf.tools.wsdlto.jaxws.CodeGenTest)
  testLogicalOnlyWSDL(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBug305729(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBug305773(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBug305700(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testNamespacePackageMapping1(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testNamespacePackageMapping2(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testNamespacePackageMapping3(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBug305772(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCommandLine(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testLocatorWithJaxbBinding(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testWsdlNoService(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testNoServiceImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testServiceNS(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testNoServiceNOPortType(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testDefatultNsMap(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testDefatultNsMapExclude(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testHelloWorldExternalBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testWebResult(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCXF627(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testRecursiveImport(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCXF804(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testDefinieServiceName(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testAntFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testAsyncImplAndClient(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testZeroInputOutOfBandHeader(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBindingForImportWSDL(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testReuseJaxwsBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testBindingXPath(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testJaxbCatalog(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCatalog2(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCatalog3(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testServer(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testTwoJaxwsBindingFile(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testJaxwsBindingJavaDoc(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testWSAActionAnno(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCXF964(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCXF1620(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testCXF1048(org.apache.cxf.tools.wsdlto.jaxws.CodeGenBugTest)
  testJaxbNpa(org.apache.cxf.tools.wsdlto.jaxb.JAXBCodeGenOptionTest)

Tests run: 124, Failures: 4, Errors: 82, Skipped: 1

> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Tuesday, December 22, 2009 10:06
> To: users@cxf.apache.org
> Cc: Gary Gregory
> Subject: Re: Inflexible fault interceptor chain?
>
>
> Can you create a small test case and attach to a jira?
>
> This definitely sounds like bug of some sort.   When I redid the
> Provider
> based services, I noticed that strange code in the StaxOutInterceptor
> as well
> and tried to remove it.   However, that broke some of the JAX-WS tck
> tests.
> I don't remember the exact reason.   I think it has something to do
> with
> faults thrown from the logical or soap handlers on the outgoing chain
> needed
> some strange and wacky processing.     Don't really remember.
>
> If we can get your test case, we may be able to get it to work better.
>
> That said, you could probably write your own interceptor (you seem to
> be good
> at that :-)  that would run on the fault chain prior to the SAAJOut and
> have
> it remove the SAAJ model from the message.   You may need to trace
> through a
> couple other interceptors (like SoapOutInterceptor) to see if other
> properties
> need to be removed/reset.
>
> Dan
>
>
> On Mon December 21 2009 8:12:50 pm Gary Gregory wrote:
> > Hello Dan and all,
> >
> > Ok, the SAAJOutInterceptor solution almost worked. The behavior I
> describe
> >  below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of Saturday's
> >  build). I am not on 2.2.5 due to some bugs that are fixed in 2.2.6.
> The
> >  debugging information I gathered for this message is with 2.2.4.
> >
> > I have two scenarios, one works and one does not with the
> >  SAAJOutInterceptor solution.
> >
> > If a Fault is thrown by a custom interceptor at a certain point in
> the
> >  output chain, the wrong SOAP XML is generated, specifically no SOAP
> fault
> >  XML elements are generated. Let me start by showing what works and
> why
> >  before showing what does not and why.
> >
> > In the first scenario, which works, a SoapFault is thrown by our
> provider's
> >  invoke(SOAPMessage) method under certain conditions, basically if
> our
> >  server detects certain errors. Our provider looks like this:
> >
> > @WebServiceProvider
> > @ServiceMode(value = Service.Mode.MESSAGE)
> > public static class LdeWebServiceProvider implements
> Provider<SOAPMessage>
> >  { @Override
> >    public SOAPMessage invoke(SOAPMessage soapRequest) {
> >       ...
> >       throw new SoapFault("Our message",
> >  Soap11.getInstance().getReceiver()); }
> > }
> >
> > In SAAJOutInterceptor.handleMessage, the local variable saaj is null,
> so
> >  the code path taken builds a SOAP message from scratch and plugs in
> a
> >  W3CDOMStreamWriter. All of the interceptors then write to
> >  W3CDOMStreamWriter instead of the default XMLStreamWriter which
> normally
> >  caches and writes to the HTTP wire. The W3CDOMStreamWriter allows me
> to
> >  transform the DOM before it gets on the wire. Great stuff, it works.
> >
> > In the second scenario, I test our output feature where in addition
> to an
> >  optional transformation, we have custom interceptors to do optional
> XML
> >  validation before and after the XML transformation. After our
> provider
> >  successfully processed a message, the output chain processing kicks
> in and
> >  looks like this:
> >
> > Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current
> flow:
> >   setup [PolicyOutInterceptor]
> >   pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
> >   post-logical [SoapPreProtocolOutInterceptor]
> >   prepare-send [MessageSenderInterceptor, MessageModeOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  AttachmentOutInterceptor, StaxOutInterceptor] pre-protocol
> >  [MessageModeOutInterceptorInternal, SAAJOutInterceptor,
> >  SOAPHandlerInterceptor, OurWSS4JOutInterceptor] write
> [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerOutInterceptor,
> ValidatingOutInterceptor*,
> >  TransformOutInterceptor*, ValidatingOutInterceptor*] marshal
> >  [BareOutInterceptor]
> >   write-ending [SoapOutEndingInterceptor]
> >   pre-protocol-ending [SAAJOutEndingInterceptor]
> >   pre-stream-ending [StaxOutEndingInterceptor]
> >   prepare-send-ending [MessageSenderEndingInterceptor]
> >
> > The interceptors marked with * are mine:
> > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > - ValidatingOutInterceptor validates XML
> > - TransformOutInterceptor transforms XML
> > - ValidatingOutInterceptor validates XML
> >
> > The problem occurs if XML validation fails (the first validation in
> this
> >  test).
> >
> > When the XML validation fails, an exception thrown, caught, and re-
> thrown
> >  as a fault.
> >
> > At the start of fault processing, the chain when SAAJOutInterceptor
> is
> >  called looks like this:
> >
> >   Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f. Current
> flow:
> >   setup [ServerPolicyOutFaultInterceptor]
> >   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> >  SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor] write
> >  [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> >   marshal [Soap11FaultOutInterceptorInternal]
> >   pre-protocol-ending [TransformOutFaultInterceptor*]
> >   prepare-send-ending [MessageSenderEndingInterceptor]
> >
> > The interceptors marked with * are mine:
> > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > - TransformOutFaultInterceptor validates XML
> >
> > When I step through this SAAJOutInterceptor invocation, the saaj
> variable
> >  is NOT null, so the code path taken is different from what I
> described
> >  above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is
> created
> >  that throws away whatever is written to it:
> >
> >             //as the SOAPMessage already has everything in place, we
> do not
> >  need XMLStreamWriter to write //anything for us, so we just set
> >  XMLStreamWriter's output to a dummy output stream. XMLStreamWriter
> >  origWriter = message.getContent(XMLStreamWriter.class);
> >  message.put(ORIGINAL_XML_WRITER, origWriter);
> >
> >             XMLStreamWriter dummyWriter =
> >  StaxUtils.createXMLStreamWriter(new OutputStream() { public void
> write(int
> >  b) throws IOException {
> >                     }
> >                     public void write(byte b[], int off, int len)
> throws
> >  IOException { }
> >                 });
> >             message.setContent(XMLStreamWriter.class, dummyWriter);
> >
> > No wonder I get no SOAP fault information back, I get:
> >
> > <?xml version='1.0' encoding='ISO-8859-1'?>
> > <SOAP-ENV:Envelope
> >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-
> ENV:Header
> >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
> <ais:requestID
> >
> xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80
> 102
> > -00ce16ad0000010e75da25398002}</ais:requestID> </SOAP-ENV:Header>
> >     <SOAP-ENV:Body xmlns:SOAP-
> ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >  /> </SOAP-ENV:Envelope>
> >
> > Is this a bug? Why would there be a dummy writer put in place? Is
> there
> >  another CXF way to do this?
> >
> > Thank you,
> > Gary
> >
> > > -----Original Message-----
> > > From: Gary Gregory
> > > Sent: Friday, December 18, 2009 18:11
> > > To: 'Daniel Kulp'; users@cxf.apache.org
> > > Subject: RE: Inflexible fault interceptor chain?
> > >
> > > Ok, that worked!
> > >
> > > Thank you Dan,
> > > Gary
> > >
> > > > -----Original Message-----
> > > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > > Sent: Friday, December 18, 2009 07:33
> > > > To: users@cxf.apache.org
> > > > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > > > Subject: Re: Inflexible fault interceptor chain?
> > > >
> > > >
> > > > Honestly, the EASIEST way to accomplish this, since you are using
> > >
> > > soap,
> > >
> > > > is to
> > > > add the SAAJOutInterceptor to the fault chain.  Then, your
> > >
> > > interceptor
> > >
> > > > would
> > > > live right before it's "ending" interceptor and do:
> > > >
> > > > message.getContext(SOAPMessage.class)
> > > >
> > > > to get the SAAJ model out.   Since the SAAJ model implements the
> DOM
> > > > interfaces, you can then feed that into an XSLT processor or
> similar
> > >
> > > to
> > >
> > > > transform it and then set a new version back with the setContent
> > >
> > > call.
> > >
> > > > Dan
> > > >
> > > > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > > > Hi All:
> > > > >
> > > > > I need to apply an XSL transformation to messages coming out of
> CXF
> > > >
> > > > (our
> > > >
> > > > >  users configure what the XSL looks like.) For a normal
> > >
> > > (successful)
> > >
> > > > >  message, I have an interceptor (during Phase.PRE_MARSHAL) that
> > >
> > > uses
> > >
> > > > the
> > > >
> > > > >  DOM aspect of a message. That works great. BTW, I get to the
> DOM
> > > >
> > > > like
> > > >
> > > > >  this:
> > > > >
> > > > > Node node = (Node) message.getContent(List.class).get(0);
> > > > >
> > > > > That seems brittle, is there a safer way to get to an aspect of
> the
> > > >
> > > > message
> > > >
> > > > >  I can feed to javax.xml.transform?
> > > > >
> > > > > The real issue comes with fault messages because the fault
> chain
> > >
> > > uses
> > >
> > > > an
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>. The fault chain looks like this:
> > > > >
> > > > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303.
> Current
> > > >
> > > > flow:
> > > > >   setup [ServerPolicyOutFaultInterceptor]
> > > > >   prepare-send [MessageSenderInterceptor,
> > >
> > > Soap11FaultOutInterceptor]
> > >
> > > > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > > > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > > > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > > > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > > > >   marshal [Soap11FaultOutInterceptorInternal]
> > > > >   pre-stream-ending [StaxOutEndingInterceptor,
> > > > >  TransformOutFaultInterceptor*] prepare-send-ending
> > > > >  [MessageSenderEndingInterceptor]
> > > > >
> > > > > FYI, the interceptors marked with * are our own:
> > > > >
> > > > > *         XmlDeclOutInterceptor forces an XML declaration to be
> > > >
> > > > written.
> > > >
> > > > > *         TransformOutFaultInterceptor is where I thought I
> could
> > > >
> > > > transform
> > > >
> > > > >  the fault XML message.
> > > > >
> > > > > The
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> looks like this:
> > > > >
> > > > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> > >
> > > underlying
> > >
> > > > >  outputter:
> > >
> > >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> > >
> > > > ati
> > > >
> > > > > n1XmlWriter@1125cf44>
> > > > >
> > > > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > > > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > > > >
> > > > > *         currentStream - LoadingByteArrayOutputStream
> > > > >
> > > > > *         flowThroughStream -
> > > >
> > > > AbstractHTTPDestination$WrappedOutputStream
> > > >
> > > > > All of this to say that when the chain's interceptors are
> working
> > > >
> > > > with the
> > > >
> > > > >  message's
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>, the bytes are cached and written to the
> wire.
> > >
> > > It
> > >
> > > > is not
> > > >
> > > > >  possible to catch the fault XML message and change it.
> > > > >
> > > > > The only thing I've come up with but not implemented yet would
> be
> > >
> > > to
> > >
> > > > insert
> > > >
> > > > >  an interceptor before the XML declaration is written and put
> the
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> into a temp spot in the message content map,
> > >
> > > then
> > >
> > > > put a
> > > >
> > > > >  new
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> on a byte array in its place. A pre-stream-
> > >
> > > ending
> > >
> > > > >  interceptor can take those bytes, apply XSL to them and then
> write
> > > >
> > > > them to
> > > >
> > > > >  the original
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>, before putting the original
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> back in it original slot in the message
> content
> > > >
> > > > map.
> > > >
> > > > > That seems like big old hack.
> > > > >
> > > > > Any ideas on a cleaner solution?
> > > > >
> > > > > Thank you,
> > > > > Gary Gregory
> > > > > Seagull Software
> > > > > ggregory@seagullsoftware.com
> > > > > www.seagullsoftware.com
> > > >
> > > > --
> > > > Daniel Kulp
> > > > dkulp@apache.org
> > > > http://www.dankulp.com/blog
> >
>
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

RE: [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor

Posted by Gary Gregory <GG...@seagullsoftware.com>.
> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Thursday, January 07, 2010 12:16
> To: users@cxf.apache.org
> Cc: Gary Gregory; ggregory@apache.org
> Subject: Re: [CXF-2594] No SOAP fault XML elements when a Fault is
> thrown in the output chain after SAAJOutInterceptor
> 
> On Thu January 7 2010 1:44:25 pm Gary Gregory wrote:
> > I updated to the latest from SVN and ran the unit tests attached to
> >  [CXF-2594] and it now works!
> >
> > My next question is: When can we expect a 2.2.6 release?
> 
> I'm hoping to do builds the week of the 18th sometime.  I need a
> release of
> jettison first though.   Hopefully I can convince Dejan to do that next
> week.
> 
> Dan

Sounds good. I am going to duplicate the unit test attached to [CXF-2594] and include it in our product build as a sanity check. I can clean up the test in the ticket as well if you want to use in the test suite. Let me know...

Gary

> 
> 
> >
> > Thank you,
> > Gary
> >
> > > -----Original Message-----
> > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > Sent: Thursday, January 07, 2010 07:48
> > > To: users@cxf.apache.org
> > > Cc: Gary Gregory; ggregory@apache.org
> > > Subject: Re: [CXF-2594] No SOAP fault XML elements when a Fault is
> > > thrown in the output chain after SAAJOutInterceptor
> > >
> > >
> > > I just committed some fixes to the unwind/handleFault logic in a
> couple
> > > interceptors that I think should fix this.   Can you check
> tomorrow's
> > > snapshots (or checkout the code and build today).
> > >
> > > Dan
> > >
> > > On Wed January 6 2010 3:04:51 pm Gary Gregory wrote:
> > > > Hi All,
> > > >
> > > > Has anyone gotten the chance to look at:
> > > >
> > > > [CXF-2594] No SOAP fault XML elements when a Fault is thrown in
> the
> > >
> > > output
> > >
> > > >  chain after SAAJOutInterceptor
> > > >  https://issues.apache.org/jira/browse/CXF-2594
> > > >
> > > > Thank you,
> > > > Gary
> > > > ---
> > > > Gary Gregory
> > > > Seagull Software
> > > > ggregory@seagullsoftware.com
> > > > www.seagullsoftware.com
> > > > ---
> > > > ggregory@apache.org
> > >
> > > --
> > > Daniel Kulp
> > > dkulp@apache.org
> > > http://www.dankulp.com/blog
> >
> 
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

Re: [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor

Posted by Daniel Kulp <dk...@apache.org>.
On Thu January 7 2010 1:44:25 pm Gary Gregory wrote:
> I updated to the latest from SVN and ran the unit tests attached to
>  [CXF-2594] and it now works!
> 
> My next question is: When can we expect a 2.2.6 release?

I'm hoping to do builds the week of the 18th sometime.  I need a release of 
jettison first though.   Hopefully I can convince Dejan to do that next week.

Dan


> 
> Thank you,
> Gary
> 
> > -----Original Message-----
> > From: Daniel Kulp [mailto:dkulp@apache.org]
> > Sent: Thursday, January 07, 2010 07:48
> > To: users@cxf.apache.org
> > Cc: Gary Gregory; ggregory@apache.org
> > Subject: Re: [CXF-2594] No SOAP fault XML elements when a Fault is
> > thrown in the output chain after SAAJOutInterceptor
> >
> >
> > I just committed some fixes to the unwind/handleFault logic in a couple
> > interceptors that I think should fix this.   Can you check tomorrow's
> > snapshots (or checkout the code and build today).
> >
> > Dan
> >
> > On Wed January 6 2010 3:04:51 pm Gary Gregory wrote:
> > > Hi All,
> > >
> > > Has anyone gotten the chance to look at:
> > >
> > > [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the
> >
> > output
> >
> > >  chain after SAAJOutInterceptor
> > >  https://issues.apache.org/jira/browse/CXF-2594
> > >
> > > Thank you,
> > > Gary
> > > ---
> > > Gary Gregory
> > > Seagull Software
> > > ggregory@seagullsoftware.com
> > > www.seagullsoftware.com
> > > ---
> > > ggregory@apache.org
> >
> > --
> > Daniel Kulp
> > dkulp@apache.org
> > http://www.dankulp.com/blog
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

RE: [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor

Posted by Gary Gregory <GG...@seagullsoftware.com>.
I updated to the latest from SVN and ran the unit tests attached to [CXF-2594] and it now works!

My next question is: When can we expect a 2.2.6 release?

Thank you,
Gary

> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Thursday, January 07, 2010 07:48
> To: users@cxf.apache.org
> Cc: Gary Gregory; ggregory@apache.org
> Subject: Re: [CXF-2594] No SOAP fault XML elements when a Fault is
> thrown in the output chain after SAAJOutInterceptor
> 
> 
> I just committed some fixes to the unwind/handleFault logic in a couple
> interceptors that I think should fix this.   Can you check tomorrow's
> snapshots (or checkout the code and build today).
> 
> Dan
> 
> 
> On Wed January 6 2010 3:04:51 pm Gary Gregory wrote:
> > Hi All,
> >
> > Has anyone gotten the chance to look at:
> >
> > [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the
> output
> >  chain after SAAJOutInterceptor
> >  https://issues.apache.org/jira/browse/CXF-2594
> >
> > Thank you,
> > Gary
> > ---
> > Gary Gregory
> > Seagull Software
> > ggregory@seagullsoftware.com
> > www.seagullsoftware.com
> > ---
> > ggregory@apache.org
> >
> 
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

Re: [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor

Posted by Daniel Kulp <dk...@apache.org>.
I just committed some fixes to the unwind/handleFault logic in a couple 
interceptors that I think should fix this.   Can you check tomorrow's 
snapshots (or checkout the code and build today).

Dan


On Wed January 6 2010 3:04:51 pm Gary Gregory wrote:
> Hi All,
> 
> Has anyone gotten the chance to look at:
> 
> [CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output
>  chain after SAAJOutInterceptor
>  https://issues.apache.org/jira/browse/CXF-2594
> 
> Thank you,
> Gary
> ---
> Gary Gregory
> Seagull Software
> ggregory@seagullsoftware.com
> www.seagullsoftware.com
> ---
> ggregory@apache.org
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

[CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor

Posted by Gary Gregory <GG...@seagullsoftware.com>.
Hi All,

Has anyone gotten the chance to look at:

[CXF-2594] No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor 
https://issues.apache.org/jira/browse/CXF-2594

Thank you,
Gary
---
Gary Gregory
Seagull Software
ggregory@seagullsoftware.com
www.seagullsoftware.com
---
ggregory@apache.org

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
> -----Original Message-----
> From: Gary Gregory
> Sent: Sunday, December 27, 2009 16:16
> To: 'Daniel Kulp'; users@cxf.apache.org
> Subject: RE: Inflexible fault interceptor chain?
>
> > -----Original Message-----
> > From: Daniel Kulp [mailto:dkulp@apache.org]
> > Sent: Tuesday, December 22, 2009 10:06
> > To: users@cxf.apache.org
> > Cc: Gary Gregory
> > Subject: Re: Inflexible fault interceptor chain?
> >
> >
> > Can you create a small test case and attach to a jira?
>
> Here is the unit test:
>
> https://issues.apache.org/jira/browse/CXF-2594
> No SOAP fault XML elements when a Fault is thrown in the output chain
> after SAAJOutInterceptor.

Hi Dan and all,

Any news on looking at this unit tests? Can you see the failure and situation I am talking about?

Thank you,
Gary

>
> Thank you,
> Gary
>
> >
> > This definitely sounds like bug of some sort.   When I redid the
> > Provider
> > based services, I noticed that strange code in the StaxOutInterceptor
> > as well
> > and tried to remove it.   However, that broke some of the JAX-WS tck
> > tests.
> > I don't remember the exact reason.   I think it has something to do
> > with
> > faults thrown from the logical or soap handlers on the outgoing chain
> > needed
> > some strange and wacky processing.     Don't really remember.
> >
> > If we can get your test case, we may be able to get it to work
> better.
> >
> > That said, you could probably write your own interceptor (you seem to
> > be good
> > at that :-)  that would run on the fault chain prior to the SAAJOut
> and
> > have
> > it remove the SAAJ model from the message.   You may need to trace
> > through a
> > couple other interceptors (like SoapOutInterceptor) to see if other
> > properties
> > need to be removed/reset.
> >
> > Dan
> >
> >
> > On Mon December 21 2009 8:12:50 pm Gary Gregory wrote:
> > > Hello Dan and all,
> > >
> > > Ok, the SAAJOutInterceptor solution almost worked. The behavior I
> > describe
> > >  below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of
> Saturday's
> > >  build). I am not on 2.2.5 due to some bugs that are fixed in
> 2.2.6.
> > The
> > >  debugging information I gathered for this message is with 2.2.4.
> > >
> > > I have two scenarios, one works and one does not with the
> > >  SAAJOutInterceptor solution.
> > >
> > > If a Fault is thrown by a custom interceptor at a certain point in
> > the
> > >  output chain, the wrong SOAP XML is generated, specifically no
> SOAP
> > fault
> > >  XML elements are generated. Let me start by showing what works and
> > why
> > >  before showing what does not and why.
> > >
> > > In the first scenario, which works, a SoapFault is thrown by our
> > provider's
> > >  invoke(SOAPMessage) method under certain conditions, basically if
> > our
> > >  server detects certain errors. Our provider looks like this:
> > >
> > > @WebServiceProvider
> > > @ServiceMode(value = Service.Mode.MESSAGE)
> > > public static class LdeWebServiceProvider implements
> > Provider<SOAPMessage>
> > >  { @Override
> > >    public SOAPMessage invoke(SOAPMessage soapRequest) {
> > >       ...
> > >       throw new SoapFault("Our message",
> > >  Soap11.getInstance().getReceiver()); }
> > > }
> > >
> > > In SAAJOutInterceptor.handleMessage, the local variable saaj is
> null,
> > so
> > >  the code path taken builds a SOAP message from scratch and plugs
> in
> > a
> > >  W3CDOMStreamWriter. All of the interceptors then write to
> > >  W3CDOMStreamWriter instead of the default XMLStreamWriter which
> > normally
> > >  caches and writes to the HTTP wire. The W3CDOMStreamWriter allows
> me
> > to
> > >  transform the DOM before it gets on the wire. Great stuff, it
> works.
> > >
> > > In the second scenario, I test our output feature where in addition
> > to an
> > >  optional transformation, we have custom interceptors to do
> optional
> > XML
> > >  validation before and after the XML transformation. After our
> > provider
> > >  successfully processed a message, the output chain processing
> kicks
> > in and
> > >  looks like this:
> > >
> > > Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current
> > flow:
> > >   setup [PolicyOutInterceptor]
> > >   pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
> > >   post-logical [SoapPreProtocolOutInterceptor]
> > >   prepare-send [MessageSenderInterceptor,
> MessageModeOutInterceptor]
> > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > >  AttachmentOutInterceptor, StaxOutInterceptor] pre-protocol
> > >  [MessageModeOutInterceptorInternal, SAAJOutInterceptor,
> > >  SOAPHandlerInterceptor, OurWSS4JOutInterceptor] write
> > [SoapOutInterceptor]
> > >   pre-marshal [LogicalHandlerOutInterceptor,
> > ValidatingOutInterceptor*,
> > >  TransformOutInterceptor*, ValidatingOutInterceptor*] marshal
> > >  [BareOutInterceptor]
> > >   write-ending [SoapOutEndingInterceptor]
> > >   pre-protocol-ending [SAAJOutEndingInterceptor]
> > >   pre-stream-ending [StaxOutEndingInterceptor]
> > >   prepare-send-ending [MessageSenderEndingInterceptor]
> > >
> > > The interceptors marked with * are mine:
> > > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > > - ValidatingOutInterceptor validates XML
> > > - TransformOutInterceptor transforms XML
> > > - ValidatingOutInterceptor validates XML
> > >
> > > The problem occurs if XML validation fails (the first validation in
> > this
> > >  test).
> > >
> > > When the XML validation fails, an exception thrown, caught, and re-
> > thrown
> > >  as a fault.
> > >
> > > At the start of fault processing, the chain when SAAJOutInterceptor
> > is
> > >  called looks like this:
> > >
> > >   Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f.
> Current
> > flow:
> > >   setup [ServerPolicyOutFaultInterceptor]
> > >   prepare-send [MessageSenderInterceptor,
> Soap11FaultOutInterceptor]
> > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > >  SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor] write
> > >  [SoapOutInterceptor]
> > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > >   marshal [Soap11FaultOutInterceptorInternal]
> > >   pre-protocol-ending [TransformOutFaultInterceptor*]
> > >   prepare-send-ending [MessageSenderEndingInterceptor]
> > >
> > > The interceptors marked with * are mine:
> > > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > > - TransformOutFaultInterceptor validates XML
> > >
> > > When I step through this SAAJOutInterceptor invocation, the saaj
> > variable
> > >  is NOT null, so the code path taken is different from what I
> > described
> > >  above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is
> > created
> > >  that throws away whatever is written to it:
> > >
> > >             //as the SOAPMessage already has everything in place,
> we
> > do not
> > >  need XMLStreamWriter to write //anything for us, so we just set
> > >  XMLStreamWriter's output to a dummy output stream. XMLStreamWriter
> > >  origWriter = message.getContent(XMLStreamWriter.class);
> > >  message.put(ORIGINAL_XML_WRITER, origWriter);
> > >
> > >             XMLStreamWriter dummyWriter =
> > >  StaxUtils.createXMLStreamWriter(new OutputStream() { public void
> > write(int
> > >  b) throws IOException {
> > >                     }
> > >                     public void write(byte b[], int off, int len)
> > throws
> > >  IOException { }
> > >                 });
> > >             message.setContent(XMLStreamWriter.class, dummyWriter);
> > >
> > > No wonder I get no SOAP fault information back, I get:
> > >
> > > <?xml version='1.0' encoding='ISO-8859-1'?>
> > > <SOAP-ENV:Envelope
> > >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
> > >  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-
> > ENV:Header
> > >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
> > <ais:requestID
> > >
> >
> xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80
> > 102
> > > -00ce16ad0000010e75da25398002}</ais:requestID> </SOAP-ENV:Header>
> > >   <SOAP-ENV:Body xmlns:SOAP-
> > ENV="http://schemas.xmlsoap.org/soap/envelope/"
> > >  /> </SOAP-ENV:Envelope>
> > >
> > > Is this a bug? Why would there be a dummy writer put in place? Is
> > there
> > >  another CXF way to do this?
> > >
> > > Thank you,
> > > Gary
> > >
> > > > -----Original Message-----
> > > > From: Gary Gregory
> > > > Sent: Friday, December 18, 2009 18:11
> > > > To: 'Daniel Kulp'; users@cxf.apache.org
> > > > Subject: RE: Inflexible fault interceptor chain?
> > > >
> > > > Ok, that worked!
> > > >
> > > > Thank you Dan,
> > > > Gary
> > > >
> > > > > -----Original Message-----
> > > > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > > > Sent: Friday, December 18, 2009 07:33
> > > > > To: users@cxf.apache.org
> > > > > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > > > > Subject: Re: Inflexible fault interceptor chain?
> > > > >
> > > > >
> > > > > Honestly, the EASIEST way to accomplish this, since you are
> using
> > > >
> > > > soap,
> > > >
> > > > > is to
> > > > > add the SAAJOutInterceptor to the fault chain.  Then, your
> > > >
> > > > interceptor
> > > >
> > > > > would
> > > > > live right before it's "ending" interceptor and do:
> > > > >
> > > > > message.getContext(SOAPMessage.class)
> > > > >
> > > > > to get the SAAJ model out.   Since the SAAJ model implements
> the
> > DOM
> > > > > interfaces, you can then feed that into an XSLT processor or
> > similar
> > > >
> > > > to
> > > >
> > > > > transform it and then set a new version back with the
> setContent
> > > >
> > > > call.
> > > >
> > > > > Dan
> > > > >
> > > > > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > > > > Hi All:
> > > > > >
> > > > > > I need to apply an XSL transformation to messages coming out
> of
> > CXF
> > > > >
> > > > > (our
> > > > >
> > > > > >  users configure what the XSL looks like.) For a normal
> > > >
> > > > (successful)
> > > >
> > > > > >  message, I have an interceptor (during Phase.PRE_MARSHAL)
> that
> > > >
> > > > uses
> > > >
> > > > > the
> > > > >
> > > > > >  DOM aspect of a message. That works great. BTW, I get to the
> > DOM
> > > > >
> > > > > like
> > > > >
> > > > > >  this:
> > > > > >
> > > > > > Node node = (Node) message.getContent(List.class).get(0);
> > > > > >
> > > > > > That seems brittle, is there a safer way to get to an aspect
> of
> > the
> > > > >
> > > > > message
> > > > >
> > > > > >  I can feed to javax.xml.transform?
> > > > > >
> > > > > > The real issue comes with fault messages because the fault
> > chain
> > > >
> > > > uses
> > > >
> > > > > an
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html>. The fault chain looks like this:
> > > > > >
> > > > > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303.
> > Current
> > > > >
> > > > > flow:
> > > > > >   setup [ServerPolicyOutFaultInterceptor]
> > > > > >   prepare-send [MessageSenderInterceptor,
> > > >
> > > > Soap11FaultOutInterceptor]
> > > >
> > > > > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > > > > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > > > > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > > > > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > > > > >   marshal [Soap11FaultOutInterceptorInternal]
> > > > > >   pre-stream-ending [StaxOutEndingInterceptor,
> > > > > >  TransformOutFaultInterceptor*] prepare-send-ending
> > > > > >  [MessageSenderEndingInterceptor]
> > > > > >
> > > > > > FYI, the interceptors marked with * are our own:
> > > > > >
> > > > > > *         XmlDeclOutInterceptor forces an XML declaration to
> be
> > > > >
> > > > > written.
> > > > >
> > > > > > *         TransformOutFaultInterceptor is where I thought I
> > could
> > > > >
> > > > > transform
> > > > >
> > > > > >  the fault XML message.
> > > > > >
> > > > > > The
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> looks like this:
> > > > > >
> > > > > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> > > >
> > > > underlying
> > > >
> > > > > >  outputter:
> > > >
> > > >
> >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> > > >
> > > > > ati
> > > > >
> > > > > > n1XmlWriter@1125cf44>
> > > > > >
> > > > > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > > > > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > > > > >
> > > > > > *         currentStream - LoadingByteArrayOutputStream
> > > > > >
> > > > > > *         flowThroughStream -
> > > > >
> > > > > AbstractHTTPDestination$WrappedOutputStream
> > > > >
> > > > > > All of this to say that when the chain's interceptors are
> > working
> > > > >
> > > > > with the
> > > > >
> > > > > >  message's
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html>, the bytes are cached and written to the
> > wire.
> > > >
> > > > It
> > > >
> > > > > is not
> > > > >
> > > > > >  possible to catch the fault XML message and change it.
> > > > > >
> > > > > > The only thing I've come up with but not implemented yet
> would
> > be
> > > >
> > > > to
> > > >
> > > > > insert
> > > > >
> > > > > >  an interceptor before the XML declaration is written and put
> > the
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> into a temp spot in the message content
> map,
> > > >
> > > > then
> > > >
> > > > > put a
> > > > >
> > > > > >  new
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> on a byte array in its place. A pre-
> stream-
> > > >
> > > > ending
> > > >
> > > > > >  interceptor can take those bytes, apply XSL to them and then
> > write
> > > > >
> > > > > them to
> > > > >
> > > > > >  the original
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html>, before putting the original
> > > >
> > > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > > >
> > > > > XML
> > > > >
> > > > > > StreamWriter.html> back in it original slot in the message
> > content
> > > > >
> > > > > map.
> > > > >
> > > > > > That seems like big old hack.
> > > > > >
> > > > > > Any ideas on a cleaner solution?
> > > > > >
> > > > > > Thank you,
> > > > > > Gary Gregory
> > > > > > Seagull Software
> > > > > > ggregory@seagullsoftware.com
> > > > > > www.seagullsoftware.com
> > > > >
> > > > > --
> > > > > Daniel Kulp
> > > > > dkulp@apache.org
> > > > > http://www.dankulp.com/blog
> > >
> >
> > --
> > Daniel Kulp
> > dkulp@apache.org
> > http://www.dankulp.com/blog

Test failure for JAXWSDefinitionBuilderTest.testBuildDefinitionWithXMLBinding

Posted by Gary Gregory <GG...@seagullsoftware.com>.
Hi All:

I am running unit tests from Eclipse (3.6M4 / JUnit 4) and I see this failure with the latest from SVN 2.2.x.

Does anyone else see this failure?

Thank you,
Gary

Rerun org.apache.cxf.tools.wsdlto.jaxws.wsdl11.JAXWSDefinitionBuilderTest
org.apache.cxf.tools.wsdlto.jaxws.wsdl11.JAXWSDefinitionBuilderTest
testBuildDefinitionWithXMLBinding(org.apache.cxf.tools.wsdlto.jaxws.wsdl11.JAXWSDefinitionBuilderTest)
java.lang.AssertionError: org.apache.cxf.wsdl.http.AddressType
	at org.junit.Assert.fail(Assert.java:91)
	at org.junit.Assert.assertTrue(Assert.java:43)
	at org.apache.cxf.tools.wsdlto.jaxws.wsdl11.JAXWSDefinitionBuilderTest.testBuildDefinitionWithXMLBinding(JAXWSDefinitionBuilderTest.java:74)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Tuesday, December 22, 2009 10:06
> To: users@cxf.apache.org
> Cc: Gary Gregory
> Subject: Re: Inflexible fault interceptor chain?
> 
> 
> Can you create a small test case and attach to a jira?

Here is the unit test:

https://issues.apache.org/jira/browse/CXF-2594 
No SOAP fault XML elements when a Fault is thrown in the output chain after SAAJOutInterceptor.

Thank you,
Gary

> 
> This definitely sounds like bug of some sort.   When I redid the
> Provider
> based services, I noticed that strange code in the StaxOutInterceptor
> as well
> and tried to remove it.   However, that broke some of the JAX-WS tck
> tests.
> I don't remember the exact reason.   I think it has something to do
> with
> faults thrown from the logical or soap handlers on the outgoing chain
> needed
> some strange and wacky processing.     Don't really remember.
> 
> If we can get your test case, we may be able to get it to work better.
> 
> That said, you could probably write your own interceptor (you seem to
> be good
> at that :-)  that would run on the fault chain prior to the SAAJOut and
> have
> it remove the SAAJ model from the message.   You may need to trace
> through a
> couple other interceptors (like SoapOutInterceptor) to see if other
> properties
> need to be removed/reset.
> 
> Dan
> 
> 
> On Mon December 21 2009 8:12:50 pm Gary Gregory wrote:
> > Hello Dan and all,
> >
> > Ok, the SAAJOutInterceptor solution almost worked. The behavior I
> describe
> >  below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of Saturday's
> >  build). I am not on 2.2.5 due to some bugs that are fixed in 2.2.6.
> The
> >  debugging information I gathered for this message is with 2.2.4.
> >
> > I have two scenarios, one works and one does not with the
> >  SAAJOutInterceptor solution.
> >
> > If a Fault is thrown by a custom interceptor at a certain point in
> the
> >  output chain, the wrong SOAP XML is generated, specifically no SOAP
> fault
> >  XML elements are generated. Let me start by showing what works and
> why
> >  before showing what does not and why.
> >
> > In the first scenario, which works, a SoapFault is thrown by our
> provider's
> >  invoke(SOAPMessage) method under certain conditions, basically if
> our
> >  server detects certain errors. Our provider looks like this:
> >
> > @WebServiceProvider
> > @ServiceMode(value = Service.Mode.MESSAGE)
> > public static class LdeWebServiceProvider implements
> Provider<SOAPMessage>
> >  { @Override
> >    public SOAPMessage invoke(SOAPMessage soapRequest) {
> >       ...
> >       throw new SoapFault("Our message",
> >  Soap11.getInstance().getReceiver()); }
> > }
> >
> > In SAAJOutInterceptor.handleMessage, the local variable saaj is null,
> so
> >  the code path taken builds a SOAP message from scratch and plugs in
> a
> >  W3CDOMStreamWriter. All of the interceptors then write to
> >  W3CDOMStreamWriter instead of the default XMLStreamWriter which
> normally
> >  caches and writes to the HTTP wire. The W3CDOMStreamWriter allows me
> to
> >  transform the DOM before it gets on the wire. Great stuff, it works.
> >
> > In the second scenario, I test our output feature where in addition
> to an
> >  optional transformation, we have custom interceptors to do optional
> XML
> >  validation before and after the XML transformation. After our
> provider
> >  successfully processed a message, the output chain processing kicks
> in and
> >  looks like this:
> >
> > Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current
> flow:
> >   setup [PolicyOutInterceptor]
> >   pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
> >   post-logical [SoapPreProtocolOutInterceptor]
> >   prepare-send [MessageSenderInterceptor, MessageModeOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  AttachmentOutInterceptor, StaxOutInterceptor] pre-protocol
> >  [MessageModeOutInterceptorInternal, SAAJOutInterceptor,
> >  SOAPHandlerInterceptor, OurWSS4JOutInterceptor] write
> [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerOutInterceptor,
> ValidatingOutInterceptor*,
> >  TransformOutInterceptor*, ValidatingOutInterceptor*] marshal
> >  [BareOutInterceptor]
> >   write-ending [SoapOutEndingInterceptor]
> >   pre-protocol-ending [SAAJOutEndingInterceptor]
> >   pre-stream-ending [StaxOutEndingInterceptor]
> >   prepare-send-ending [MessageSenderEndingInterceptor]
> >
> > The interceptors marked with * are mine:
> > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > - ValidatingOutInterceptor validates XML
> > - TransformOutInterceptor transforms XML
> > - ValidatingOutInterceptor validates XML
> >
> > The problem occurs if XML validation fails (the first validation in
> this
> >  test).
> >
> > When the XML validation fails, an exception thrown, caught, and re-
> thrown
> >  as a fault.
> >
> > At the start of fault processing, the chain when SAAJOutInterceptor
> is
> >  called looks like this:
> >
> >   Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f. Current
> flow:
> >   setup [ServerPolicyOutFaultInterceptor]
> >   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> >  SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor] write
> >  [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> >   marshal [Soap11FaultOutInterceptorInternal]
> >   pre-protocol-ending [TransformOutFaultInterceptor*]
> >   prepare-send-ending [MessageSenderEndingInterceptor]
> >
> > The interceptors marked with * are mine:
> > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > - TransformOutFaultInterceptor validates XML
> >
> > When I step through this SAAJOutInterceptor invocation, the saaj
> variable
> >  is NOT null, so the code path taken is different from what I
> described
> >  above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is
> created
> >  that throws away whatever is written to it:
> >
> >             //as the SOAPMessage already has everything in place, we
> do not
> >  need XMLStreamWriter to write //anything for us, so we just set
> >  XMLStreamWriter's output to a dummy output stream. XMLStreamWriter
> >  origWriter = message.getContent(XMLStreamWriter.class);
> >  message.put(ORIGINAL_XML_WRITER, origWriter);
> >
> >             XMLStreamWriter dummyWriter =
> >  StaxUtils.createXMLStreamWriter(new OutputStream() { public void
> write(int
> >  b) throws IOException {
> >                     }
> >                     public void write(byte b[], int off, int len)
> throws
> >  IOException { }
> >                 });
> >             message.setContent(XMLStreamWriter.class, dummyWriter);
> >
> > No wonder I get no SOAP fault information back, I get:
> >
> > <?xml version='1.0' encoding='ISO-8859-1'?>
> > <SOAP-ENV:Envelope
> >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-
> ENV:Header
> >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
> <ais:requestID
> >
> xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80
> 102
> > -00ce16ad0000010e75da25398002}</ais:requestID> </SOAP-ENV:Header>
> > 	<SOAP-ENV:Body xmlns:SOAP-
> ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >  /> </SOAP-ENV:Envelope>
> >
> > Is this a bug? Why would there be a dummy writer put in place? Is
> there
> >  another CXF way to do this?
> >
> > Thank you,
> > Gary
> >
> > > -----Original Message-----
> > > From: Gary Gregory
> > > Sent: Friday, December 18, 2009 18:11
> > > To: 'Daniel Kulp'; users@cxf.apache.org
> > > Subject: RE: Inflexible fault interceptor chain?
> > >
> > > Ok, that worked!
> > >
> > > Thank you Dan,
> > > Gary
> > >
> > > > -----Original Message-----
> > > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > > Sent: Friday, December 18, 2009 07:33
> > > > To: users@cxf.apache.org
> > > > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > > > Subject: Re: Inflexible fault interceptor chain?
> > > >
> > > >
> > > > Honestly, the EASIEST way to accomplish this, since you are using
> > >
> > > soap,
> > >
> > > > is to
> > > > add the SAAJOutInterceptor to the fault chain.  Then, your
> > >
> > > interceptor
> > >
> > > > would
> > > > live right before it's "ending" interceptor and do:
> > > >
> > > > message.getContext(SOAPMessage.class)
> > > >
> > > > to get the SAAJ model out.   Since the SAAJ model implements the
> DOM
> > > > interfaces, you can then feed that into an XSLT processor or
> similar
> > >
> > > to
> > >
> > > > transform it and then set a new version back with the setContent
> > >
> > > call.
> > >
> > > > Dan
> > > >
> > > > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > > > Hi All:
> > > > >
> > > > > I need to apply an XSL transformation to messages coming out of
> CXF
> > > >
> > > > (our
> > > >
> > > > >  users configure what the XSL looks like.) For a normal
> > >
> > > (successful)
> > >
> > > > >  message, I have an interceptor (during Phase.PRE_MARSHAL) that
> > >
> > > uses
> > >
> > > > the
> > > >
> > > > >  DOM aspect of a message. That works great. BTW, I get to the
> DOM
> > > >
> > > > like
> > > >
> > > > >  this:
> > > > >
> > > > > Node node = (Node) message.getContent(List.class).get(0);
> > > > >
> > > > > That seems brittle, is there a safer way to get to an aspect of
> the
> > > >
> > > > message
> > > >
> > > > >  I can feed to javax.xml.transform?
> > > > >
> > > > > The real issue comes with fault messages because the fault
> chain
> > >
> > > uses
> > >
> > > > an
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>. The fault chain looks like this:
> > > > >
> > > > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303.
> Current
> > > >
> > > > flow:
> > > > >   setup [ServerPolicyOutFaultInterceptor]
> > > > >   prepare-send [MessageSenderInterceptor,
> > >
> > > Soap11FaultOutInterceptor]
> > >
> > > > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > > > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > > > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > > > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > > > >   marshal [Soap11FaultOutInterceptorInternal]
> > > > >   pre-stream-ending [StaxOutEndingInterceptor,
> > > > >  TransformOutFaultInterceptor*] prepare-send-ending
> > > > >  [MessageSenderEndingInterceptor]
> > > > >
> > > > > FYI, the interceptors marked with * are our own:
> > > > >
> > > > > *         XmlDeclOutInterceptor forces an XML declaration to be
> > > >
> > > > written.
> > > >
> > > > > *         TransformOutFaultInterceptor is where I thought I
> could
> > > >
> > > > transform
> > > >
> > > > >  the fault XML message.
> > > > >
> > > > > The
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> looks like this:
> > > > >
> > > > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> > >
> > > underlying
> > >
> > > > >  outputter:
> > >
> > >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> > >
> > > > ati
> > > >
> > > > > n1XmlWriter@1125cf44>
> > > > >
> > > > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > > > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > > > >
> > > > > *         currentStream - LoadingByteArrayOutputStream
> > > > >
> > > > > *         flowThroughStream -
> > > >
> > > > AbstractHTTPDestination$WrappedOutputStream
> > > >
> > > > > All of this to say that when the chain's interceptors are
> working
> > > >
> > > > with the
> > > >
> > > > >  message's
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>, the bytes are cached and written to the
> wire.
> > >
> > > It
> > >
> > > > is not
> > > >
> > > > >  possible to catch the fault XML message and change it.
> > > > >
> > > > > The only thing I've come up with but not implemented yet would
> be
> > >
> > > to
> > >
> > > > insert
> > > >
> > > > >  an interceptor before the XML declaration is written and put
> the
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> into a temp spot in the message content map,
> > >
> > > then
> > >
> > > > put a
> > > >
> > > > >  new
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> on a byte array in its place. A pre-stream-
> > >
> > > ending
> > >
> > > > >  interceptor can take those bytes, apply XSL to them and then
> write
> > > >
> > > > them to
> > > >
> > > > >  the original
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>, before putting the original
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> back in it original slot in the message
> content
> > > >
> > > > map.
> > > >
> > > > > That seems like big old hack.
> > > > >
> > > > > Any ideas on a cleaner solution?
> > > > >
> > > > > Thank you,
> > > > > Gary Gregory
> > > > > Seagull Software
> > > > > ggregory@seagullsoftware.com
> > > > > www.seagullsoftware.com
> > > >
> > > > --
> > > > Daniel Kulp
> > > > dkulp@apache.org
> > > > http://www.dankulp.com/blog
> >
> 
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
I'll see if I can create a standalone test... in the meantime I am trying to see if my fix breaks 2.2.6-SNAPSHOT tests.

Gary

> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Tuesday, December 22, 2009 10:06
> To: users@cxf.apache.org
> Cc: Gary Gregory
> Subject: Re: Inflexible fault interceptor chain?
> 
> 
> Can you create a small test case and attach to a jira?
> 
> This definitely sounds like bug of some sort.   When I redid the
> Provider
> based services, I noticed that strange code in the StaxOutInterceptor
> as well
> and tried to remove it.   However, that broke some of the JAX-WS tck
> tests.
> I don't remember the exact reason.   I think it has something to do
> with
> faults thrown from the logical or soap handlers on the outgoing chain
> needed
> some strange and wacky processing.     Don't really remember.
> 
> If we can get your test case, we may be able to get it to work better.
> 
> That said, you could probably write your own interceptor (you seem to
> be good
> at that :-)  that would run on the fault chain prior to the SAAJOut and
> have
> it remove the SAAJ model from the message.   You may need to trace
> through a
> couple other interceptors (like SoapOutInterceptor) to see if other
> properties
> need to be removed/reset.
> 
> Dan
> 
> 
> On Mon December 21 2009 8:12:50 pm Gary Gregory wrote:
> > Hello Dan and all,
> >
> > Ok, the SAAJOutInterceptor solution almost worked. The behavior I
> describe
> >  below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of Saturday's
> >  build). I am not on 2.2.5 due to some bugs that are fixed in 2.2.6.
> The
> >  debugging information I gathered for this message is with 2.2.4.
> >
> > I have two scenarios, one works and one does not with the
> >  SAAJOutInterceptor solution.
> >
> > If a Fault is thrown by a custom interceptor at a certain point in
> the
> >  output chain, the wrong SOAP XML is generated, specifically no SOAP
> fault
> >  XML elements are generated. Let me start by showing what works and
> why
> >  before showing what does not and why.
> >
> > In the first scenario, which works, a SoapFault is thrown by our
> provider's
> >  invoke(SOAPMessage) method under certain conditions, basically if
> our
> >  server detects certain errors. Our provider looks like this:
> >
> > @WebServiceProvider
> > @ServiceMode(value = Service.Mode.MESSAGE)
> > public static class LdeWebServiceProvider implements
> Provider<SOAPMessage>
> >  { @Override
> >    public SOAPMessage invoke(SOAPMessage soapRequest) {
> >       ...
> >       throw new SoapFault("Our message",
> >  Soap11.getInstance().getReceiver()); }
> > }
> >
> > In SAAJOutInterceptor.handleMessage, the local variable saaj is null,
> so
> >  the code path taken builds a SOAP message from scratch and plugs in
> a
> >  W3CDOMStreamWriter. All of the interceptors then write to
> >  W3CDOMStreamWriter instead of the default XMLStreamWriter which
> normally
> >  caches and writes to the HTTP wire. The W3CDOMStreamWriter allows me
> to
> >  transform the DOM before it gets on the wire. Great stuff, it works.
> >
> > In the second scenario, I test our output feature where in addition
> to an
> >  optional transformation, we have custom interceptors to do optional
> XML
> >  validation before and after the XML transformation. After our
> provider
> >  successfully processed a message, the output chain processing kicks
> in and
> >  looks like this:
> >
> > Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current
> flow:
> >   setup [PolicyOutInterceptor]
> >   pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
> >   post-logical [SoapPreProtocolOutInterceptor]
> >   prepare-send [MessageSenderInterceptor, MessageModeOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  AttachmentOutInterceptor, StaxOutInterceptor] pre-protocol
> >  [MessageModeOutInterceptorInternal, SAAJOutInterceptor,
> >  SOAPHandlerInterceptor, OurWSS4JOutInterceptor] write
> [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerOutInterceptor,
> ValidatingOutInterceptor*,
> >  TransformOutInterceptor*, ValidatingOutInterceptor*] marshal
> >  [BareOutInterceptor]
> >   write-ending [SoapOutEndingInterceptor]
> >   pre-protocol-ending [SAAJOutEndingInterceptor]
> >   pre-stream-ending [StaxOutEndingInterceptor]
> >   prepare-send-ending [MessageSenderEndingInterceptor]
> >
> > The interceptors marked with * are mine:
> > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > - ValidatingOutInterceptor validates XML
> > - TransformOutInterceptor transforms XML
> > - ValidatingOutInterceptor validates XML
> >
> > The problem occurs if XML validation fails (the first validation in
> this
> >  test).
> >
> > When the XML validation fails, an exception thrown, caught, and re-
> thrown
> >  as a fault.
> >
> > At the start of fault processing, the chain when SAAJOutInterceptor
> is
> >  called looks like this:
> >
> >   Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f. Current
> flow:
> >   setup [ServerPolicyOutFaultInterceptor]
> >   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> >  SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor] write
> >  [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> >   marshal [Soap11FaultOutInterceptorInternal]
> >   pre-protocol-ending [TransformOutFaultInterceptor*]
> >   prepare-send-ending [MessageSenderEndingInterceptor]
> >
> > The interceptors marked with * are mine:
> > - XmlDeclOutInterceptor forces the XML declaration to be written.
> > - TransformOutFaultInterceptor validates XML
> >
> > When I step through this SAAJOutInterceptor invocation, the saaj
> variable
> >  is NOT null, so the code path taken is different from what I
> described
> >  above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is
> created
> >  that throws away whatever is written to it:
> >
> >             //as the SOAPMessage already has everything in place, we
> do not
> >  need XMLStreamWriter to write //anything for us, so we just set
> >  XMLStreamWriter's output to a dummy output stream. XMLStreamWriter
> >  origWriter = message.getContent(XMLStreamWriter.class);
> >  message.put(ORIGINAL_XML_WRITER, origWriter);
> >
> >             XMLStreamWriter dummyWriter =
> >  StaxUtils.createXMLStreamWriter(new OutputStream() { public void
> write(int
> >  b) throws IOException {
> >                     }
> >                     public void write(byte b[], int off, int len)
> throws
> >  IOException { }
> >                 });
> >             message.setContent(XMLStreamWriter.class, dummyWriter);
> >
> > No wonder I get no SOAP fault information back, I get:
> >
> > <?xml version='1.0' encoding='ISO-8859-1'?>
> > <SOAP-ENV:Envelope
> >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-
> ENV:Header
> >  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
> <ais:requestID
> >
> xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80
> 102
> > -00ce16ad0000010e75da25398002}</ais:requestID> </SOAP-ENV:Header>
> > 	<SOAP-ENV:Body xmlns:SOAP-
> ENV="http://schemas.xmlsoap.org/soap/envelope/"
> >  /> </SOAP-ENV:Envelope>
> >
> > Is this a bug? Why would there be a dummy writer put in place? Is
> there
> >  another CXF way to do this?
> >
> > Thank you,
> > Gary
> >
> > > -----Original Message-----
> > > From: Gary Gregory
> > > Sent: Friday, December 18, 2009 18:11
> > > To: 'Daniel Kulp'; users@cxf.apache.org
> > > Subject: RE: Inflexible fault interceptor chain?
> > >
> > > Ok, that worked!
> > >
> > > Thank you Dan,
> > > Gary
> > >
> > > > -----Original Message-----
> > > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > > Sent: Friday, December 18, 2009 07:33
> > > > To: users@cxf.apache.org
> > > > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > > > Subject: Re: Inflexible fault interceptor chain?
> > > >
> > > >
> > > > Honestly, the EASIEST way to accomplish this, since you are using
> > >
> > > soap,
> > >
> > > > is to
> > > > add the SAAJOutInterceptor to the fault chain.  Then, your
> > >
> > > interceptor
> > >
> > > > would
> > > > live right before it's "ending" interceptor and do:
> > > >
> > > > message.getContext(SOAPMessage.class)
> > > >
> > > > to get the SAAJ model out.   Since the SAAJ model implements the
> DOM
> > > > interfaces, you can then feed that into an XSLT processor or
> similar
> > >
> > > to
> > >
> > > > transform it and then set a new version back with the setContent
> > >
> > > call.
> > >
> > > > Dan
> > > >
> > > > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > > > Hi All:
> > > > >
> > > > > I need to apply an XSL transformation to messages coming out of
> CXF
> > > >
> > > > (our
> > > >
> > > > >  users configure what the XSL looks like.) For a normal
> > >
> > > (successful)
> > >
> > > > >  message, I have an interceptor (during Phase.PRE_MARSHAL) that
> > >
> > > uses
> > >
> > > > the
> > > >
> > > > >  DOM aspect of a message. That works great. BTW, I get to the
> DOM
> > > >
> > > > like
> > > >
> > > > >  this:
> > > > >
> > > > > Node node = (Node) message.getContent(List.class).get(0);
> > > > >
> > > > > That seems brittle, is there a safer way to get to an aspect of
> the
> > > >
> > > > message
> > > >
> > > > >  I can feed to javax.xml.transform?
> > > > >
> > > > > The real issue comes with fault messages because the fault
> chain
> > >
> > > uses
> > >
> > > > an
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>. The fault chain looks like this:
> > > > >
> > > > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303.
> Current
> > > >
> > > > flow:
> > > > >   setup [ServerPolicyOutFaultInterceptor]
> > > > >   prepare-send [MessageSenderInterceptor,
> > >
> > > Soap11FaultOutInterceptor]
> > >
> > > > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > > > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > > > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > > > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > > > >   marshal [Soap11FaultOutInterceptorInternal]
> > > > >   pre-stream-ending [StaxOutEndingInterceptor,
> > > > >  TransformOutFaultInterceptor*] prepare-send-ending
> > > > >  [MessageSenderEndingInterceptor]
> > > > >
> > > > > FYI, the interceptors marked with * are our own:
> > > > >
> > > > > *         XmlDeclOutInterceptor forces an XML declaration to be
> > > >
> > > > written.
> > > >
> > > > > *         TransformOutFaultInterceptor is where I thought I
> could
> > > >
> > > > transform
> > > >
> > > > >  the fault XML message.
> > > > >
> > > > > The
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> looks like this:
> > > > >
> > > > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> > >
> > > underlying
> > >
> > > > >  outputter:
> > >
> > >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> > >
> > > > ati
> > > >
> > > > > n1XmlWriter@1125cf44>
> > > > >
> > > > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > > > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > > > >
> > > > > *         currentStream - LoadingByteArrayOutputStream
> > > > >
> > > > > *         flowThroughStream -
> > > >
> > > > AbstractHTTPDestination$WrappedOutputStream
> > > >
> > > > > All of this to say that when the chain's interceptors are
> working
> > > >
> > > > with the
> > > >
> > > > >  message's
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>, the bytes are cached and written to the
> wire.
> > >
> > > It
> > >
> > > > is not
> > > >
> > > > >  possible to catch the fault XML message and change it.
> > > > >
> > > > > The only thing I've come up with but not implemented yet would
> be
> > >
> > > to
> > >
> > > > insert
> > > >
> > > > >  an interceptor before the XML declaration is written and put
> the
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> into a temp spot in the message content map,
> > >
> > > then
> > >
> > > > put a
> > > >
> > > > >  new
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> on a byte array in its place. A pre-stream-
> > >
> > > ending
> > >
> > > > >  interceptor can take those bytes, apply XSL to them and then
> write
> > > >
> > > > them to
> > > >
> > > > >  the original
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html>, before putting the original
> > >
> > >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > >
> > > > XML
> > > >
> > > > > StreamWriter.html> back in it original slot in the message
> content
> > > >
> > > > map.
> > > >
> > > > > That seems like big old hack.
> > > > >
> > > > > Any ideas on a cleaner solution?
> > > > >
> > > > > Thank you,
> > > > > Gary Gregory
> > > > > Seagull Software
> > > > > ggregory@seagullsoftware.com
> > > > > www.seagullsoftware.com
> > > >
> > > > --
> > > > Daniel Kulp
> > > > dkulp@apache.org
> > > > http://www.dankulp.com/blog
> >
> 
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

Re: Inflexible fault interceptor chain?

Posted by Daniel Kulp <dk...@apache.org>.
Can you create a small test case and attach to a jira?

This definitely sounds like bug of some sort.   When I redid the Provider 
based services, I noticed that strange code in the StaxOutInterceptor as well 
and tried to remove it.   However, that broke some of the JAX-WS tck tests.   
I don't remember the exact reason.   I think it has something to do with 
faults thrown from the logical or soap handlers on the outgoing chain needed 
some strange and wacky processing.     Don't really remember.   

If we can get your test case, we may be able to get it to work better.   

That said, you could probably write your own interceptor (you seem to be good 
at that :-)  that would run on the fault chain prior to the SAAJOut and have 
it remove the SAAJ model from the message.   You may need to trace through a 
couple other interceptors (like SoapOutInterceptor) to see if other properties 
need to be removed/reset.

Dan


On Mon December 21 2009 8:12:50 pm Gary Gregory wrote:
> Hello Dan and all,
> 
> Ok, the SAAJOutInterceptor solution almost worked. The behavior I describe
>  below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of Saturday's
>  build). I am not on 2.2.5 due to some bugs that are fixed in 2.2.6. The
>  debugging information I gathered for this message is with 2.2.4.
> 
> I have two scenarios, one works and one does not with the
>  SAAJOutInterceptor solution.
> 
> If a Fault is thrown by a custom interceptor at a certain point in the
>  output chain, the wrong SOAP XML is generated, specifically no SOAP fault
>  XML elements are generated. Let me start by showing what works and why
>  before showing what does not and why.
> 
> In the first scenario, which works, a SoapFault is thrown by our provider's
>  invoke(SOAPMessage) method under certain conditions, basically if our
>  server detects certain errors. Our provider looks like this:
> 
> @WebServiceProvider
> @ServiceMode(value = Service.Mode.MESSAGE)
> public static class LdeWebServiceProvider implements Provider<SOAPMessage>
>  { @Override
>    public SOAPMessage invoke(SOAPMessage soapRequest) {
>       ...
>       throw new SoapFault("Our message",
>  Soap11.getInstance().getReceiver()); }
> }
> 
> In SAAJOutInterceptor.handleMessage, the local variable saaj is null, so
>  the code path taken builds a SOAP message from scratch and plugs in a
>  W3CDOMStreamWriter. All of the interceptors then write to
>  W3CDOMStreamWriter instead of the default XMLStreamWriter which normally
>  caches and writes to the HTTP wire. The W3CDOMStreamWriter allows me to
>  transform the DOM before it gets on the wire. Great stuff, it works.
> 
> In the second scenario, I test our output feature where in addition to an
>  optional transformation, we have custom interceptors to do optional XML
>  validation before and after the XML transformation. After our provider
>  successfully processed a message, the output chain processing kicks in and
>  looks like this:
> 
> Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current flow:
>   setup [PolicyOutInterceptor]
>   pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
>   post-logical [SoapPreProtocolOutInterceptor]
>   prepare-send [MessageSenderInterceptor, MessageModeOutInterceptor]
>   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
>  AttachmentOutInterceptor, StaxOutInterceptor] pre-protocol
>  [MessageModeOutInterceptorInternal, SAAJOutInterceptor,
>  SOAPHandlerInterceptor, OurWSS4JOutInterceptor] write [SoapOutInterceptor]
>   pre-marshal [LogicalHandlerOutInterceptor, ValidatingOutInterceptor*,
>  TransformOutInterceptor*, ValidatingOutInterceptor*] marshal
>  [BareOutInterceptor]
>   write-ending [SoapOutEndingInterceptor]
>   pre-protocol-ending [SAAJOutEndingInterceptor]
>   pre-stream-ending [StaxOutEndingInterceptor]
>   prepare-send-ending [MessageSenderEndingInterceptor]
> 
> The interceptors marked with * are mine:
> - XmlDeclOutInterceptor forces the XML declaration to be written.
> - ValidatingOutInterceptor validates XML
> - TransformOutInterceptor transforms XML
> - ValidatingOutInterceptor validates XML
> 
> The problem occurs if XML validation fails (the first validation in this
>  test).
> 
> When the XML validation fails, an exception thrown, caught, and re-thrown
>  as a fault.
> 
> At the start of fault processing, the chain when SAAJOutInterceptor is
>  called looks like this:
> 
>   Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f. Current flow:
>   setup [ServerPolicyOutFaultInterceptor]
>   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
>   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
>  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
>  SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor] write
>  [SoapOutInterceptor]
>   pre-marshal [LogicalHandlerFaultOutInterceptor]
>   marshal [Soap11FaultOutInterceptorInternal]
>   pre-protocol-ending [TransformOutFaultInterceptor*]
>   prepare-send-ending [MessageSenderEndingInterceptor]
> 
> The interceptors marked with * are mine:
> - XmlDeclOutInterceptor forces the XML declaration to be written.
> - TransformOutFaultInterceptor validates XML
> 
> When I step through this SAAJOutInterceptor invocation, the saaj variable
>  is NOT null, so the code path taken is different from what I described
>  above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is created
>  that throws away whatever is written to it:
> 
>             //as the SOAPMessage already has everything in place, we do not
>  need XMLStreamWriter to write //anything for us, so we just set
>  XMLStreamWriter's output to a dummy output stream. XMLStreamWriter
>  origWriter = message.getContent(XMLStreamWriter.class);
>  message.put(ORIGINAL_XML_WRITER, origWriter);
> 
>             XMLStreamWriter dummyWriter =
>  StaxUtils.createXMLStreamWriter(new OutputStream() { public void write(int
>  b) throws IOException {
>                     }
>                     public void write(byte b[], int off, int len) throws
>  IOException { }
>                 });
>             message.setContent(XMLStreamWriter.class, dummyWriter);
> 
> No wonder I get no SOAP fault information back, I get:
> 
> <?xml version='1.0' encoding='ISO-8859-1'?>
> <SOAP-ENV:Envelope
>  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header
>  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <ais:requestID
>  xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80102
> -00ce16ad0000010e75da25398002}</ais:requestID> </SOAP-ENV:Header>
> 	<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
>  /> </SOAP-ENV:Envelope>
> 
> Is this a bug? Why would there be a dummy writer put in place? Is there
>  another CXF way to do this?
> 
> Thank you,
> Gary
> 
> > -----Original Message-----
> > From: Gary Gregory
> > Sent: Friday, December 18, 2009 18:11
> > To: 'Daniel Kulp'; users@cxf.apache.org
> > Subject: RE: Inflexible fault interceptor chain?
> >
> > Ok, that worked!
> >
> > Thank you Dan,
> > Gary
> >
> > > -----Original Message-----
> > > From: Daniel Kulp [mailto:dkulp@apache.org]
> > > Sent: Friday, December 18, 2009 07:33
> > > To: users@cxf.apache.org
> > > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > > Subject: Re: Inflexible fault interceptor chain?
> > >
> > >
> > > Honestly, the EASIEST way to accomplish this, since you are using
> >
> > soap,
> >
> > > is to
> > > add the SAAJOutInterceptor to the fault chain.  Then, your
> >
> > interceptor
> >
> > > would
> > > live right before it's "ending" interceptor and do:
> > >
> > > message.getContext(SOAPMessage.class)
> > >
> > > to get the SAAJ model out.   Since the SAAJ model implements the DOM
> > > interfaces, you can then feed that into an XSLT processor or similar
> >
> > to
> >
> > > transform it and then set a new version back with the setContent
> >
> > call.
> >
> > > Dan
> > >
> > > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > > Hi All:
> > > >
> > > > I need to apply an XSL transformation to messages coming out of CXF
> > >
> > > (our
> > >
> > > >  users configure what the XSL looks like.) For a normal
> >
> > (successful)
> >
> > > >  message, I have an interceptor (during Phase.PRE_MARSHAL) that
> >
> > uses
> >
> > > the
> > >
> > > >  DOM aspect of a message. That works great. BTW, I get to the DOM
> > >
> > > like
> > >
> > > >  this:
> > > >
> > > > Node node = (Node) message.getContent(List.class).get(0);
> > > >
> > > > That seems brittle, is there a safer way to get to an aspect of the
> > >
> > > message
> > >
> > > >  I can feed to javax.xml.transform?
> > > >
> > > > The real issue comes with fault messages because the fault chain
> >
> > uses
> >
> > > an
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html>. The fault chain looks like this:
> > > >
> > > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current
> > >
> > > flow:
> > > >   setup [ServerPolicyOutFaultInterceptor]
> > > >   prepare-send [MessageSenderInterceptor,
> >
> > Soap11FaultOutInterceptor]
> >
> > > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > > >   marshal [Soap11FaultOutInterceptorInternal]
> > > >   pre-stream-ending [StaxOutEndingInterceptor,
> > > >  TransformOutFaultInterceptor*] prepare-send-ending
> > > >  [MessageSenderEndingInterceptor]
> > > >
> > > > FYI, the interceptors marked with * are our own:
> > > >
> > > > *         XmlDeclOutInterceptor forces an XML declaration to be
> > >
> > > written.
> > >
> > > > *         TransformOutFaultInterceptor is where I thought I could
> > >
> > > transform
> > >
> > > >  the fault XML message.
> > > >
> > > > The
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html> looks like this:
> > > >
> > > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> >
> > underlying
> >
> > > >  outputter:
> >
> > com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> >
> > > ati
> > >
> > > > n1XmlWriter@1125cf44>
> > > >
> > > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > > >
> > > > *         currentStream - LoadingByteArrayOutputStream
> > > >
> > > > *         flowThroughStream -
> > >
> > > AbstractHTTPDestination$WrappedOutputStream
> > >
> > > > All of this to say that when the chain's interceptors are working
> > >
> > > with the
> > >
> > > >  message's
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html>, the bytes are cached and written to the wire.
> >
> > It
> >
> > > is not
> > >
> > > >  possible to catch the fault XML message and change it.
> > > >
> > > > The only thing I've come up with but not implemented yet would be
> >
> > to
> >
> > > insert
> > >
> > > >  an interceptor before the XML declaration is written and put the
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html> into a temp spot in the message content map,
> >
> > then
> >
> > > put a
> > >
> > > >  new
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html> on a byte array in its place. A pre-stream-
> >
> > ending
> >
> > > >  interceptor can take those bytes, apply XSL to them and then write
> > >
> > > them to
> > >
> > > >  the original
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html>, before putting the original
> >
> > XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> >
> > > XML
> > >
> > > > StreamWriter.html> back in it original slot in the message content
> > >
> > > map.
> > >
> > > > That seems like big old hack.
> > > >
> > > > Any ideas on a cleaner solution?
> > > >
> > > > Thank you,
> > > > Gary Gregory
> > > > Seagull Software
> > > > ggregory@seagullsoftware.com
> > > > www.seagullsoftware.com
> > >
> > > --
> > > Daniel Kulp
> > > dkulp@apache.org
> > > http://www.dankulp.com/blog
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
Hello Dan and all,

Ok, the SAAJOutInterceptor solution almost worked. The behavior I describe below is the same in CXF 2.2.4 and 2.2.6-SNAPSHOT (as of Saturday's build). I am not on 2.2.5 due to some bugs that are fixed in 2.2.6. The debugging information I gathered for this message is with 2.2.4.

I have two scenarios, one works and one does not with the SAAJOutInterceptor solution. 

If a Fault is thrown by a custom interceptor at a certain point in the output chain, the wrong SOAP XML is generated, specifically no SOAP fault XML elements are generated. Let me start by showing what works and why before showing what does not and why.

In the first scenario, which works, a SoapFault is thrown by our provider's invoke(SOAPMessage) method under certain conditions, basically if our server detects certain errors. Our provider looks like this:

@WebServiceProvider
@ServiceMode(value = Service.Mode.MESSAGE)
public static class LdeWebServiceProvider implements Provider<SOAPMessage> {
   @Override
   public SOAPMessage invoke(SOAPMessage soapRequest) {
      ...
      throw new SoapFault("Our message", Soap11.getInstance().getReceiver());
   }
}

In SAAJOutInterceptor.handleMessage, the local variable saaj is null, so the code path taken builds a SOAP message from scratch and plugs in a W3CDOMStreamWriter. All of the interceptors then write to W3CDOMStreamWriter instead of the default XMLStreamWriter which normally caches and writes to the HTTP wire. The W3CDOMStreamWriter allows me to transform the DOM before it gets on the wire. Great stuff, it works.

In the second scenario, I test our output feature where in addition to an optional transformation, we have custom interceptors to do optional XML validation before and after the XML transformation. After our provider successfully processed a message, the output chain processing kicks in and looks like this:

Chain org.apache.cxf.phase.PhaseInterceptorChain@c375934. Current flow:
  setup [PolicyOutInterceptor]
  pre-logical [SwAOutInterceptor, SoapHeaderOutFilterInterceptor]
  post-logical [SoapPreProtocolOutInterceptor]
  prepare-send [MessageSenderInterceptor, MessageModeOutInterceptor]
  pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*, AttachmentOutInterceptor, StaxOutInterceptor]
  pre-protocol [MessageModeOutInterceptorInternal, SAAJOutInterceptor, SOAPHandlerInterceptor, OurWSS4JOutInterceptor]
  write [SoapOutInterceptor]
  pre-marshal [LogicalHandlerOutInterceptor, ValidatingOutInterceptor*, TransformOutInterceptor*, ValidatingOutInterceptor*]
  marshal [BareOutInterceptor]
  write-ending [SoapOutEndingInterceptor]
  pre-protocol-ending [SAAJOutEndingInterceptor]
  pre-stream-ending [StaxOutEndingInterceptor]
  prepare-send-ending [MessageSenderEndingInterceptor]

The interceptors marked with * are mine:
- XmlDeclOutInterceptor forces the XML declaration to be written.
- ValidatingOutInterceptor validates XML
- TransformOutInterceptor transforms XML
- ValidatingOutInterceptor validates XML

The problem occurs if XML validation fails (the first validation in this test).

When the XML validation fails, an exception thrown, caught, and re-thrown as a fault.
  
At the start of fault processing, the chain when SAAJOutInterceptor is called looks like this:
  
  Chain org.apache.cxf.phase.PhaseInterceptorChain@77c16c5f. Current flow:
  setup [ServerPolicyOutFaultInterceptor]
  prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
  pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*, StaxOutInterceptor]
  pre-protocol [WebFaultOutInterceptor, SAAJOutInterceptor, SOAPHandlerFaultOutInterceptor]
  write [SoapOutInterceptor]
  pre-marshal [LogicalHandlerFaultOutInterceptor]
  marshal [Soap11FaultOutInterceptorInternal]
  pre-protocol-ending [TransformOutFaultInterceptor*]
  prepare-send-ending [MessageSenderEndingInterceptor]

The interceptors marked with * are mine:
- XmlDeclOutInterceptor forces the XML declaration to be written.
- TransformOutFaultInterceptor validates XML

When I step through this SAAJOutInterceptor invocation, the saaj variable is NOT null, so the code path taken is different from what I described above. Instead of a W3CDOMStreamWriter, a dummy XMLStreamWriter is created that throws away whatever is written to it:

            //as the SOAPMessage already has everything in place, we do not need XMLStreamWriter to write
            //anything for us, so we just set XMLStreamWriter's output to a dummy output stream.         
            XMLStreamWriter origWriter = message.getContent(XMLStreamWriter.class);
            message.put(ORIGINAL_XML_WRITER, origWriter);
            
            XMLStreamWriter dummyWriter = StaxUtils.createXMLStreamWriter(new OutputStream() {
                    public void write(int b) throws IOException {
                    }
                    public void write(byte b[], int off, int len) throws IOException {
                    }                        
                });
            message.setContent(XMLStreamWriter.class, dummyWriter);

No wonder I get no SOAP fault information back, I get:

<?xml version='1.0' encoding='ISO-8859-1'?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
		<ais:requestID xmlns:ais="http://com.seagullsw.appinterface/AppInterfaceServer">{c0a80102-00ce16ad0000010e75da25398002}</ais:requestID>
	</SOAP-ENV:Header>
	<SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" />
</SOAP-ENV:Envelope>

Is this a bug? Why would there be a dummy writer put in place? Is there another CXF way to do this?

Thank you,
Gary

> -----Original Message-----
> From: Gary Gregory
> Sent: Friday, December 18, 2009 18:11
> To: 'Daniel Kulp'; users@cxf.apache.org
> Subject: RE: Inflexible fault interceptor chain?
> 
> Ok, that worked!
> 
> Thank you Dan,
> Gary
> 
> > -----Original Message-----
> > From: Daniel Kulp [mailto:dkulp@apache.org]
> > Sent: Friday, December 18, 2009 07:33
> > To: users@cxf.apache.org
> > Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> > Subject: Re: Inflexible fault interceptor chain?
> >
> >
> > Honestly, the EASIEST way to accomplish this, since you are using
> soap,
> > is to
> > add the SAAJOutInterceptor to the fault chain.  Then, your
> interceptor
> > would
> > live right before it's "ending" interceptor and do:
> >
> > message.getContext(SOAPMessage.class)
> >
> > to get the SAAJ model out.   Since the SAAJ model implements the DOM
> > interfaces, you can then feed that into an XSLT processor or similar
> to
> > transform it and then set a new version back with the setContent
> call.
> >
> >
> > Dan
> >
> >
> > On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > > Hi All:
> > >
> > > I need to apply an XSL transformation to messages coming out of CXF
> > (our
> > >  users configure what the XSL looks like.) For a normal
> (successful)
> > >  message, I have an interceptor (during Phase.PRE_MARSHAL) that
> uses
> > the
> > >  DOM aspect of a message. That works great. BTW, I get to the DOM
> > like
> > >  this:
> > >
> > > Node node = (Node) message.getContent(List.class).get(0);
> > >
> > > That seems brittle, is there a safer way to get to an aspect of the
> > message
> > >  I can feed to javax.xml.transform?
> > >
> > > The real issue comes with fault messages because the fault chain
> uses
> > an
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html>. The fault chain looks like this:
> > >
> > > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current
> > flow:
> > >   setup [ServerPolicyOutFaultInterceptor]
> > >   prepare-send [MessageSenderInterceptor,
> Soap11FaultOutInterceptor]
> > >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> > >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> > >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> > >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> > >   marshal [Soap11FaultOutInterceptorInternal]
> > >   pre-stream-ending [StaxOutEndingInterceptor,
> > >  TransformOutFaultInterceptor*] prepare-send-ending
> > >  [MessageSenderEndingInterceptor]
> > >
> > > FYI, the interceptors marked with * are our own:
> > >
> > > *         XmlDeclOutInterceptor forces an XML declaration to be
> > written.
> > >
> > > *         TransformOutFaultInterceptor is where I thought I could
> > transform
> > >  the fault XML message.
> > >
> > > The
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html> looks like this:
> > >
> > > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter,
> underlying
> > >  outputter:
> > >
> >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> > ati
> > > n1XmlWriter@1125cf44>
> > >
> > > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> > >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> > >
> > > *         currentStream - LoadingByteArrayOutputStream
> > >
> > > *         flowThroughStream -
> > AbstractHTTPDestination$WrappedOutputStream
> > >
> > > All of this to say that when the chain's interceptors are working
> > with the
> > >  message's
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html>, the bytes are cached and written to the wire.
> It
> > is not
> > >  possible to catch the fault XML message and change it.
> > >
> > > The only thing I've come up with but not implemented yet would be
> to
> > insert
> > >  an interceptor before the XML declaration is written and put the
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html> into a temp spot in the message content map,
> then
> > put a
> > >  new
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html> on a byte array in its place. A pre-stream-
> ending
> > >  interceptor can take those bytes, apply XSL to them and then write
> > them to
> > >  the original
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html>, before putting the original
> > >
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> > XML
> > > StreamWriter.html> back in it original slot in the message content
> > map.
> > >
> > > That seems like big old hack.
> > >
> > > Any ideas on a cleaner solution?
> > >
> > > Thank you,
> > > Gary Gregory
> > > Seagull Software
> > > ggregory@seagullsoftware.com
> > > www.seagullsoftware.com
> > >
> >
> > --
> > Daniel Kulp
> > dkulp@apache.org
> > http://www.dankulp.com/blog

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
I'll give that a try. Thank you.

Gary

> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Friday, December 18, 2009 07:33
> To: users@cxf.apache.org
> Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> Subject: Re: Inflexible fault interceptor chain?
> 
> 
> Honestly, the EASIEST way to accomplish this, since you are using soap,
> is to
> add the SAAJOutInterceptor to the fault chain.  Then, your interceptor
> would
> live right before it's "ending" interceptor and do:
> 
> message.getContext(SOAPMessage.class)
> 
> to get the SAAJ model out.   Since the SAAJ model implements the DOM
> interfaces, you can then feed that into an XSLT processor or similar to
> transform it and then set a new version back with the setContent call.
> 
> 
> Dan
> 
> 
> On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > Hi All:
> >
> > I need to apply an XSL transformation to messages coming out of CXF
> (our
> >  users configure what the XSL looks like.) For a normal (successful)
> >  message, I have an interceptor (during Phase.PRE_MARSHAL) that uses
> the
> >  DOM aspect of a message. That works great. BTW, I get to the DOM
> like
> >  this:
> >
> > Node node = (Node) message.getContent(List.class).get(0);
> >
> > That seems brittle, is there a safer way to get to an aspect of the
> message
> >  I can feed to javax.xml.transform?
> >
> > The real issue comes with fault messages because the fault chain uses
> an
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html>. The fault chain looks like this:
> >
> > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current
> flow:
> >   setup [ServerPolicyOutFaultInterceptor]
> >   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> >   marshal [Soap11FaultOutInterceptorInternal]
> >   pre-stream-ending [StaxOutEndingInterceptor,
> >  TransformOutFaultInterceptor*] prepare-send-ending
> >  [MessageSenderEndingInterceptor]
> >
> > FYI, the interceptors marked with * are our own:
> >
> > *         XmlDeclOutInterceptor forces an XML declaration to be
> written.
> >
> > *         TransformOutFaultInterceptor is where I thought I could
> transform
> >  the fault XML message.
> >
> > The
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> looks like this:
> >
> > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter, underlying
> >  outputter:
> >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> ati
> > n1XmlWriter@1125cf44>
> >
> > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> >
> > *         currentStream - LoadingByteArrayOutputStream
> >
> > *         flowThroughStream -
> AbstractHTTPDestination$WrappedOutputStream
> >
> > All of this to say that when the chain's interceptors are working
> with the
> >  message's
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html>, the bytes are cached and written to the wire. It
> is not
> >  possible to catch the fault XML message and change it.
> >
> > The only thing I've come up with but not implemented yet would be to
> insert
> >  an interceptor before the XML declaration is written and put the
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> into a temp spot in the message content map, then
> put a
> >  new
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> on a byte array in its place. A pre-stream-ending
> >  interceptor can take those bytes, apply XSL to them and then write
> them to
> >  the original
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html>, before putting the original
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> back in it original slot in the message content
> map.
> >
> > That seems like big old hack.
> >
> > Any ideas on a cleaner solution?
> >
> > Thank you,
> > Gary Gregory
> > Seagull Software
> > ggregory@seagullsoftware.com
> > www.seagullsoftware.com
> >
> 
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
Ok, that worked!

Thank you Dan,
Gary

> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Friday, December 18, 2009 07:33
> To: users@cxf.apache.org
> Cc: Gary Gregory; Lee Breisacher; Nikolay Glazyrin
> Subject: Re: Inflexible fault interceptor chain?
> 
> 
> Honestly, the EASIEST way to accomplish this, since you are using soap,
> is to
> add the SAAJOutInterceptor to the fault chain.  Then, your interceptor
> would
> live right before it's "ending" interceptor and do:
> 
> message.getContext(SOAPMessage.class)
> 
> to get the SAAJ model out.   Since the SAAJ model implements the DOM
> interfaces, you can then feed that into an XSLT processor or similar to
> transform it and then set a new version back with the setContent call.
> 
> 
> Dan
> 
> 
> On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> > Hi All:
> >
> > I need to apply an XSL transformation to messages coming out of CXF
> (our
> >  users configure what the XSL looks like.) For a normal (successful)
> >  message, I have an interceptor (during Phase.PRE_MARSHAL) that uses
> the
> >  DOM aspect of a message. That works great. BTW, I get to the DOM
> like
> >  this:
> >
> > Node node = (Node) message.getContent(List.class).get(0);
> >
> > That seems brittle, is there a safer way to get to an aspect of the
> message
> >  I can feed to javax.xml.transform?
> >
> > The real issue comes with fault messages because the fault chain uses
> an
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html>. The fault chain looks like this:
> >
> > Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current
> flow:
> >   setup [ServerPolicyOutFaultInterceptor]
> >   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
> >   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> >  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
> >  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
> >   pre-marshal [LogicalHandlerFaultOutInterceptor]
> >   marshal [Soap11FaultOutInterceptorInternal]
> >   pre-stream-ending [StaxOutEndingInterceptor,
> >  TransformOutFaultInterceptor*] prepare-send-ending
> >  [MessageSenderEndingInterceptor]
> >
> > FYI, the interceptors marked with * are our own:
> >
> > *         XmlDeclOutInterceptor forces an XML declaration to be
> written.
> >
> > *         TransformOutFaultInterceptor is where I thought I could
> transform
> >  the fault XML message.
> >
> > The
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> looks like this:
> >
> > [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter, underlying
> >  outputter:
> >
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> ati
> > n1XmlWriter@1125cf44>
> >
> > The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> >  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> >
> > *         currentStream - LoadingByteArrayOutputStream
> >
> > *         flowThroughStream -
> AbstractHTTPDestination$WrappedOutputStream
> >
> > All of this to say that when the chain's interceptors are working
> with the
> >  message's
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html>, the bytes are cached and written to the wire. It
> is not
> >  possible to catch the fault XML message and change it.
> >
> > The only thing I've come up with but not implemented yet would be to
> insert
> >  an interceptor before the XML declaration is written and put the
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> into a temp spot in the message content map, then
> put a
> >  new
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> on a byte array in its place. A pre-stream-ending
> >  interceptor can take those bytes, apply XSL to them and then write
> them to
> >  the original
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html>, before putting the original
> >
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XML
> > StreamWriter.html> back in it original slot in the message content
> map.
> >
> > That seems like big old hack.
> >
> > Any ideas on a cleaner solution?
> >
> > Thank you,
> > Gary Gregory
> > Seagull Software
> > ggregory@seagullsoftware.com
> > www.seagullsoftware.com
> >
> 
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog

Re: Inflexible fault interceptor chain?

Posted by Daniel Kulp <dk...@apache.org>.
Honestly, the EASIEST way to accomplish this, since you are using soap, is to 
add the SAAJOutInterceptor to the fault chain.  Then, your interceptor would 
live right before it's "ending" interceptor and do:

message.getContext(SOAPMessage.class)

to get the SAAJ model out.   Since the SAAJ model implements the DOM 
interfaces, you can then feed that into an XSLT processor or similar to 
transform it and then set a new version back with the setContent call.


Dan


On Fri December 18 2009 4:13:29 am Gary Gregory wrote:
> Hi All:
> 
> I need to apply an XSL transformation to messages coming out of CXF (our
>  users configure what the XSL looks like.) For a normal (successful)
>  message, I have an interceptor (during Phase.PRE_MARSHAL) that uses the
>  DOM aspect of a message. That works great. BTW, I get to the DOM like
>  this:
> 
> Node node = (Node) message.getContent(List.class).get(0);
> 
> That seems brittle, is there a safer way to get to an aspect of the message
>  I can feed to javax.xml.transform?
> 
> The real issue comes with fault messages because the fault chain uses an
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html>. The fault chain looks like this:
> 
> Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current flow:
>   setup [ServerPolicyOutFaultInterceptor]
>   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
>   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
>  StaxOutInterceptor] pre-protocol [WebFaultOutInterceptor,
>  SOAPHandlerFaultOutInterceptor] write [SoapOutInterceptor]
>   pre-marshal [LogicalHandlerFaultOutInterceptor]
>   marshal [Soap11FaultOutInterceptorInternal]
>   pre-stream-ending [StaxOutEndingInterceptor,
>  TransformOutFaultInterceptor*] prepare-send-ending
>  [MessageSenderEndingInterceptor]
> 
> FYI, the interceptors marked with * are our own:
> 
> *         XmlDeclOutInterceptor forces an XML declaration to be written.
> 
> *         TransformOutFaultInterceptor is where I thought I could transform
>  the fault XML message.
> 
> The
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html> looks like this:
> 
> [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter, underlying
>  outputter:
>  com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOLati
> n1XmlWriter@1125cf44>
> 
> The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
>  org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> 
> *         currentStream - LoadingByteArrayOutputStream
> 
> *         flowThroughStream - AbstractHTTPDestination$WrappedOutputStream
> 
> All of this to say that when the chain's interceptors are working with the
>  message's
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html>, the bytes are cached and written to the wire. It is not
>  possible to catch the fault XML message and change it.
> 
> The only thing I've come up with but not implemented yet would be to insert
>  an interceptor before the XML declaration is written and put the
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html> into a temp spot in the message content map, then put a
>  new
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html> on a byte array in its place. A pre-stream-ending
>  interceptor can take those bytes, apply XSL to them and then write them to
>  the original
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html>, before putting the original
>  XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XML
> StreamWriter.html> back in it original slot in the message content map.
> 
> That seems like big old hack.
> 
> Any ideas on a cleaner solution?
> 
> Thank you,
> Gary Gregory
> Seagull Software
> ggregory@seagullsoftware.com
> www.seagullsoftware.com
> 

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog

RE: Inflexible fault interceptor chain?

Posted by Gary Gregory <GG...@seagullsoftware.com>.
Actually, there is no JAXWS or JAXB in this case, the server processes XML documents dynamically.

Gary

> -----Original Message-----
> From: Sergey Beryozkin [mailto:sberyozk@progress.com]
> Sent: Friday, December 18, 2009 02:32
> To: users@cxf.apache.org
> Cc: Lee Breisacher; Nikolay Glazyrin
> Subject: Re: Inflexible fault interceptor chain?
> 
> Hi,
> 
> I'm presuming you use JAXWS.
> Please see a couple of comments inline prefixed with S.B, perhaps they
> migth help
> 
> cheers, Sergey
> 
> Hi All:
> 
> I need to apply an XSL transformation to messages coming out of CXF
> (our users configure what the XSL looks like.) For a normal
> (successful) message, I have an interceptor (during Phase.PRE_MARSHAL)
> that uses the DOM aspect of a message. That works great. BTW,
> I get to the DOM like this:
> 
> Node node = (Node) message.getContent(List.class).get(0);
> 
> That seems brittle, is there a safer way to get to an aspect of the
> message I can feed to javax.xml.transform?
> 
> >S.B. Perhaps you can inject an out interceptor before the response
> object (which is a JAXB Bean) is wrapped into DOM ? And then
> use JAXBContext to marshal into an XSLT engine handler and then abort
> the chain ? JAXBDatabinding keeps the map of existing
> JAXBContexts but I'm not sure how exactly they can be retrieved...
> 
> The real issue comes with fault messages because the fault chain uses
> an
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html>. The fault chain looks like this:
> 
> > S.B : is it possible to catch a Fault before early, and use JAXB to
> XSLT path again, perhaps by wrapping a Fault in a JAXBContext
> > ?
> 
> 
> Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current
> flow:
>   setup [ServerPolicyOutFaultInterceptor]
>   prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
>   pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*,
> StaxOutInterceptor]
>   pre-protocol [WebFaultOutInterceptor, SOAPHandlerFaultOutInterceptor]
>   write [SoapOutInterceptor]
>   pre-marshal [LogicalHandlerFaultOutInterceptor]
>   marshal [Soap11FaultOutInterceptorInternal]
>   pre-stream-ending [StaxOutEndingInterceptor,
> TransformOutFaultInterceptor*]
>   prepare-send-ending [MessageSenderEndingInterceptor]
> 
> FYI, the interceptors marked with * are our own:
> 
> *         XmlDeclOutInterceptor forces an XML declaration to be
> written.
> 
> *         TransformOutFaultInterceptor is where I thought I could
> transform the fault XML message.
> 
> The
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html> looks like this:
> 
> [StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter, underlying
> outputter:
> com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<mailto:com.ctc.wstx.sw.ISOL
> atin1XmlWriter@1125cf44>
> 
> The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a
> org.apache.cxf.io.CachedOutputStream, which in turns wraps:
> 
> *         currentStream - LoadingByteArrayOutputStream
> 
> *         flowThroughStream -
> AbstractHTTPDestination$WrappedOutputStream
> 
> All of this to say that when the chain's interceptors are working with
> the message's
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html>, the bytes are cached and written to
> the wire. It is not possible to catch the fault XML message and change
> it.
> 
> The only thing I've come up with but not implemented yet would be to
> insert an interceptor before the XML declaration is written and
> put the
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html> into a temp spot in the message
> content map, then put a new
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html> on a byte
> array in its place. A pre-stream-ending interceptor can take those
> bytes, apply XSL to them and then write them to the original
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html>, before putting the original
> XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/
> XMLStreamWriter.html> back in it original slot in the message
> content map.
> 
> That seems like big old hack.
> 
> Any ideas on a cleaner solution?
> 
> Thank you,
> Gary Gregory
> Seagull Software
> ggregory@seagullsoftware.com
> www.seagullsoftware.com
> 


Re: Inflexible fault interceptor chain?

Posted by Sergey Beryozkin <sb...@progress.com>.
Hi,

I'm presuming you use JAXWS.
Please see a couple of comments inline prefixed with S.B, perhaps they migth help

cheers, Sergey

Hi All:

I need to apply an XSL transformation to messages coming out of CXF (our users configure what the XSL looks like.) For a normal 
(successful) message, I have an interceptor (during Phase.PRE_MARSHAL) that uses the DOM aspect of a message. That works great. BTW, 
I get to the DOM like this:

Node node = (Node) message.getContent(List.class).get(0);

That seems brittle, is there a safer way to get to an aspect of the message I can feed to javax.xml.transform?

>S.B. Perhaps you can inject an out interceptor before the response object (which is a JAXB Bean) is wrapped into DOM ? And then
use JAXBContext to marshal into an XSLT engine handler and then abort the chain ? JAXBDatabinding keeps the map of existing 
JAXBContexts but I'm not sure how exactly they can be retrieved...

The real issue comes with fault messages because the fault chain uses an 
XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html>. The fault chain looks like this:

> S.B : is it possible to catch a Fault before early, and use JAXB to XSLT path again, perhaps by wrapping a Fault in a JAXBContext 
> ?


Chain org.apache.cxf.phase.PhaseInterceptorChain@3015b303. Current flow:
  setup [ServerPolicyOutFaultInterceptor]
  prepare-send [MessageSenderInterceptor, Soap11FaultOutInterceptor]
  pre-stream [LoggingOutInterceptor, XmlDeclOutInterceptor*, StaxOutInterceptor]
  pre-protocol [WebFaultOutInterceptor, SOAPHandlerFaultOutInterceptor]
  write [SoapOutInterceptor]
  pre-marshal [LogicalHandlerFaultOutInterceptor]
  marshal [Soap11FaultOutInterceptorInternal]
  pre-stream-ending [StaxOutEndingInterceptor, TransformOutFaultInterceptor*]
  prepare-send-ending [MessageSenderEndingInterceptor]

FYI, the interceptors marked with * are our own:

*         XmlDeclOutInterceptor forces an XML declaration to be written.

*         TransformOutFaultInterceptor is where I thought I could transform the fault XML message.

The XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> looks like this:

[StreamWriter: class com.ctc.wstx.sw.SimpleNsStreamWriter, underlying outputter: 
com.ctc.wstx.sw.ISOLatin1XmlWriter@1125cf44<ma...@1125cf44>

The com.ctc.wstx.sw.ISOLatin1XmlWriter wraps a org.apache.cxf.io.CachedOutputStream, which in turns wraps:

*         currentStream - LoadingByteArrayOutputStream

*         flowThroughStream - AbstractHTTPDestination$WrappedOutputStream

All of this to say that when the chain's interceptors are working with the message's 
XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html>, the bytes are cached and written to 
the wire. It is not possible to catch the fault XML message and change it.

The only thing I've come up with but not implemented yet would be to insert an interceptor before the XML declaration is written and 
put the XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> into a temp spot in the message 
content map, then put a new XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> on a byte 
array in its place. A pre-stream-ending interceptor can take those bytes, apply XSL to them and then write them to the original 
XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html>, before putting the original 
XMLStreamWriter<http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamWriter.html> back in it original slot in the message 
content map.

That seems like big old hack.

Any ideas on a cleaner solution?

Thank you,
Gary Gregory
Seagull Software
ggregory@seagullsoftware.com
www.seagullsoftware.com