On Friday 21 March 2008, Yuval Zou wrote:
> Hi Dan,
>
> I have tried the second option. I modified the codes as you suggested.
> It works but the attachment data are still embeded in the cached
> stream. So the performance of the transformation is terrible. The code
> looks like below, could you please help to find if there is something
> wrong and how can I fix it? Thank you very much!
Try moving the interceptors inside the bounds of the
AttachmentOutInterceptors:
First interceptor:
addAfter(AttachmentOutInterceptor.class.getName());
Second interceptor:
addBefore(AttachmentOutInterceptor.AttachmentOutEndingInterceptor.class.getName());
That should do the trick and only give you the root part.
Dan
>
> public class StreamInterceptor extends AbstractPhaseInterceptor {
>
> private StreamEndingInterceptor ending = new
> StreamEndingInterceptor(); public static final String ORIGINAL_OUTPUT
> = "original_output";
>
> public StreamInterceptor() {
> super(Phase.PRE_STREAM);
> addBefore(AttachmentOutInterceptor.class.getName());
> }
>
> public void handleMessage(Message message) {
> OutputStream os = message.getContent(OutputStream.class);
> message.put(ORIGINAL_OUTPUT, os);
> CachedStream cs = new CachedStream();
> message.setContent(OutputStream.class, cs);
>
> // message.getInterceptorChain().doIntercept(message);
> try {
> cs.flush();
> } catch (IOException e) {
> e.printStackTrace();
> }
> message.getInterceptorChain().add(ending);
> }
>
> public void handleFault(Message message) {
> }
>
> public class StreamEndingInterceptor extends
> AbstractPhaseInterceptor {
>
> public StreamEndingInterceptor() {
> super(Phase.PRE_STREAM_ENDING);
>
> addAfter(AttachmentOutInterceptor.AttachmentOutEndingInterceptor.class
>.getName()); }
>
> public void handleMessage(Message message) {
> try {
> CachedOutputStream csnew = (CachedOutputStream)
> message.getContent(OutputStream.class);
> OutputStream os = (OutputStream)
> message.get(ORIGINAL_OUTPUT);
>
> StringBuilder sb = new StringBuilder();
> csnew.writeCacheTo(sb);
>
> String tmpXML = sb.toString();
> System.out.println("#####OLD#####" + tmpXML);
> while (tmpXML.indexOf("<ns2:")!=-1){
> String subTmp =
> tmpXML.substring(tmpXML.indexOf("<ns2:")); subTmp =
> subTmp.substring(1, subTmp.indexOf(" ")); tmpXML =
> tmpXML.replaceAll(subTmp, subTmp.substring(4) + " " +
> "xmlns=\"http://www.ibm.com/xmlns/db2/cm/api/1.0/schema\" ");
> System.out.println("#####FIXED#####" + tmpXML); }
>
> InputStream in = new
> ByteArrayInputStream(tmpXML.getBytes()); BufferedOutputStream bos =
> new BufferedOutputStream(os); CachedOutputStream.copyStream(in, bos,
> 1024);
>
> csnew.close();
> in.close();
> bos.close();
> os.flush();
>
> // message.setContent(OutputStream.class, os);
> } catch (IOException e) {
> e.printStackTrace();
> }
> }
>
> }
>
> private class CachedStream extends CachedOutputStream {
>
> public CachedStream() {
> super();
> }
>
> protected void doFlush() throws IOException {
> currentStream.flush();
> }
>
> protected void doClose() throws IOException {
> }
>
> protected void onWrite() throws IOException {
> }
>
> }
> }
>
> Yuval
>
> dkulp wrote:
> > This is definitely a bug for whomever is consuming that message.
> > According to the XML rules, both messages are equivilent.
> >
> > Couple options:
> >
> > 1) Best performing option: write an interceptor that would be
> > immediately AFTER the StaxOutInterceptor that would take the
> > XMLStreamWriter and replace it with a new XMLStreamWriter that
> > wrappers the original, but overwrides the start element and
> > namespace map stuff so that it generates empty prefixes at all
> > times. That StreamWriter might be a bit tricky to write if you
> > aren't familliar with StAX, but it would definitely be the best
> > performing as you wouln't break the streaming, you wouldn't need to
> > scan the byte[], etc.... FYI: your interceptor will also need to
> > set:
> > msg.put(AbstractOutDatabindingInterceptor.DISABLE_OUTPUTSTREAM_OPTIM
> >IZATION, Boolean.TRUE);
> > to make sure it actually uses the new StreamWriter in all cases.
> >
> >
> > 2) Next option: your CachedOutputStream stuff..... This actually
> > will work, but you need to modify things a bit. First off, it needs
> > to be split into two interceptors: (usually, it's one
> > interceptor.java that then has an inner class for the other. See
> > the AttachmentOutInterceptor for example)
> > a) First/Outer one will replace the OutputStream with the cached
> > output stream and record the original stream. It will also then
> > add the second one to the chain. Make sure it's stuck before the
> > attachement stuff:
> > super(Phase.PRE_STREAM);
> > addBefore(AttachmentOutInterceptor.class.getName());
> >
> > b) The second/inner interceptor would grab the Cached stream, do
> > the transformation, and flush back to original stream. It would
> > be: super(Phase.PRE_STREAM_ENDING);
> > addAfter(AttachmentOutInterceptor.AttachmentOutEndingInterceptor
> > .class.getName());
> >
> > Dan
> >
> > On Thursday 20 March 2008, Yuval Zou wrote:
> >> Hi,
> >>
> >> Recently, I'm working on a web services client using CXF. But some
> >> request messages can't be parsed by the web services server. I
> >> found the problem is related to the namespace and prefix.
> >> The correct message:
> >> <?xml version="1.0" encoding="UTF-8"?>
> >> <CreateItemRequest
> >> xmlns="http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema">
> >> <AuthenticationData>
> >> <ServerDef>
> >> <ServerName>icmnlsdb</ServerName>
> >> </ServerDef>
> >> <LoginData>
> >> <UserID>icmadmin</UserID>
> >> <Password>********</Password>
> >> </LoginData>
> >> </AuthenticationData>
> >> <Item>
> >> <ItemXML>
> >> <CLAIM_1047 DATE_1047="2004-01-27" CLAIMNO_1047="1234"
> >> DESC_1047="This is a claim regarding the accident.3">
> >> <properties
> >> xmlns="http://www.ibm.com/xmlns/db2/cm/api/1.0/schema"
> >> type="document"/>
> >> <VEHICLE_1047 VIN_1047="38">
> >> <OWNER_1047 FNAME_1047="Ben" LNAME_1047="Dover"/>
> >> <OWNER_1047 FNAME_1047="Eileen" LNAME_1047="Dover"/>
> >> </VEHICLE_1047>
> >> <VEHICLE_1047 VIN_1047="34">
> >> <OWNER_1047 FNAME_1047="I.P." LNAME_1047="Freely"/>
> >> </VEHICLE_1047>
> >> <ICMBASE>
> >> <resourceObject
> >> xmlns="http://www.ibm.com/xmlns/db2/cm/api/1.0/schema"
> >> MIMEType="image/tiff">
> >> <label name="base 1"/>
> >> </resourceObject>
> >> </ICMBASE>
> >> </CLAIM_1047>
> >> </ItemXML>
> >> </Item>
> >> </CreateItemRequest>
> >> The namespace http://www.ibm.com/xmlns/db2/cm/api/1.0/schema was
> >> put in the element that needs it in this correct message.
> >>
> >> The mesage can't be parsed by server (sent by CXF):
> >> <?xml version="1.0" encoding="UTF-8"?>
> >> <CreateItemRequest
> >> xmlns:ns2="http://www.ibm.com/xmlns/db2/cm/api/1.0/schema"
> >> xmlns="http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema">
> >> <AuthenticationData>
> >> <ServerDef>
> >> <ServerName>icmnlsdb</ServerName>
> >> </ServerDef>
> >> <LoginData>
> >> <UserID>icmadmin</UserID>
> >> <Password>********</Password>
> >> </LoginData>
> >> </AuthenticationData>
> >> <Item>
> >> <ItemXML>
> >> <CLAIM_1047 DESC_1047="This is a claim regarding the accident.3"
> >> CLAIMNO_1047="1234" DATE_1047="2004-01-27">
> >> <ns2:properties type="document"/>
> >> <VEHICLE_1047 VIN_1047="38">
> >> <OWNER_1047 LNAME_1047="Dover" FNAME_1047="Ben"/>
> >> <OWNER_1047 LNAME_1047="Dover" FNAME_1047="Eileen"/>
> >> </VEHICLE_1047>
> >> <VEHICLE_1047 VIN_1047="34">
> >> <OWNER_1047 LNAME_1047="Freely" FNAME_1047="I.P."/>
> >> </VEHICLE_1047>
> >> <ICMBASE>
> >> <ns2:resourceObject MIMEType="image/tiff">
> >> <ns2:label name="base 1"/>
> >> </ns2:resourceObject>
> >> </ICMBASE>
> >> </CLAIM_1047>
> >> </ItemXML>
> >> </Item>
> >> </CreateItemRequest>
> >>
> >> The namespace http://www.ibm.com/xmlns/db2/cm/api/1.0/schema was
> >> put in the root element.
> >>
> >> Is there anyone who knows how to configure CXF to generate the XML
> >> message in accordance with the first style? Or is there possible to
> >> manually modify the generated message using out Interceptor?
> >> Actually, I have tried to use interceptor the modify the output
> >> stream: public StreamInterceptor() {
> >> super(Phase.PRE_STREAM);
> >> addBefore(SoapPreProtocolOutInterceptor.class.getName());
> >> }
> >>
> >> public void handleMessage(Message message) {
> >> OutputStream os = message.getContent(OutputStream.class);
> >> CachedStream cs = new CachedStream();
> >> message.setContent(OutputStream.class, cs);
> >>
> >> message.getInterceptorChain().doIntercept(message);
> >>
> >> try {
> >> cs.flush();
> >> CachedOutputStream csnew = (CachedOutputStream)
> >> message.getContent(OutputStream.class);
> >> // FileOutputStream fileOut = new
> >> FileOutputStream("D:\\test.txt");
> >> // CachedOutputStream.copyStream(csnew.getInputStream(),
> >> fileOut, 1024);
> >>
> >> StringBuilder sb = new StringBuilder();
> >> csnew.writeCacheTo(sb);
> >>
> >> String tmpXML = sb.toString();
> >> System.out.println("#####OLD####" + tmpXML);
> >> while (tmpXML.indexOf("<ns2:")!=-1){
> >> String subTmp =
> >> tmpXML.substring(tmpXML.indexOf("<ns2:")); subTmp =
> >> subTmp.substring(1, subTmp.indexOf(" ")); tmpXML =
> >> tmpXML.replaceAll(subTmp, subTmp.substring(4) + " " +
> >> "xmlns=\"http://www.ibm.com/xmlns/db2/cm/api/1.0/schema\<http://www
> >>.ib m.com/xmlns/db2/cm/api/1.0/schema/>" ");
> >> System.out.println("#####FIXED#######" + tmpXML);
> >> }
> >>
> >> InputStream in = new
> >> ByteArrayInputStream(tmpXML.getBytes());
> >>
> >> BufferedOutputStream bos = new
> >> BufferedOutputStream(os); CachedOutputStream.copyStream(in, bos,
> >> 1024);
> >>
> >> cs.close();
> >> in.close();
> >> // fileOut.close();
> >> bos.close();
> >> os.flush();
> >>
> >> message.setContent(OutputStream.class, os);
> >> } catch (IOException ioe) {
> >> ioe.printStackTrace();
> >> }
> >> }
> >>
> >> But the above code can't handle the message stream with MTOM
> >> attachements. It can't get the OutputStream at all. I don't know
> >> the reason.
> >>
> >> Your help will be really appreciated. Thanks in advance!
> >> Yuval Zou
> >
> > --
> > J. Daniel Kulp
> > Principal Engineer, IONA
> > [EMAIL PROTECTED]
> > http://www.dankulp.com/blog
--
J. Daniel Kulp
Principal Engineer, IONA
[EMAIL PROTECTED]
http://www.dankulp.com/blog