Hi all, (not sure if this belongs in cxf-dev or cxf-user; given the level of code detail here though, I'm thinking cxf-dev but feel free to redirect if appropriate)
I'm looking to get some advice on how to fix a WebApplicationException / IllegalStateException inside CXF's JSON code. I've got a solution in mind for the CXF code but I'm not an expert in JSON so I'm wondering if my code is incorrect or if this is truely a bug in CXF? In my scenario, CXF is generating the following exception: WARNING: WebApplicationException has been caught : Invalid JSON namespace: http://www.w3.org/2001/XMLSchema-instance even when I have JSONProvider.setIgnoreNamespaces to be true. The XML output is fine: <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Library xmlns:ns2="http://example.com/2011/book"> <Book> <ns2:Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/> </Book> </Library> However, the JSON output fails with HTTP 500 due to the above WebApplicationException. Looking at the source code, I can see that it's failing in IgnoreContentJettisonWriter: public void writeAttribute(String prefix, String uri, String local, String value) throws XMLStreamException { if (!writeXsiType && "type".equals(local) && "xsi".equals(prefix)) { return; } super.writeAttribute(prefix, uri, local, value); } At the time of invocation for IgnoreContentJettisonWriter.writeAttribute, we have the following values: prefix = xsi uri = http://www.w3.org/2001/XMLSchema-instance local = nil value = true writeXsiType = false Given these values, we still call super.writeAttribute which then consequently bombs with the IllegalStateException. To me, the naive solution in this scenario would be the following: If writeXsiType is set to false and local != "type", super.writeAttribute should be called with a null value for uri. With this change, the JSON output looks like the following: {"Library": {"Book": {"Book": {"@nil":"true"} } } } What are your thoughts? Would there be any issues with reading this JSON? Regards, kl Appendix A: JAXB Classes @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = {"book"}) @XmlRootElement(name = "Library") public class Library { @XmlElement(name = "Book", required = true) protected List<Book> book; public List<Book> getBook() { if (this.book == null) { this.book = new ArrayList<Book>(); } return this.book; } public void setBook(List<Book> l) { this.book = l; } } @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name="Book", propOrder={"book"}) public class Book { @XmlElement(name="Book", namespace="http://example.com/2011/book", required=true, nillable=true) protected String book; public String getBook() { return this.book; } public void setBook(String value) { this.book = value; } } Appendix B: Invocation Example @GET @Path("book") public Library getBook() throws JAXBException { final Book john = new Book(); john.setBook(null); Library lib = new Library(); List<Book> l = new ArrayList<Book>(1); l.add(john); docs.setBook(l); return lib; }
