You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Varun Singhal <va...@live.com> on 2019/03/04 18:39:24 UTC
[Reading CXF message content] What is CachedOutputStream's primary
purpose and how its different than DelegatingInputStream ?
Hi all,
Greetings !
I have designed a interceptor that runs in RECEIVE phase and takes a decision whether to modify the header of an incoming SOAP request OR not.
It does so by reading the message's contents and parsing it into a XML document instance.
Here is the code:
//get message as stream
InputStream ipStream = message.getContent(InputStream.class);
CachedOutputStream cos = new CachedOutputStream();
//create a re-readable inputstream
IOUtils.copy(ipStream, cos);
ipStream.close();
cos.flush();
//set the new inputstream
message.setContent(InputStream.class, cos.getInputStream());
//XML document instance
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(cos.getInputStream());
cos.close();
if (doc != null) {
takeDecisionOnHeaderModification(doc);
}
}
The code works fine.
As you can make out i needed a re-readable `inputStream` otherwise successive application code/interceptors would have empty input stream.
so i used CachedOutputStream because cos.getInputStream() is re-readable.
Here are my queries about this approach :
Query#1 :
If CachedOutputStream is used for creating a re-readable inputStream why the name is so misleading ? (It doesn't even have input word in it)
Query#2 :
For the requirement of re-readable inputStream, is CachedOutputStream the best candidate, why not DelegatingInputStream<https://cxf.apache.org/javadoc/latest/org/apache/cxf/io/DelegatingInputStream.html>, if yes would you be kind enough to provide a working code snippet of same ?
I will be very grateful if anyone could shed light on these queries ?
Many Thanks !
Warm Regards,
Varun SINGHAL
Re: [Reading CXF message content] What is CachedOutputStream's
primary purpose and how its different than DelegatingInputStream ?
Posted by Varun Singhal <va...@live.com>.
Hello Daniel,
Many thanks for the advise, it works well.
I am quite happy now all the in-efficient transformations have gone now š.
Many thanks for the optimized approach !
Warm Regards,
Varun SINGHAL
________________________________
From: Daniel Kulp <dk...@apache.org>
Sent: Wednesday, March 6, 2019 8:15 PM
To: users@cxf.apache.org; Varun Singhal
Subject: Re: [Reading CXF message content] What is CachedOutputStream's primary purpose and how its different than DelegatingInputStream ?
Comments inlineā¦..
> On Mar 6, 2019, at 2:30 AM, Varun Singhal <va...@live.com> wrote:
>
> Solution :
> Examine the request, if "<wsa:MessageID>" is absent add it in the headers !
>
> Solution Implementation :
> Add 2 interceptors to the IN interceptor chain.
> First intereptor detects if a "<wsa:MessageID>" header is absent, if absent then it adds a "transformInterceptor" in the interceptor chain to append a bogus "<wsa:MessageID>" header
>
> Solution Code (Also attached):
> Here is the code for first interceptor/MessageIdDetector
>
> public class MessageIdDetector extends AbstractSoapInterceptor {
>
> private static final String CXF_TRANSFORM_MESSAGE_ID_ELEMENT_KEY =
> "{http://schemas.xmlsoap.org/soap/envelope/ <http://schemas.xmlsoap.org/soap/envelope/>}Header/";
> private static final String CXF_TRANSFORM_MESSAGE_ID_ELEMENT_VALUE =
> "{http://schemas.xmlsoap.org/ws/2004/08/addressing <http://schemas.xmlsoap.org/ws/2004/08/addressing>}MessageID=http://www.w3.org/2005/08/addressing/unspecified <http://www.w3.org/2005/08/addressing/unspecified>";
>
>
> public MessageIdDetector() {
> super(Phase.READ);
> addAfter(ReadHeadersInterceptor.class.getName());
> }
>
> @Override
> public void handleMessage(SoapMessage message) throws Fault {
> QName messageIdQname = new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing <http://schemas.xmlsoap.org/ws/2004/08/addressing>", "MessageID");
> boolean isMessageIDheaderPresent = message.hasHeader(messageIdQname);
> if (!isMessageIDheaderPresent) {
> addMessageIdTransformInInterceptor(message);
> }
> }
>
This part is perfect. It would detect the presence of the messageID header and, if not present, does somethingā¦.
> /**
> * Adds a transform interceptor to the chain in order to transform the message
> *
> * @param message
> */
> private void addMessageIdTransformInInterceptor(Message message) {
> TransformInInterceptor transformInterceptor = new TransformInInterceptor(Phase.PRE_PROTOCOL);
> Map<String, String> inAppendMap = new HashMap<>();
> // this map contains the messageID element that we want to append to message
> inAppendMap.put(CXF_TRANSFORM_MESSAGE_ID_ELEMENT_KEY, CXF_TRANSFORM_MESSAGE_ID_ELEMENT_VALUE);
> transformInterceptor.setInAppendElements(inAppendMap);
> transformInterceptor.addBefore(SAAJInInterceptor.class.getName());
> // add the interceptor to the current chain
> message.getInterceptorChain()
> .add(transformInterceptor);
> }
>
> }
This is where you are doing a bunch of stuff that isnāt necessary. Instead of adding a second interceptor, create a new DOM element with your āfakeā MessageID, wrapper it with a org.apache.cxf.headers.Header object, and just add it to the list of headers. So something like:
Document doc = org.apache.cxf.helpers.DOMUtils.getEmptyDocument();
Element el = doc.createElementNS(Names.WSA_NAMESPACE_NAME, āwsa:MessageIDā);
el.appendChild(doc.createTextNode(newId);
Header header = new Header(Names.WSA_MESSAGEID_QNAME, el);
soapMessage.getHeaders().add(header);
That should be all that is necessary. That gets the message ID into the list of headers that MAPCodec will process. You would need to use the right namespaces and such to match the other addressing headers and such, but that should give you an idea how to handle it.
--
Daniel Kulp
dkulp@apache.org <ma...@apache.org> - http://dankulp.com/blog <http://dankulp.com/blog>
Talend Community Coder - http://talend.com <http://coders.talend.com/>
Re: [Reading CXF message content] What is CachedOutputStream's
primary purpose and how its different than DelegatingInputStream ?
Posted by Daniel Kulp <dk...@apache.org>.
Comments inlineā¦..
> On Mar 6, 2019, at 2:30 AM, Varun Singhal <va...@live.com> wrote:
>
> Solution :
> Examine the request, if "<wsa:MessageID>" is absent add it in the headers !
>
> Solution Implementation :
> Add 2 interceptors to the IN interceptor chain.
> First intereptor detects if a "<wsa:MessageID>" header is absent, if absent then it adds a "transformInterceptor" in the interceptor chain to append a bogus "<wsa:MessageID>" header
>
> Solution Code (Also attached):
> Here is the code for first interceptor/MessageIdDetector
>
> public class MessageIdDetector extends AbstractSoapInterceptor {
>
> private static final String CXF_TRANSFORM_MESSAGE_ID_ELEMENT_KEY =
> "{http://schemas.xmlsoap.org/soap/envelope/ <http://schemas.xmlsoap.org/soap/envelope/>}Header/";
> private static final String CXF_TRANSFORM_MESSAGE_ID_ELEMENT_VALUE =
> "{http://schemas.xmlsoap.org/ws/2004/08/addressing <http://schemas.xmlsoap.org/ws/2004/08/addressing>}MessageID=http://www.w3.org/2005/08/addressing/unspecified <http://www.w3.org/2005/08/addressing/unspecified>";
>
>
> public MessageIdDetector() {
> super(Phase.READ);
> addAfter(ReadHeadersInterceptor.class.getName());
> }
>
> @Override
> public void handleMessage(SoapMessage message) throws Fault {
> QName messageIdQname = new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing <http://schemas.xmlsoap.org/ws/2004/08/addressing>", "MessageID");
> boolean isMessageIDheaderPresent = message.hasHeader(messageIdQname);
> if (!isMessageIDheaderPresent) {
> addMessageIdTransformInInterceptor(message);
> }
> }
>
This part is perfect. It would detect the presence of the messageID header and, if not present, does somethingā¦.
> /**
> * Adds a transform interceptor to the chain in order to transform the message
> *
> * @param message
> */
> private void addMessageIdTransformInInterceptor(Message message) {
> TransformInInterceptor transformInterceptor = new TransformInInterceptor(Phase.PRE_PROTOCOL);
> Map<String, String> inAppendMap = new HashMap<>();
> // this map contains the messageID element that we want to append to message
> inAppendMap.put(CXF_TRANSFORM_MESSAGE_ID_ELEMENT_KEY, CXF_TRANSFORM_MESSAGE_ID_ELEMENT_VALUE);
> transformInterceptor.setInAppendElements(inAppendMap);
> transformInterceptor.addBefore(SAAJInInterceptor.class.getName());
> // add the interceptor to the current chain
> message.getInterceptorChain()
> .add(transformInterceptor);
> }
>
> }
This is where you are doing a bunch of stuff that isnāt necessary. Instead of adding a second interceptor, create a new DOM element with your āfakeā MessageID, wrapper it with a org.apache.cxf.headers.Header object, and just add it to the list of headers. So something like:
Document doc = org.apache.cxf.helpers.DOMUtils.getEmptyDocument();
Element el = doc.createElementNS(Names.WSA_NAMESPACE_NAME, āwsa:MessageIDā);
el.appendChild(doc.createTextNode(newId);
Header header = new Header(Names.WSA_MESSAGEID_QNAME, el);
soapMessage.getHeaders().add(header);
That should be all that is necessary. That gets the message ID into the list of headers that MAPCodec will process. You would need to use the right namespaces and such to match the other addressing headers and such, but that should give you an idea how to handle it.
--
Daniel Kulp
dkulp@apache.org <ma...@apache.org> - http://dankulp.com/blog <http://dankulp.com/blog>
Talend Community Coder - http://talend.com <http://coders.talend.com/>
Re: [Reading CXF message content] What is CachedOutputStream's
primary purpose and how its different than DelegatingInputStream ?
Posted by Varun Singhal <va...@live.com>.
Hi Daniel,
Many thanks for your insights !
Regarding the in-efficiency of approach taken, i completely agree. However, i dont see any other solution, i will tell you my complete problem that i am trying to solve.
May be you could advise for a better solution.
Problem :
Post CXF upgrade to 3.2.7 from a quite old version, MapCodec interceptor enforces, that a tag called "<wsa:MessageID>" should be present in CXF request, if absent CXF drops the request. Unfortunately some customers of our webservice send "<wsa:MessageID>" , others don't.
Solution :
Examine the request, if "<wsa:MessageID>" is absent add it in the headers !
Solution Implementation :
Add 2 interceptors to the IN interceptor chain.
First intereptor detects if a "<wsa:MessageID>" header is absent, if absent then it adds a "transformInterceptor" in the interceptor chain to append a bogus "<wsa:MessageID>" header
Solution Code (Also attached):
Here is the code for first interceptor/MessageIdDetector
public class MessageIdDetector extends AbstractSoapInterceptor {
private static final String CXF_TRANSFORM_MESSAGE_ID_ELEMENT_KEY =
"{http://schemas.xmlsoap.org/soap/envelope/}Header/";
private static final String CXF_TRANSFORM_MESSAGE_ID_ELEMENT_VALUE =
"{http://schemas.xmlsoap.org/ws/2004/08/addressing}MessageID=http://www.w3.org/2005/08/addressing/unspecified";
public MessageIdDetector() {
super(Phase.READ);
addAfter(ReadHeadersInterceptor.class.getName());
}
@Override
public void handleMessage(SoapMessage message) throws Fault {
QName messageIdQname = new QName("http://schemas.xmlsoap.org/ws/2004/08/addressing", "MessageID");
boolean isMessageIDheaderPresent = message.hasHeader(messageIdQname);
if (!isMessageIDheaderPresent) {
addMessageIdTransformInInterceptor(message);
}
}
/**
* Adds a transform interceptor to the chain in order to transform the message
*
* @param message
*/
private void addMessageIdTransformInInterceptor(Message message) {
TransformInInterceptor transformInterceptor = new TransformInInterceptor(Phase.PRE_PROTOCOL);
Map<String, String> inAppendMap = new HashMap<>();
// this map contains the messageID element that we want to append to message
inAppendMap.put(CXF_TRANSFORM_MESSAGE_ID_ELEMENT_KEY, CXF_TRANSFORM_MESSAGE_ID_ELEMENT_VALUE);
transformInterceptor.setInAppendElements(inAppendMap);
transformInterceptor.addBefore(SAAJInInterceptor.class.getName());
// add the interceptor to the current chain
message.getInterceptorChain()
.add(transformInterceptor);
}
}
Why this solution fails and i have to opt for the in-efficient approach ?
As per above code when the incoming request doesn't have the "<wsa:MessageID>", transformInterceptor is added and post execution of first interceptor,
Following is the interceptor chain :
receive [PolicyInInterceptor, AttachmentInInterceptor]
pre-stream [CertConstraintsInterceptor]
post-stream [StaxInInterceptor]
read [SAAJPreInInterceptor, ReadHeadersInterceptor, MessageIdDetector, WSDLGetInterceptor, SoapActionInInterceptor, StartBodyInterceptor]
pre-protocol [TransformInInterceptor, SAAJInInterceptor, MAPCodec, WSS4JInInterceptor, MustUnderstandInterceptor]
post-protocol [CheckFaultInterceptor]
unmarshal [DocLiteralInInterceptor, SoapHeaderInterceptor]
pre-logical [MAPAggregatorImpl, OneWayProcessorInterceptor]
post-logical [MessageModeInInterceptor]
pre-invoke [StaxInEndingInterceptor, SwAInInterceptor]
invoke [ServiceInvokerInterceptor]
post-invoke [OutgoingChainInterceptor]
However, CXF fails with the following exception :
11:18:27,068 WARNING [org.apache.cxf.phase.PhaseInterceptorChain] (http-127.0.0.1:8080-1) Interceptor for <redacted> has thrown exception, unwinding now: java.util.NoSuchElementException
at java.util.LinkedList.removeFirst(LinkedList.java:270) [rt.jar:1.8.0_191]
at org.apache.cxf.staxutils.transform.DelegatingNamespaceContext.up(DelegatingNamespaceContext.java:50) [cxf-core-3.2.7.jar:3.2.7]
at org.apache.cxf.staxutils.transform.InTransformReader.next(InTransformReader.java:171) [cxf-core-3.2.7.jar:3.2.7]
at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:793) [cxf-core-3.2.7.jar:3.2.7]
I have attched full stacktrace in the attachments.
Now if i move the transformation step prior to ReadHeadersInterceptor the exact same transformInterceptor works, but i loose the access to message.getHeaders() and hence the in-efficient approach.
Please advise if something comes to your mind, OR a better approach that i can take.
Many thanks for advsing on my queries š!
Warm Regards,
Varun SINGHAL
________________________________
From: Daniel Kulp <dk...@apache.org>
Sent: Tuesday, March 5, 2019 6:55 PM
To: users@cxf.apache.org; Varun Singhal
Subject: Re: [Reading CXF message content] What is CachedOutputStream's primary purpose and how its different than DelegatingInputStream ?
Well, my first thought is that for what you are trying to do, you are doing it in a very in-efficient manner. :)
For the most part, you would be better off adding an interceptor to the beginning of the PRE_PROTOCOL phase. At that point, you could do:
((SoapMessage)message).getHeaders()
To get the list of headers that have already been parsed. You could modify the contents of the header objects at that point. This would not break streaming of the body and would perform significantly better, particularly for large requests. Your method involves parsing the entire message twice, potentially storing larger messages on disk.
Now, to answer the specific question2:
Query#1 :
If CachedOutputStream is used for creating a re-readable inputStream why the name is so misleading ? (It doesn't even have input word in it)
CachedOutputStream is not just used for that. Itās not required to ever get an InputStream from it. There is a writeCacheTo method that can be used to write everything to a different output stream. There is a getBytes() call for getting everything as a byte[], etcā¦. Its primary use case is via the CachedOutputStreamCallback objects. In some cases, we use the CachedOutputStream to start writing, and once a certain threshold is hit, the callback is triggered and the cache is flushed to a real output stream, and the CachedOutputStream is replaced with the real output stream. Thus, if the amount of data never hits the threshold, we can optimize certain cases, but if it does, we go another route.
Query#2 :
For the requirement of re-readable inputStream, is CachedOutputStream the best candidate, why not DelegatingInputStream<https://cxf.apache.org/javadoc/latest/org/apache/cxf/io/DelegatingInputStream.html>, if yes would you be kind enough to provide a working code snippet of same ?
CachedOutputStream is likely the best option at this point, but see above for your specific use case.
Dan
On Mar 5, 2019, at 10:30 AM, Varun Singhal <va...@live.com>> wrote:
Hi guys,
Can anyone advise on the below queries, please ?
I really want to understand if my understanding is flawed ā¹
Many thanks !
Warm Regards,
Varun SINGHAL
________________________________
From: Varun Singhal
Sent: Tuesday, March 5, 2019 12:09:24 AM
To: users@cxf.apache.org<ma...@cxf.apache.org>
Subject: [Reading CXF message content] What is CachedOutputStream's primary purpose and how its different than DelegatingInputStream ?
Hi all,
Greetings !
I have designed a interceptor that runs in RECEIVE phase and takes a decision whether to modify the header of an incoming SOAP request OR not.
It does so by reading the message's contents and parsing it into a XML document instance.
Here is the code:
//get message as stream
InputStream ipStream = message.getContent(InputStream.class);
CachedOutputStream cos = new CachedOutputStream();
//create a re-readable inputstream
IOUtils.copy(ipStream, cos);
ipStream.close();
cos.flush();
//set the new inputstream
message.setContent(InputStream.class, cos.getInputStream());
//XML document instance
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(cos.getInputStream());
cos.close();
if (doc != null) {
takeDecisionOnHeaderModification(doc);
}
}
The code works fine.
As you can make out i needed a re-readable `inputStream` otherwise successive application code/interceptors would have empty input stream.
so i used CachedOutputStream because cos.getInputStream() is re-readable.
Here are my queries about this approach :
Query#1 :
If CachedOutputStream is used for creating a re-readable inputStream why the name is so misleading ? (It doesn't even have input word in it)
Query#2 :
For the requirement of re-readable inputStream, is CachedOutputStream the best candidate, why not DelegatingInputStream<https://cxf.apache.org/javadoc/latest/org/apache/cxf/io/DelegatingInputStream.html>, if yes would you be kind enough to provide a working code snippet of same ?
I will be very grateful if anyone could shed light on these queries ?
Many Thanks !
Warm Regards,
Varun SINGHAL
--
Daniel Kulp
dkulp@apache.org<ma...@apache.org> - http://dankulp.com/blog
Talend Community Coder - http://talend.com<http://coders.talend.com>
Re: [Reading CXF message content] What is CachedOutputStream's
primary purpose and how its different than DelegatingInputStream ?
Posted by Daniel Kulp <dk...@apache.org>.
Well, my first thought is that for what you are trying to do, you are doing it in a very in-efficient manner. :)
For the most part, you would be better off adding an interceptor to the beginning of the PRE_PROTOCOL phase. At that point, you could do:
((SoapMessage)message).getHeaders()
To get the list of headers that have already been parsed. You could modify the contents of the header objects at that point. This would not break streaming of the body and would perform significantly better, particularly for large requests. Your method involves parsing the entire message twice, potentially storing larger messages on disk.
Now, to answer the specific question2:
> Query#1 :
> If CachedOutputStream is used for creating a re-readable inputStream why the name is so misleading ? (It doesn't even have input word in it)
CachedOutputStream is not just used for that. Itās not required to ever get an InputStream from it. There is a writeCacheTo method that can be used to write everything to a different output stream. There is a getBytes() call for getting everything as a byte[], etcā¦. Its primary use case is via the CachedOutputStreamCallback objects. In some cases, we use the CachedOutputStream to start writing, and once a certain threshold is hit, the callback is triggered and the cache is flushed to a real output stream, and the CachedOutputStream is replaced with the real output stream. Thus, if the amount of data never hits the threshold, we can optimize certain cases, but if it does, we go another route.
> Query#2 :
> For the requirement of re-readable inputStream, is CachedOutputStream the best candidate, why not DelegatingInputStream<https://cxf.apache.org/javadoc/latest/org/apache/cxf/io/DelegatingInputStream.html>, if yes would you be kind enough to provide a working code snippet of same ?
CachedOutputStream is likely the best option at this point, but see above for your specific use case.
Dan
> On Mar 5, 2019, at 10:30 AM, Varun Singhal <va...@live.com> wrote:
>
> Hi guys,
>
> Can anyone advise on the below queries, please ?
>
> I really want to understand if my understanding is flawed ā¹
>
> Many thanks !
>
> Warm Regards,
> Varun SINGHAL
>
> ________________________________
> From: Varun Singhal
> Sent: Tuesday, March 5, 2019 12:09:24 AM
> To: users@cxf.apache.org
> Subject: [Reading CXF message content] What is CachedOutputStream's primary purpose and how its different than DelegatingInputStream ?
>
> Hi all,
>
> Greetings !
>
> I have designed a interceptor that runs in RECEIVE phase and takes a decision whether to modify the header of an incoming SOAP request OR not.
> It does so by reading the message's contents and parsing it into a XML document instance.
>
> Here is the code:
>
> //get message as stream
> InputStream ipStream = message.getContent(InputStream.class);
> CachedOutputStream cos = new CachedOutputStream();
> //create a re-readable inputstream
> IOUtils.copy(ipStream, cos);
> ipStream.close();
> cos.flush();
> //set the new inputstream
> message.setContent(InputStream.class, cos.getInputStream());
> //XML document instance
> DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
> DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
> doc = dBuilder.parse(cos.getInputStream());
> cos.close();
> if (doc != null) {
> takeDecisionOnHeaderModification(doc);
> }
> }
>
> The code works fine.
> As you can make out i needed a re-readable `inputStream` otherwise successive application code/interceptors would have empty input stream.
> so i used CachedOutputStream because cos.getInputStream() is re-readable.
>
> Here are my queries about this approach :
>
> Query#1 :
> If CachedOutputStream is used for creating a re-readable inputStream why the name is so misleading ? (It doesn't even have input word in it)
>
> Query#2 :
> For the requirement of re-readable inputStream, is CachedOutputStream the best candidate, why not DelegatingInputStream<https://cxf.apache.org/javadoc/latest/org/apache/cxf/io/DelegatingInputStream.html>, if yes would you be kind enough to provide a working code snippet of same ?
>
> I will be very grateful if anyone could shed light on these queries ?
>
> Many Thanks !
>
> Warm Regards,
>
> Varun SINGHAL
>
--
Daniel Kulp
dkulp@apache.org <ma...@apache.org> - http://dankulp.com/blog <http://dankulp.com/blog>
Talend Community Coder - http://talend.com <http://coders.talend.com/>
RE: [Reading CXF message content] What is CachedOutputStream's
primary purpose and how its different than DelegatingInputStream ?
Posted by Varun Singhal <va...@live.com>.
Hi guys,
Can anyone advise on the below queries, please ?
I really want to understand if my understanding is flawed ā¹
Many thanks !
Warm Regards,
Varun SINGHAL
________________________________
From: Varun Singhal
Sent: Tuesday, March 5, 2019 12:09:24 AM
To: users@cxf.apache.org
Subject: [Reading CXF message content] What is CachedOutputStream's primary purpose and how its different than DelegatingInputStream ?
Hi all,
Greetings !
I have designed a interceptor that runs in RECEIVE phase and takes a decision whether to modify the header of an incoming SOAP request OR not.
It does so by reading the message's contents and parsing it into a XML document instance.
Here is the code:
//get message as stream
InputStream ipStream = message.getContent(InputStream.class);
CachedOutputStream cos = new CachedOutputStream();
//create a re-readable inputstream
IOUtils.copy(ipStream, cos);
ipStream.close();
cos.flush();
//set the new inputstream
message.setContent(InputStream.class, cos.getInputStream());
//XML document instance
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
doc = dBuilder.parse(cos.getInputStream());
cos.close();
if (doc != null) {
takeDecisionOnHeaderModification(doc);
}
}
The code works fine.
As you can make out i needed a re-readable `inputStream` otherwise successive application code/interceptors would have empty input stream.
so i used CachedOutputStream because cos.getInputStream() is re-readable.
Here are my queries about this approach :
Query#1 :
If CachedOutputStream is used for creating a re-readable inputStream why the name is so misleading ? (It doesn't even have input word in it)
Query#2 :
For the requirement of re-readable inputStream, is CachedOutputStream the best candidate, why not DelegatingInputStream<https://cxf.apache.org/javadoc/latest/org/apache/cxf/io/DelegatingInputStream.html>, if yes would you be kind enough to provide a working code snippet of same ?
I will be very grateful if anyone could shed light on these queries ?
Many Thanks !
Warm Regards,
Varun SINGHAL