Re: How to change the namespace position in the generate xml message (SOAP message)?
Hi Ian, I have tried your solution but it seems not work as expected. I'm a beginner of CXF and I'm not sure my implementation is correct. Could you please take a look at it? 1. I created cxf.xml on the client side: beans xmlns=http://www.springframework.org/schema/beans; xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; xmlns:jaxws=http://cxf.apache.org/jaxws; xmlns:soap=http://cxf.apache.org/bindings/soap; xsi:schemaLocation= http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd; jaxws:client id=cmwebserviceClient serviceClass=cm.webservices.CMWebServicePortType address=http://localhost/CMBSpecificWebService/services/CMWebService; jaxws:dataBinding bean class=org.apache.cxf.jaxb.JAXBDataBinding property name=marshallerProperties map entry key=com.sun.xml.bind.namespacePrefixMapper bean class=common.webservices.NoNamespacePrefixMapper / /entry /map /property property name=namespaceMap map entry key=http://www.ibm.com/xmlns/db2/cm/api/1.0/schema; valuecm/value /entry entry key=http://www.ibm.com/xmlns/db2/cm/beans/1.0/schema; valuecmb/value /entry /map /property /bean /jaxws:dataBinding /jaxws:client /beans property name=namespaceMap is insignificant. If it is removed, the result is same. 2. Implemented the NoNamespacePrefixMapper: public class NoNamespacePrefixMapper extends com.sun.xml.bind.marshaller.NamespacePrefixMapper { @Override public String getPreferredPrefix(String arg0, String arg1, boolean arg2) { return ; } } 3. Get service: ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[]{cxf.xml}); return (CMWebServicePortType)context.getBean(cmwebserviceClient); 4. Invoke the service operation. The xml message is still as before. Is there anything wrong in these steps? Thanks! ianroberts wrote: 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; [snip] /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; [snip] /CreateItemRequest The namespace http://www.ibm.com/xmlns/db2/cm/api/1.0/schema was put in the root element. In XML terms the two messages are exactly the same, so it's more the fault of whatever is parsing the message on the server side rather than of the XML generator in CXF. Nontheless... If you're using JAXB databinding then you may be able to do what you want using a custom namespace prefix mapper in the data binding. Something like this (not tested but you get the idea): jaxws:client ... jaxws:dataBinding bean class=org.apache.cxf.jaxb.JAXBDataBinding property name=marshallerProperties map entry key=com.sun.xml.bind.namespacePrefixMapper bean class=my.package.NoPrefixNamespaceMapper / /entry /map /property /bean /jaxws:dataBinding /jaxws:client Where NoPrefixNamespaceMapper is an implementation of com.sun.xml.bind.marshaller.NamespacePrefixMapper whose getPreferredPrefix method always returns . This should force the marshaller to only use prefixes when it absolutely has to. Ian -- Ian Roberts | Department of Computer Science [EMAIL PROTECTED] | University of Sheffield, UK -- View this message in context: http://www.nabble.com/How-to-change-the-namespace-position-in-the-generate-xml-message-%28SOAP-message%29--tp16176819p16194418.html Sent from the cxf-user mailing list archive at Nabble.com.
Re: How to change the namespace position in the generate xml message (SOAP message)?
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! 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_OPTIMIZATION, 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
Re: How to change the namespace position in the generate xml message (SOAP message)?
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
How to change the namespace position in the generate xml message (SOAP message)?
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 ServerNameicmnlsdb/ServerName /ServerDef LoginData UserIDicmadmin/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 ServerNameicmnlsdb/ServerName /ServerDef LoginData UserIDicmadmin/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.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); 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
Re: How to change the namespace position in the generate xml message (SOAP message)?
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; [snip] /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; [snip] /CreateItemRequest The namespace http://www.ibm.com/xmlns/db2/cm/api/1.0/schema was put in the root element. In XML terms the two messages are exactly the same, so it's more the fault of whatever is parsing the message on the server side rather than of the XML generator in CXF. Nontheless... If you're using JAXB databinding then you may be able to do what you want using a custom namespace prefix mapper in the data binding. Something like this (not tested but you get the idea): jaxws:client ... jaxws:dataBinding bean class=org.apache.cxf.jaxb.JAXBDataBinding property name=marshallerProperties map entry key=com.sun.xml.bind.namespacePrefixMapper bean class=my.package.NoPrefixNamespaceMapper / /entry /map /property /bean /jaxws:dataBinding /jaxws:client Where NoPrefixNamespaceMapper is an implementation of com.sun.xml.bind.marshaller.NamespacePrefixMapper whose getPreferredPrefix method always returns . This should force the marshaller to only use prefixes when it absolutely has to. Ian -- Ian Roberts | Department of Computer Science [EMAIL PROTECTED] | University of Sheffield, UK
Re: How to change the namespace position in the generate xml message (SOAP message)?
The CXF JAXB binding has a custom namespace mapper which can be told to control the prefixes. You can override it for further control. However, I'm very skeptical as to the idea modifying where the prefixes are defined. You might need to just make an interceptor that rewrites the XML. On Thu, Mar 20, 2008 at 8:20 AM, Ian Roberts [EMAIL PROTECTED] wrote: 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; [snip] /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; [snip] /CreateItemRequest The namespace http://www.ibm.com/xmlns/db2/cm/api/1.0/schema was put in the root element. In XML terms the two messages are exactly the same, so it's more the fault of whatever is parsing the message on the server side rather than of the XML generator in CXF. Nontheless... If you're using JAXB databinding then you may be able to do what you want using a custom namespace prefix mapper in the data binding. Something like this (not tested but you get the idea): jaxws:client ... jaxws:dataBinding bean class=org.apache.cxf.jaxb.JAXBDataBinding property name=marshallerProperties map entry key=com.sun.xml.bind.namespacePrefixMapper bean class=my.package.NoPrefixNamespaceMapper / /entry /map /property /bean /jaxws:dataBinding /jaxws:client Where NoPrefixNamespaceMapper is an implementation of com.sun.xml.bind.marshaller.NamespacePrefixMapper whose getPreferredPrefix method always returns . This should force the marshaller to only use prefixes when it absolutely has to. Ian -- Ian Roberts | Department of Computer Science [EMAIL PROTECTED] | University of Sheffield, UK
Re: How to change the namespace position in the generate xml message (SOAP message)?
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_OPTIMIZATION, 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 ServerNameicmnlsdb/ServerName /ServerDef LoginData UserIDicmadmin/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 ServerNameicmnlsdb/ServerName /ServerDef LoginData UserIDicmadmin/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();
Re: How to change the namespace position in the generate xml message (SOAP message)?
Hi Dan, Thanks a lot for your quick and detailed response! I will try the options provided by you. Hope everything goes well~~ :) Yuval 2008/3/20, Daniel Kulp [EMAIL PROTECTED]: 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_OPTIMIZATION, 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 ServerNameicmnlsdb/ServerName /ServerDef LoginData UserIDicmadmin/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 ServerNameicmnlsdb/ServerName /ServerDef LoginData UserIDicmadmin/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