users@jersey.java.net

Re: [Jersey] entities encoding issues in the response

From: Arul Dhesiaseelan <arul_at_fluxcorp.com>
Date: Thu, 22 May 2008 08:50:36 -0600

Paul,

Thanks for your help.

I tried this approach, but I am not seeing the SOP made it to my
console. I suspect whether my custom stream writer is used at the first
place. Is there a way to tell Jersey/Java to use my custom writer
instead of the default writer?

I see this in the console, which tells that at least my message body
writer was loaded properly.

INFO: Provider classes found:
  class impl.rest.jaxb.CDATAProvider

Here is my MBW writer which uses the custom stream writer.

@ProduceMime("application/xml")
@Provider
public class CDATAProvider implements MessageBodyWriter<CellType> {

    public void writeTo(CellType cellType,
            Class<?> type, Type genericType, Annotation annotations[],
            MediaType mediaType, MultivaluedMap<String, Object> headers,
            OutputStream out) throws IOException {
      try {
        JAXBContext jc = JAXBContext.newInstance(CellType.class);
        Marshaller marshaller = jc.createMarshaller();
        XMLStreamWriter swImpl =
XMLOutputFactory.newInstance().createXMLStreamWriter(out);
        XMLStreamWriter sw = new MyStreamWriter(swImpl);
        marshaller.marshal(cellType, sw);
      } catch (XMLStreamException xse) {
        System.out.println(xse.getMessage());
      } catch (JAXBException je) {
        System.out.println(je.getMessage());
      }
    }

    public boolean isWriteable(Class<?> type, Type genericType,
Annotation annotations[]) {
        return CellType.class.isAssignableFrom(type);
    }

    public long getSize(CellType cellType) {
        return -1;
    }
}


Best regards,
Arul

Paul Sandoz wrote:
> As i understand it your use-case is you want to embed some generic
> HTML content in some XML.
>
> Can you try the following code instead:
>
> private Rows processRowsResponse() {
> List<RowType> rows = new ArrayList<RowType>();
> RowType row = new RowType();
> CellType cell = new CellType();
> final String cdata = new StringBuilder().append("<div
> class=\"progressOuterRow\"><div class=\"progressInnerRow\"
> style=\"width: ").append(result.toString()).append("px;\"></div><div
> class=\"progressText\">").append(used).append("/").append(total).append("
> MB</div></div>").toString();
> cell.setValue(cdata);
> row.getCell().add(cell);
> rows.add(row);
> return rows;
> }
>
> public class MyStreamWriter implements XMLStreamWriter {
> private XMLStreamWriter mImpl;
>
> public MyStreamWriter(XMLStreamWriter xmlStreamWriter) throws
> XMLStreamException {
> this.mImpl = xmlStreamWriter;
> }
>
> public void writeCharacters(String s) throws XMLStreamException {
> System.out.println("writeCharacters: " + s);
> mImpl.writeCData(s);
> }
>
> //removed other methods
> }
>
>
> and check the output to see if the "writeCharacters: " string is being
> printed and check if the content is escaped or not before the
> delegated call.
>
> Paul.
>
> Arul Dhesiaseelan wrote:
>> Tatu,
>>
>> I have the CDATA set in my resource class.
>>
>> @GET
>> @Path("/list")
>> @ProduceMime({"application/xml"})
>> public Response getRows() {
>> final Rows rows;
>> rows = processRowsResponse();
>> return Response.ok(rows).build();
>> }
>>
>> private Rows processRowsResponse() {
>> List<RowType> rows = new ArrayList<RowType>();
>> RowType row = new RowType();
>> CellType cell = new CellType();
>> final String cdata = new StringBuilder().append("<![CDATA[<div
>> class=\"progressOuterRow\"><div class=\"progressInnerRow\"
>> style=\"width: ").append(result.toString()).append("px;\"></div><div
>> class=\"progressText\">").append(used).append("/").append(total).append("
>> MB</div></div>]]>").toString();
>> cell.setValue(cdata);
>> row.getCell().add(cell);
>> rows.add(row);
>> return rows;
>> }
>>
>> I assume this CDATA will be sent as a string to the
>> XMLStreamWriter.writeCharacters() when the
>> MessageBodyWriter<CellType> is invoked.
>>
>> May be I missing something here?
>>
>> Thanks!
>> Arul
>>
>> Tatu Saloranta wrote:
>>> Code below looks correct, but where does that "CDATA"
>>> come into String? Is it just added for testing?
>>>
>>> What seems to be happening is that for some reason
>>> content you are getting is already xml-escaped (or is
>>> fed to another xml stream writer); like OutputStream
>>> or Writer passing its content back to xml writer.
>>>
>>> -+ Tatu +-
>>>
>>> --- Arul Dhesiaseelan <arul_at_fluxcorp.com> wrote:
>>>
>>>
>>>> Paul,
>>>>
>>>> Here is my custom Stream writer. I just delegate
>>>> writeCData to XMLStreamWriter. I will try with a standalone test.
>>>>
>>>> public class MyStreamWriter implements
>>>> XMLStreamWriter {
>>>> private XMLStreamWriter mImpl;
>>>>
>>>> public MyStreamWriter(XMLStreamWriter
>>>> xmlStreamWriter) throws XMLStreamException {
>>>> this.mImpl = xmlStreamWriter;
>>>> }
>>>>
>>>> public void writeCData(String s) throws
>>>> XMLStreamException {
>>>> mImpl.writeCData(s);
>>>> }
>>>>
>>>> public void writeCharacters(String s) throws
>>>> XMLStreamException {
>>>> if (shouldUseCData(s)) {
>>>> System.out.println("Using CDATA");
>>>> mImpl.writeCData(s);
>>>> } else {
>>>> mImpl.writeCharacters(s);
>>>> }
>>>> }
>>>>
>>>> private boolean shouldUseCData(String s) {
>>>> if (s.contains("CDATA")) {
>>>> return true;
>>>> } else return false;
>>>> }
>>>> //removed other methods
>>>> }
>>>>
>>>> Am I missing something here?
>>>>
>>>> Thanks!
>>>> Arul
>>>>
>>>>