You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Joe Sunday <su...@csh.rit.edu> on 2008/06/17 20:32:47 UTC

REST + JSON + Namespaces

Sorry if this is obvious, but I can't find an answer. Spring 2.5, CXF  
2.1, Jettison 1.0.1.

I've got a SOAP and a REST service both being configured in Spring..  
REST works for XML, but I get an "Invalid JSON namespace" error if I  
try to use JSON. I've tried to inject the correct Jettison mapping,  
which doesn't seem to work. HOWEVER, it does seem to be doing the  
right thing with the "cxf" namespace on error.

Spring config:

     <util:map id="jsonNamespaceMap" map-class="java.util.Hashtable">
         <entry key="http://www.acme.com/test" value="t"/>
         <entry key="http://cxf.apache.org/bindings/xformat"  
value="cxf"/>
     </util:map>

     <bean id="jsonInputFactory"
         class="org.codehaus.jettison.mapped.MappedXMLInputFactory">
         <constructor-arg ref="jsonNamespaceMap"/>
     </bean>

     <bean id="jsonOutputFactory"
         class="org.codehaus.jettison.mapped.MappedXMLOutputFactory">
         <constructor-arg ref="jsonNamespaceMap"/>
     </bean>

     <jaxrs:server id="systemEndpoint" address="/system">
         <jaxrs:serviceBeans>
             <ref bean="systemImpl"/>
         </jaxrs:serviceBeans>
         <jaxrs:properties>
             <entry key="javax.xml.stream.XMLInputFactory">
                 <ref bean="jsonInputFactory"/>
             </entry>
             <entry key="javax.xml.stream.XMLOutputFactory">
                 <ref bean="jsonOutputFactory"/>
             </entry>
         </jaxrs:properties>
     </jaxrs:server>

