CXF jaxb send string as CData

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

CXF jaxb send string as CData

idar
Hi

I am calling a webservice outside of my control. I am being told that
i need to send html tags as Cdata and not > tags for some reason.
Is it possible to force jaxb in cxf to encode a string in CDATA?

--
Idar
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

Sergey Beryozkin
Administrator
Hi
On 29/02/12 09:52, Idar Borlaug wrote:
> Hi
>
> I am calling a webservice outside of my control. I am being told that
> i need to send html tags as Cdata and not> tags for some reason.
> Is it possible to force jaxb in cxf to encode a string in CDATA?
>
I looked at some available recommendations on the web but it appears
the simplest and the most flexible solution is to register a custom
XMLStreamWriter which will delegate to the default CXF utility writer
and only override a couple of methods dealing with writing the
characters, and optionally check the current element name if its content
should not be wrapped, example:

private static class CDataContentWriter extends DelegatingXMLStreamWriter {

         private String currentElementName;

         public CDataContentWriter(XMLStreamWriter writer) {
             super(writer);
         }


         public void writeCharacters(String text) throws
XMLStreamException {
               boolean useCData = checkIfCDATAneededForCurrentElement();
               if (useCData) {
                   super.writeCharacters("<[![CDATA[");
               }
               super.write(text);
               if (useCData) {
                   super.writeCharacters("]]");
               }
         }

         // optional
         public void writeStartElement(String prefix, String local,
String uri) throws XMLStreamException {
             currentElementName = local;
             super.writeStartElement(prefix, local, uri);
         }
}

then from the interceptor or a filer do

XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(outputStream);
message.setContent(XMLStreamWriter.class, new CDataContentWriter(writer));

That should do

Sergey
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

Sergey Beryozkin
Administrator
I forgot XNLStreamWriter has CDATA specific methods so those would have
to be used instead which makes things even simpler
On 29/02/12 11:16, Sergey Beryozkin wrote:

> Hi
> On 29/02/12 09:52, Idar Borlaug wrote:
>> Hi
>>
>> I am calling a webservice outside of my control. I am being told that
>> i need to send html tags as Cdata and not&gt; tags for some reason.
>> Is it possible to force jaxb in cxf to encode a string in CDATA?
>>
> I looked at some available recommendations on the web but it appears the
> simplest and the most flexible solution is to register a custom
> XMLStreamWriter which will delegate to the default CXF utility writer
> and only override a couple of methods dealing with writing the
> characters, and optionally check the current element name if its content
> should not be wrapped, example:
>
> private static class CDataContentWriter extends DelegatingXMLStreamWriter {
>
> private String currentElementName;
>
> public CDataContentWriter(XMLStreamWriter writer) {
> super(writer);
> }
>
>
> public void writeCharacters(String text) throws XMLStreamException {
> boolean useCData = checkIfCDATAneededForCurrentElement();
> if (useCData) {
> super.writeCharacters("<[![CDATA[");
> }
> super.write(text);
> if (useCData) {
> super.writeCharacters("]]");
> }
> }
>
> // optional
> public void writeStartElement(String prefix, String local, String uri)
> throws XMLStreamException {
> currentElementName = local;
> super.writeStartElement(prefix, local, uri);
> }
> }
>
> then from the interceptor or a filer do
>
> XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(outputStream);
> message.setContent(XMLStreamWriter.class, new CDataContentWriter(writer));
>
> That should do
>
> Sergey


--
Sergey Beryozkin

Talend Community Coders
http://coders.talend.com/

Blog: http://sberyozkin.blogspot.com
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

idar
On 29 February 2012 12:19, Sergey Beryozkin <[hidden email]> wrote:
> I forgot XNLStreamWriter has CDATA specific methods so those would have to

Thanks, i will look into this, though this seems like a lot of work
for a buggy webservice :)

--
Idar
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

idar
Ok i am now trying to create an interceptor that captures element name
and prints CDATA in the correct element.

The problem is my code intercept everyting until soap:body tag, then it stops.

