[
https://issues.apache.org/jira/browse/CXF-2594?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12794751#action_12794751
]
Gary Gregory commented on CXF-2594:
-----------------------------------
-----Original Message-----
From: Gary Gregory [mailto:[email protected]]
Sent: Monday, December 21, 2009 17:13
To: Daniel Kulp; [email protected]
Subject: RE: Inflexible fault interceptor chain?
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.phaseinterceptorch...@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.phaseinterceptorch...@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
> No SOAP fault XML elements when a Fault is thrown in the output chain after
> SAAJOutInterceptor
> ----------------------------------------------------------------------------------------------
>
> Key: CXF-2594
> URL: https://issues.apache.org/jira/browse/CXF-2594
> Project: CXF
> Issue Type: Bug
> Affects Versions: 2.2.4
> Environment: java version "1.6.0_16"
> Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
> Java HotSpot(TM) 64-Bit Server VM (build 14.2-b01, mixed mode)
> Microsoft Windows [Version 6.0.6002]
> Apache Maven 2.2.1 (r801777; 2009-08-06 12:16:01-0700)
> Java version: 1.6.0_16
> Java home: C:\Program Files\Java\jdk1.6.0_16\jre
> Default locale: en_US, platform encoding: Cp1252
> OS name: "windows vista" version: "6.0" arch: "amd64" Family: "windows"
> Eclipse 3.6M4:
> Version: 3.6.0
> Build id: I20091210-1301
> Reporter: Gary Gregory
> Fix For: 2.2.6
>
>
> The attached unit test runs on top of the 2.2.x SVN branch updated from SVN
> as of now.
> This ticket originated with this thread:
> http://old.nabble.com/Inflexible-fault-interceptor-chain--td26840876.html
> Which I replicate here with comments used for each step:
> 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.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
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.