Return type;
@XmlRootElement(name = "JSONTest", namespace = "http://www.acme.com/ 
test")
@XmlType(name = "", propOrder = {"a", "b", "c"})
@XmlAccessorType(XmlAccessType.FIELD)
public class JSONTest {
     @XmlElement
     private String a;
     @XmlElement
     private String b;
     @XmlElement
     private String c;

REST impl:
     @GET
     @Path("/jupdate/")
     public JSONTest jupdates() {
         JSONTest b = new JSONTest("1", "2", "3");
         return b;
     }

$ curl -H "Accept: application/xml" http://localhost:8080/test/system/jupdate
<ns2:JSONTest xmlns:ns2="http://www.acme.com/test"><a>1</a><b>2</ 
b><c>3</c></ns2:JSONTest>

$ curl -H "Accept: application/json" http://localhost:8080/test/system/jupdate
{"cxf.XMLFault":{"cxf.faultstring":"java.lang.IllegalStateException:  
Invalid JSON namespace: http:\/\/www.acme.com\/test"}}

Log file:
java.lang.IllegalStateException: Invalid JSON namespace: http://www.acme.com/test
         at  
org 
.codehaus 
.jettison 
.mapped 
.MappedNamespaceConvention 
.getJSONNamespace(MappedNamespaceConvention.java:151)
         at  
org 
.codehaus 
.jettison 
.mapped 
.MappedNamespaceConvention.createKey(MappedNamespaceConvention.java:158)
         at  
org 
.codehaus 
.jettison 
.mapped 
.MappedXMLStreamWriter.writeStartElement(MappedXMLStreamWriter.java:241)
         at  
com 
.sun 
.xml 
.bind 
.v2 
.runtime 
.output.XMLStreamWriterOutput.beginStartTag(XMLStreamWriterOutput.java: 
113)
...

If I remove the namespace declaration from JSONTest, I get a valid  
answer, but the types on the wire are really JAXB generated and I want  
namespaces on them for the XML domain:

$ curl -H "Accept: application/json" http://localhost:8080/test/system/jupdate
{"JSONTest":{"a":1,"b":2,"c":3}}

--Joe


Re: REST + JSON + Namespaces

Posted by Joe Sunday <su...@csh.rit.edu>.
Thanks for the hints. I added a setNamespaceMap(Map<String, String>)  
setter to JSONProvider and set that with the map I had in spring, then  
set that provider bean via jaxrs:entityProviders. I actually prefer  
that, it's cleaner than creating the input and output factories like I  
was attempting.

Is there an open JIRA for this or should I open one?

--Joe

On Jun 18, 2008, at 12:03 PM, Sergey Beryozkin wrote:

> Ok, sure, that can be fixed.
>
> In meantime, the simplest workaround is to copy and paste the  
> existing JSONProvider, update it to pass the correct properties to  
> the constructor, or possibly have the factory bean injected through  
> spring, and then register the custom provider through  
> jaxrs:providers, and it will be checked first...
>
> JAX-RS ContextResolvers will also be supported soon.
>
> Cheers, Sergey
>
>
>>
>> On Jun 18, 2008, at 11:35 AM, Sergey Beryozkin wrote:
>>> Just would like to clarify :
>>>
>>> Do you expect that the bean with id 'jsonOutputFactory' is to be   
>>> used as a org.codehaus.jettison.mapped.MappedXMLOutputFactory  
>>> instance ?
>>>
>>> At the moment, no jaxrs:properties are checked. But that can be   
>>> fixed...
>>>
>>> Cheers, Sergey
>>>
>>
>> Yes.. I want my service to do JSON, but it doesn't work unless I  
>> can  configure jettison first with the namespace prefixes I need,  
>> and I  can't figure out how to inject that map via Spring anywhere.
>>
>> I see a couple examples on the web how to do it programatically,  
>> but  not how to do it in my spring container.
>>
>> --Joe
>
> ----------------------------
> IONA Technologies PLC (registered in Ireland)
> Registered Number: 171387
> Registered Address: The IONA Building, Shelbourne Road, Dublin 4,  
> Ireland


Re: REST + JSON + Namespaces

Posted by Joe Sunday <su...@csh.rit.edu>.
I've opened up JIRA CXF-1671 and attached a patch against 2.1.. I will  
generate a true SVN diff patch against the 2.1 trunk if you need it,  
but it'll take me a little bit to update my current project to 2.1.1  
first.

--Joe

On Jun 26, 2008, at 12:23 PM, Sergey Beryozkin wrote:

> Hi
>
> Thanks for trying these suggestions. Are you thinking of applying  
> the changes you've referred to
> the existing JSONProvider ? That's are you explicitly configuring  
> the existing JSONProvider in Spring ?
> Thats' probably a good idea - that way people can just reuse the  
> existing provider rather than creating a duplicate...
> Please create a JIRA and attach your patch.
>
> Cheers, Sergey
>
> ----- Original Message ----- From: "Sergey Beryozkin" <sergey.beryozkin@iona.com 
> >
> To: <us...@cxf.apache.org>
> Sent: Wednesday, June 18, 2008 5:03 PM
> Subject: Re: REST + JSON + Namespaces
>
>
> Ok, sure, that can be fixed.
>
> In meantime, the simplest workaround is to copy and paste the  
> existing JSONProvider, update it to pass the correct properties to the
> constructor, or possibly have the factory bean injected through  
> spring, and then register the custom provider through
> jaxrs:providers, and it will be checked first...
>
> JAX-RS ContextResolvers will also be supported soon.
>
> Cheers, Sergey
>
>
>>
>> On Jun 18, 2008, at 11:35 AM, Sergey Beryozkin wrote:
>>> Just would like to clarify :
>>>
>>> Do you expect that the bean with id 'jsonOutputFactory' is to be   
>>> used as a org.codehaus.jettison.mapped.MappedXMLOutputFactory  
>>> instance ?
>>>
>>> At the moment, no jaxrs:properties are checked. But that can be   
>>> fixed...
>>>
>>> Cheers, Sergey
>>>
>>
>> Yes.. I want my service to do JSON, but it doesn't work unless I  
>> can  configure jettison first with the namespace prefixes I need,  
>> and I  can't figure out how to inject that map via Spring anywhere.
>>
>> I see a couple examples on the web how to do it programatically,  
>> but  not how to do it in my spring container.
>>
>> --Joe
>
> ----------------------------
> IONA Technologies PLC (registered in Ireland)
> Registered Number: 171387
> Registered Address: The IONA Building, Shelbourne Road, Dublin 4,  
> Ireland
> ----------------------------
> IONA Technologies PLC (registered in Ireland)
> Registered Number: 171387
> Registered Address: The IONA Building, Shelbourne Road, Dublin 4,  
> Ireland


Re: REST + JSON + Namespaces

Posted by Sergey Beryozkin <se...@iona.com>.
Hi

Thanks for trying these suggestions. Are you thinking of applying the changes you've referred to
the existing JSONProvider ? That's are you explicitly configuring the existing JSONProvider in Spring ?
Thats' probably a good idea - that way people can just reuse the existing provider rather than creating a duplicate...
Please create a JIRA and attach your patch.

Cheers, Sergey

----- Original Message ----- 
From: "Sergey Beryozkin" <se...@iona.com>
To: <us...@cxf.apache.org>
Sent: Wednesday, June 18, 2008 5:03 PM
Subject: Re: REST + JSON + Namespaces


Ok, sure, that can be fixed.

In meantime, the simplest workaround is to copy and paste the existing JSONProvider, update it to pass the correct properties to the
constructor, or possibly have the factory bean injected through spring, and then register the custom provider through
jaxrs:providers, and it will be checked first...

JAX-RS ContextResolvers will also be supported soon.

Cheers, Sergey


>
> On Jun 18, 2008, at 11:35 AM, Sergey Beryozkin wrote:
>> Just would like to clarify :
>>
>> Do you expect that the bean with id 'jsonOutputFactory' is to be  used as a org.codehaus.jettison.mapped.MappedXMLOutputFactory 
>> instance ?
>>
>> At the moment, no jaxrs:properties are checked. But that can be  fixed...
>>
>> Cheers, Sergey
>>
>
> Yes.. I want my service to do JSON, but it doesn't work unless I can  configure jettison first with the namespace prefixes I need, 
> and I  can't figure out how to inject that map via Spring anywhere.
>
> I see a couple examples on the web how to do it programatically, but  not how to do it in my spring container.
>
> --Joe

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland 

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland

Re: REST + JSON + Namespaces

Posted by Sergey Beryozkin <se...@iona.com>.
Ok, sure, that can be fixed.

In meantime, the simplest workaround is to copy and paste the existing JSONProvider, update it to pass the correct properties to the 
constructor, or possibly have the factory bean injected through spring, and then register the custom provider through 
jaxrs:providers, and it will be checked first...

JAX-RS ContextResolvers will also be supported soon.

Cheers, Sergey


>
> On Jun 18, 2008, at 11:35 AM, Sergey Beryozkin wrote:
>> Just would like to clarify :
>>
>> Do you expect that the bean with id 'jsonOutputFactory' is to be  used as a org.codehaus.jettison.mapped.MappedXMLOutputFactory 
>> instance ?
>>
>> At the moment, no jaxrs:properties are checked. But that can be  fixed...
>>
>> Cheers, Sergey
>>
>
> Yes.. I want my service to do JSON, but it doesn't work unless I can  configure jettison first with the namespace prefixes I need, 
> and I  can't figure out how to inject that map via Spring anywhere.
>
> I see a couple examples on the web how to do it programatically, but  not how to do it in my spring container.
>
> --Joe 

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland

Re: REST + JSON + Namespaces

Posted by Joe Sunday <su...@csh.rit.edu>.
On Jun 18, 2008, at 11:35 AM, Sergey Beryozkin wrote:
> Just would like to clarify :
>
> Do you expect that the bean with id 'jsonOutputFactory' is to be  
> used as a org.codehaus.jettison.mapped.MappedXMLOutputFactory  
> instance ?
>
> At the moment, no jaxrs:properties are checked. But that can be  
> fixed...
>
> Cheers, Sergey
>

Yes.. I want my service to do JSON, but it doesn't work unless I can  
configure jettison first with the namespace prefixes I need, and I  
can't figure out how to inject that map via Spring anywhere.

I see a couple examples on the web how to do it programatically, but  
not how to do it in my spring container.

--Joe


Re: REST + JSON + Namespaces

Posted by Sergey Beryozkin <se...@iona.com>.
Hi

> Sorry if this is obvious, but I can't find an answer. Spring 2.5, CXF
> 2.1, Jettison 1.0.1.

It's ok, not obvious to me at all :-)

>
> I've got a SOAP and a REST service both being configured in Spring..
> REST works for XML, but I get an "Invalid JSON namespace" error if I
> try to use JSON. I've tried to inject the correct Jettison mapping,
> which doesn't seem to work. HOWEVER, it does seem to be doing the
> right thing with the "cxf" namespace on error.
>
> Spring config:
>
>     <util:map id="jsonNamespaceMap" map-class="java.util.Hashtable">
>         <entry key="http://www.acme.com/test" value="t"/>
>         <entry key="http://cxf.apache.org/bindings/xformat"
> value="cxf"/>
>     </util:map>
>
>     <bean id="jsonInputFactory"
>         class="org.codehaus.jettison.mapped.MappedXMLInputFactory">
>         <constructor-arg ref="jsonNamespaceMap"/>
>     </bean>
>
>     <bean id="jsonOutputFactory"
>         class="org.codehaus.jettison.mapped.MappedXMLOutputFactory">
>         <constructor-arg ref="jsonNamespaceMap"/>
>     </bean>

Just would like to clarify :

Do you expect that the bean with id 'jsonOutputFactory' is to be used as a org.codehaus.jettison.mapped.MappedXMLOutputFactory 
instance ?

At the moment, no jaxrs:properties are checked. But that can be fixed...

Cheers, Sergey



>
>     <jaxrs:server id="systemEndpoint" address="/system">
>         <jaxrs:serviceBeans>
>             <ref bean="systemImpl"/>
>         </jaxrs:serviceBeans>
>         <jaxrs:properties>
>             <entry key="javax.xml.stream.XMLInputFactory">
>                 <ref bean="jsonInputFactory"/>
>             </entry>
>             <entry key="javax.xml.stream.XMLOutputFactory">
>                 <ref bean="jsonOutputFactory"/>
>             </entry>
>         </jaxrs:properties>
>     </jaxrs:server>
>
> Return type;
> @XmlRootElement(name = "JSONTest", namespace = "http://www.acme.com/
> test")
> @XmlType(name = "", propOrder = {"a", "b", "c"})
> @XmlAccessorType(XmlAccessType.FIELD)
> public class JSONTest {
>     @XmlElement
>     private String a;
>     @XmlElement
>     private String b;
>     @XmlElement
>     private String c;
>
> REST impl:
>     @GET
>     @Path("/jupdate/")
>     public JSONTest jupdates() {
>         JSONTest b = new JSONTest("1", "2", "3");
>         return b;
>     }
>
> $ curl -H "Accept: application/xml" http://localhost:8080/test/system/jupdate
> <ns2:JSONTest xmlns:ns2="http://www.acme.com/test"><a>1</a><b>2</
> b><c>3</c></ns2:JSONTest>
>
> $ curl -H "Accept: application/json" http://localhost:8080/test/system/jupdate
> {"cxf.XMLFault":{"cxf.faultstring":"java.lang.IllegalStateException:
> Invalid JSON namespace: http:\/\/www.acme.com\/test"}}
>
> Log file:
> java.lang.IllegalStateException: Invalid JSON namespace: http://www.acme.com/test
>         at
> org
> .codehaus
> .jettison
> .mapped
> .MappedNamespaceConvention
> .getJSONNamespace(MappedNamespaceConvention.java:151)
>         at
> org
> .codehaus
> .jettison
> .mapped
> .MappedNamespaceConvention.createKey(MappedNamespaceConvention.java:158)
>         at
> org
> .codehaus
> .jettison
> .mapped
> .MappedXMLStreamWriter.writeStartElement(MappedXMLStreamWriter.java:241)
>         at
> com
> .sun
> .xml
> .bind
> .v2
> .runtime
> .output.XMLStreamWriterOutput.beginStartTag(XMLStreamWriterOutput.java:
> 113)
> ...
>
> If I remove the namespace declaration from JSONTest, I get a valid
> answer, but the types on the wire are really JAXB generated and I want
> namespaces on them for the XML domain:
>
> $ curl -H "Accept: application/json" http://localhost:8080/test/system/jupdate
> {"JSONTest":{"a":1,"b":2,"c":3}}
>
> --Joe
>
> 

----------------------------
IONA Technologies PLC (registered in Ireland)
Registered Number: 171387
Registered Address: The IONA Building, Shelbourne Road, Dublin 4, Ireland