cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Kulp <dk...@apache.org>
Subject Re: How to change the namespace position in the generate xml message (SOAP message)?
Date Fri, 21 Mar 2008 08:33:46 GMT
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
> > dkulp@apache.org
> > http://www.dankulp.com/blog



-- 
J. Daniel Kulp
Principal Engineer, IONA
dkulp@apache.org
http://www.dankulp.com/blog

Mime
View raw message