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 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
>
>
--
View this message in context:
http://www.nabble.com/How-to-change-the-namespace-position-in-the-generate-xml-message-%28SOAP-message%29--tp16176819p16194931.html
Sent from the cxf-user mailing list archive at Nabble.com.