I probably have it injected the wrong way in the cxf interceptro
chain. Can anyone point me in the right direction. the output is now:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><![CDATA[]]><Insert

public class CDataXMLStreamWriter extends DelegatingXMLStreamWriter {

        private String currentElementName;

        public CDataXMLStreamWriter(XMLStreamWriter del) {
                super(del);
        }

        @Override
        public void writeCharacters(String text) throws XMLStreamException {
                boolean useCData = checkIfCDATAneededForCurrentElement();
                if (useCData) {
                        System.out.println("WritingCData" + text);
                        super.writeCData(text);
                }else {
                super.writeCharacters(text);
                }
        }

        private boolean checkIfCDATAneededForCurrentElement() {
                System.out.println("ElementName " + currentElementName);
                return true;
        }

        public void writeStartElement(String prefix, String local, String
uri) throws XMLStreamException {
                currentElementName = local;
                super.writeStartElement(prefix, local, uri);
        }
}

public class CdataWriterInterceptor extends AbstractPhaseInterceptor<Message> {

        public CdataWriterInterceptor() {
                super(Phase.WRITE);
                addBefore(BareOutInterceptor.class.getName());
        }

        @Override
        public void handleMessage(Message message) {
                System.out.println("setting altinnfix on message");
                XMLStreamWriter writer =
StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class));
                message.setContent(XMLStreamWriter.class, new CDataXMLStreamWriter(writer));
        }
}

--
Idar
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

Daniel  Kulp
Administrator
 

Add a line:

message.put("disable.outputstream.optimization", Boolean.TRUE);

into the handleMessage method of your interceptor.  That likely will fix that.


Dan


On Thursday, March 01, 2012 1:42:00 PM Idar Borlaug wrote:

> Ok i am now trying to create an interceptor that captures element name
> and prints CDATA in the correct element.
>
> The problem is my code intercept everyting until soap:body tag, then it
> stops.
>
> I probably have it injected the wrong way in the cxf interceptro
> chain. Can anyone point me in the right direction. the output is now:
> <soap:Envelope
> xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><![CDATA[
> ]]><Insert
>
> public class CDataXMLStreamWriter extends DelegatingXMLStreamWriter {
>
> private String currentElementName;
>
> public CDataXMLStreamWriter(XMLStreamWriter del) {
> super(del);
> }
>
> @Override
> public void writeCharacters(String text) throws XMLStreamException {
> boolean useCData = checkIfCDATAneededForCurrentElement();
> if (useCData) {
> System.out.println("WritingCData" + text);
> super.writeCData(text);
> }else {
> super.writeCharacters(text);
> }
> }
>
> private boolean checkIfCDATAneededForCurrentElement() {
> System.out.println("ElementName " + currentElementName);
> return true;
> }
>
> public void writeStartElement(String prefix, String local, String
> uri) throws XMLStreamException {
> currentElementName = local;
> super.writeStartElement(prefix, local, uri);
> }
> }
>
> public class CdataWriterInterceptor extends
> AbstractPhaseInterceptor<Message> {
>
> public CdataWriterInterceptor() {
> super(Phase.WRITE);
> addBefore(BareOutInterceptor.class.getName());
> }
>
> @Override
> public void handleMessage(Message message) {
> System.out.println("setting altinnfix on message");
> XMLStreamWriter writer =
> StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class));
> message.setContent(XMLStreamWriter.class, new
> CDataXMLStreamWriter(writer)); }
> }
--
Daniel Kulp
[hidden email] - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

idar
Thanks for all the help. I got it working. Here is the solution:

public class CdataWriterInterceptor extends AbstractPhaseInterceptor<Message> {

        public CdataWriterInterceptor() {
                super(Phase.PRE_STREAM);
                addAfter(AttachmentOutInterceptor.class.getName());
        }

        @Override
        public void handleMessage(Message message) {
                message.put("disable.outputstream.optimization", Boolean.TRUE);
                XMLStreamWriter writer =
StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class));
                message.setContent(XMLStreamWriter.class, new CDataXMLStreamWriter(writer));
        }
}

