Sergey, Thanks for the thorough response. I'll give this a try and let you know how it goes.
-Javier -----Original Message----- From: Sergey Beryozkin [mailto:[email protected]] Sent: Friday, August 21, 2009 6:30 AM To: [email protected] Subject: Re: Spring, CXF, JAX-RS, JSON Hi There're few issues which interfere at the moment. First one is not actually an issue in the JAX-RS sense : JAX-RS resource methods can only handle a single parameter which is not annotated with JAXRS annotations like @PathParam/etc. Thus you see add() working but multiple() not. Another issue is that JSONProvider can not deserialize explicit collections at the moment, like { "x":20, "y":10 }, thus converting CalculatorResponse multiply( double x, double y ); to CalculatorResponse multiply( double[] args); would not work and would be probably wrong (require extra checks like length equals to 2, etc). so if you do POST { "x":20, "y":10 } then I'd recommend introduce a hierarchy like @XmlRootElement("bean") class AbstractOpBean { protected double x; protected double y; } class MultiplyOpBean extends AbstractOpBean { public doable multiply() {return x * y; } } and then just do CalculatorResponse multiply(MultipleOpBean op) { CalculatorResponse response = new CalculatorResponse(); response.setValue(op.multiply();); } perhaps you can have an abstract calculate() method on the Abstract bean instead and then delegate in all the cases to a helper function. The only remaining thing then would be to explicitly configure a JSONProvider with a 'wrapperName' property being set to 'bean' so that a sequence like { "x":20, "y":10 } could be deserialized into MultiplyOpBean. Now, as far as JAXB annotations are concerned you may want to have @XmlRootElement on MultiplyOpBean instead otherwise you would also likely need to add @XmlSeeAlso to AbstractBeanOp... hope it helps Sergey Javier Delgadillo wrote: > > I'm hoping someone on this list can help me figuring out what I'm missing. > I'm trying to write a CXF/Spring/JAX-RS webapp that uses JSON for both > inputs and outputs. I've got a simple ICalculator interface with the > standard add/subtract/multiply/divide methods. add/subtract are working > used @PathParm and @QueryParam annotations and return valid JSON responses > for the CalculatorResponse class. I've been trying to get multiply (or > divide) to work by posting a JSON string that has the parameters. In > essence, I'd like the following request to parse and pass parameters > appropriately: > > POST /calculator/multiply HTTP/1.1 > Accept: */* > Accept-Language: en-us > Referer: http://server/jaxrstest/calc.html > x-requested-with: XMLHttpRequest > Content-Type: application/json > Accept-Encoding: gzip, deflate > User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR > 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.4506.2152; .NET CLR > 3.5.30729) > Host: server:80 > Content-Length: 18 > Connection: Keep-Alive > Pragma: no-cache > > { "x":20, "y":10 } > > > But CXF always complains because the parser for the input isn't parsing > JSON. It sees the '{' character and throws an exception because it was > expecting a number. I've searched google and the cxf-users list but > haven't found an example that tells me how to configure CXF to parse the > JSON string. Has anyone tried doing this? I'm hoping I just missed a > setting in the Spring Config files. > > Using cxf-bundle-jaxrs 2.2.2, spring 2.5.6 > > Relevant code/config files below: > > > @XmlRootElement( name="CalculatorResponse" ) > > public class CalculatorResponse > > { > > double m_value; > > > > // Default Constructor > > public CalculatorResponse() > > { > > } > > > > public void setValue( double value ) > > { > > m_value = value; > > } > > > > public double getValue() > > { > > return m_value; > > } > > } > > > @Path("/calculator/") > @Consumes("application/json") > @Produces("application/json") > public interface ICalculator > { > /** > * This will be accessible via /calculator/1/2 > * @param x value for x > * @param y value for y > * @return CalculatorResponse > */ > @GET > @Path("/add/{x}/{y}") > CalculatorResponse add( @PathParam( "x" )long x, @PathParam( "y" )long > y ); > > /** > * The parameters here will be passed like typical URL params > * /calculator/subtract?x=10.0&y=5.0 > * @param x Value for X > * @param y Value for Y > * @return CalculatorResponse > */ > @GET > @POST > @Path("subtract") > CalculatorResponse subtract( @QueryParam( "x" ) double x, @QueryParam( > "y" ) double y ); > > @POST > @Path("divide") > CalculatorResponse divide( double x, double y ); > > @POST > @Path("multiply") > CalculatorResponse multiply( double x, double y ); > } > > > public class CalculatorImpl implements ICalculator > > { > > // Default Constructor > > public CalculatorImpl() > > { > > } > > > > public CalculatorResponse add( long x, long y) > > { > > CalculatorResponse response = new CalculatorResponse(); > > response.setValue( x+y ); > > return response; > > } > > > > > > public CalculatorResponse subtract( double x, double y) > > { > > CalculatorResponse response = new CalculatorResponse(); > > response.setValue( x-y ); > > return response; > > } > > > > public CalculatorResponse divide( double x, double y) > > { > > CalculatorResponse response = new CalculatorResponse(); > > response.setValue( x/y ); > > return response; > > } > > > > public CalculatorResponse multiply( double x, double y) > > { > > CalculatorResponse response = new CalculatorResponse(); > > response.setValue( x*y ); > > return response; > > } > > } > > > > <?xml version="1.0" encoding="UTF-8"?> > > <beans xmlns="http://www.springframework.org/schema/beans" > xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" > > xmlns:jaxrs="http://cxf.apache.org/jaxrs" > > xmlns:util="http://www.springframework.org/schema/util" > > xsi:schemaLocation=" > > http://www.springframework.org/schema/beans > > http://www.springframework.org/schema/beans/spring-beans.xsd > > http://cxf.apache.org/jaxrs > > http://cxf.apache.org/schemas/jaxrs.xsd > > http://www.springframework.org/schema/util > http://www.springframework.org/schema/util/spring-util-2.0.xsd" > > > > default-lazy-init="false"> > > > > <import resource="classpath:META-INF/cxf/cxf.xml" /> > > <import > resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" /> > > <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> > > > > <util:map id="jsonNamespaceMap" map-class="java.util.Hashtable"> > > <entry key="http://databasin.org/" value="b"/> > > <entry key="http://cxf.apache.org/bindings/xformat" value="cxf" /> > > </util:map> > > > > <bean id="jsonProvider" > class="org.apache.cxf.jaxrs.provider.JSONProvider"> > > <property name="namespaceMap" ref="jsonNamespaceMap"/> > > </bean> > > > > <bean id="calculatorBean" > class="com.esri.solutions.databasin.impl.CalculatorImpl" /> > > > > <jaxrs:server id="myService" address="/"> > > <jaxrs:serviceBeans> > > <ref bean="calculatorBean" /> > > </jaxrs:serviceBeans> > > <jaxrs:providers> > > <ref bean="jsonProvider" /> > > </jaxrs:providers> > > </jaxrs:server> > > </beans> > > > > --- > Javier Delgadillo > ESRI / Implementation Services > http://www.arcwebservices.com/ > (909) 793-2853 x1068 > > > -- View this message in context: http://www.nabble.com/Spring%2C-CXF%2C-JAX-RS%2C-JSON-tp25066939p25079830.html Sent from the cxf-user mailing list archive at Nabble.com.
