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.phaseinterceptorch...@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.isolatin1xmlwri...@1125cf44<mailto:com.ctc.wstx.sw.isolatin1xmlwri...@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
[email protected]
www.seagullsoftware.com


Reply via email to