public class CDataXMLStreamWriter extends DelegatingXMLStreamWriter {

        private String currentElementName;

        public CDataXMLStreamWriter(XMLStreamWriter del) {
                super(del);
        }

        @Override
        public void writeCharacters(String text) throws XMLStreamException {
                boolean useCData = checkIfCDATAneededForCurrentElement();
                if (useCData) {
                        System.out.println("WritingCData" + text);
                        super.writeCData(text);
                }else {
                super.writeCharacters(text);
                }
        }

        private boolean checkIfCDATAneededForCurrentElement() {
                if("MessageBody".equals(currentElementName)) return true;
                return false;
        }

        public void writeStartElement(String prefix, String local, String
uri) throws XMLStreamException {
                currentElementName = local;
                super.writeStartElement(prefix, local, uri);
        }
}

On 1 March 2012 23:19, Daniel Kulp <[hidden email]> wrote:

>
>
> Add a line:
>
> message.put("disable.outputstream.optimization", Boolean.TRUE);
>
> into the handleMessage method of your interceptor.  That likely will fix that.
>
>
> Dan
>
>
> On Thursday, March 01, 2012 1:42:00 PM Idar Borlaug wrote:
>> Ok i am now trying to create an interceptor that captures element name
>> and prints CDATA in the correct element.
>>
>> The problem is my code intercept everyting until soap:body tag, then it
>> stops.
>>
>> I probably have it injected the wrong way in the cxf interceptro
>> chain. Can anyone point me in the right direction. the output is now:
>> <soap:Envelope
>> xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><![CDATA[
>> ]]><Insert
>>
>> public class CDataXMLStreamWriter extends DelegatingXMLStreamWriter {
>>
>>       private String currentElementName;
>>
>>       public CDataXMLStreamWriter(XMLStreamWriter del) {
>>               super(del);
>>       }
>>
>>       @Override
>>       public void writeCharacters(String text) throws XMLStreamException {
>>               boolean useCData = checkIfCDATAneededForCurrentElement();
>>               if (useCData) {
>>                       System.out.println("WritingCData" + text);
>>                       super.writeCData(text);
>>               }else {
>>               super.writeCharacters(text);
>>               }
>>       }
>>
>>       private boolean checkIfCDATAneededForCurrentElement() {
>>               System.out.println("ElementName " + currentElementName);
>>               return true;
>>       }
>>
>>       public void writeStartElement(String prefix, String local, String
>> uri) throws XMLStreamException {
>>               currentElementName = local;
>>               super.writeStartElement(prefix, local, uri);
>>       }
>> }
>>
>> public class CdataWriterInterceptor extends
>> AbstractPhaseInterceptor<Message> {
>>
>>       public CdataWriterInterceptor() {
>>               super(Phase.WRITE);
>>               addBefore(BareOutInterceptor.class.getName());
>>       }
>>
>>       @Override
>>       public void handleMessage(Message message) {
>>               System.out.println("setting altinnfix on message");
>>               XMLStreamWriter writer =
>> StaxUtils.createXMLStreamWriter(message.getContent(OutputStream.class));
>>               message.setContent(XMLStreamWriter.class, new
>> CDataXMLStreamWriter(writer)); }
>> }
> --
> Daniel Kulp
> [hidden email] - http://dankulp.com/blog
> Talend Community Coder - http://coders.talend.com



--
Idar
Reply | Threaded
Open this post in threaded view
|

Re: CXF jaxb send string as CData

amardas
Hi,

I am into an issue which looks similar to what you had in past. I am writing a webserive method which looks like getScore(String text) returns a String. Here the input 'text' is a raw xml. When I run it throws the following error. Unmarshalling Error: unexpected element (uri:"", local:"HealthImpact"). Expected elements are (none). <HealthImpact> is the first element in the raw xml passed in the text. Looking at your issue looks like you have implemented an interceptor which I amunable to follow. Can you send more details on the code on how we handle this. Would appreciate your help.

Thanks in advance.
Amar