users@jersey.java.net

Re: How to pass objects in as a method parameter?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 15 Apr 2008 12:38:05 +0200

Hi Travis,

Currently we do not support the extraction of form parameters from a
request entity. In fact Jersey should reject such a method signature
because only one unannotated method parameter is allowed...

Currently, the method signature needs to be:

   @POST @Path("/test")
   public String tester(MultivaluedMap<String, String> params) {
     String x = params.getFirst("x");
     String pAsXml = params.getFirst("p");
   }

You can reuse the JAXB message body reader by doing (off the top of my
head, it may contain errors):

   @Context MessageBodyContext mbc;

   @POST @Path("/test")
   public String tester(MultivaluedMap<String, String> params) {
     String x = params.getFirst("x");

     MessageBodyReader<Profiler> mbr = mbc.getMessageBodyReader(
       Profiler.class, Profiler.class,
       null, null);
     String pAsXml = params.getFirst("p");
     Profile p = mbr.readFrom(Profiler.class, Profiler.class,
       null, null, null,
       new ByetArrayInputStream(pAsXml.getBytes()));
   }


What i would really like to have is the following:

   @FormBean
   public class MyForm {
      String x;
      Profile p;
   }

   @POST @Path("/test")
   public String tester(MyForm form) {
   }

and a message body reader that operates on @Form annotation classes can
use MessageBodyContext as shown above. In fact that would be a great
independent task for someone to experiment with.

Later today i will respond with a plug for the client API :-) to
contrast with the Apache API. Just making some tweaks to form stuff to
make it easier to use on the client side.

Paul.

Travis Reeder wrote:
> So here's the method I'm testing:
>
> @POST
> @Path("/test")
> public String tester(String x, Profile p){
> System.out.println("x=" + x);
> System.out.println("profile=" + p);
> return "allgood";
> }
>
> Here's the test code:
>
> HttpClient client = new HttpClient();
> PostMethod post = new
> PostMethod("http://localhost:8081/rest/profiles/test");
> Profile pro = new Profile();
> pro.setFirstName("Scooby");
> pro.setLastName("Doo");
> JAXBContext jaxbContext = JAXBContext.newInstance(Profile.class);
> Marshaller marshaller = jaxbContext.createMarshaller();
> StringWriter writer = new StringWriter();
> marshaller.marshal(pro, writer);
> post.addParameter("p", writer.toString());
> post.addParameter("x", "sooby_at_doo.com <mailto:sooby_at_doo.com>");
> System.out.println(post.getParameter("p"));
> int status = client.executeMethod(post);
> System.out.println("status=" + status);
> String response = post.getResponseBodyAsString();
> System.out.println("response=" + response);
>
> The Profile class has @XmlRootElement and marshals/unmarshals fine when
> using JAXB alone and when returning it via an @Get method. But when I
> try to run it with the method above, I get:
>
> Caused by: com.sun.ws.rest.api.container.ContainerException: Exception
> injecting parameters to Web resource method
> at
> com.sun.ws.rest.impl.model.method.dispatch.EntityParamDispatchProvider$EntityParamInInvoker.getParams(EntityParamDispatchProvider.java:79)
> at
> com.sun.ws.rest.impl.model.method.dispatch.EntityParamDispatchProvider$TypeOutInvoker._dispatch(EntityParamDispatchProvider.java:105)
> at
> com.sun.ws.rest.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:66)
> at
> com.sun.ws.rest.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:108)
> at
> com.sun.ws.rest.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:88)
> at
> com.sun.ws.rest.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:55)
> at
> com.sun.ws.rest.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:88)
> at
> com.sun.ws.rest.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:49)
> at
> com.sun.ws.rest.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:369)
> at
> com.sun.ws.rest.spi.container.servlet.ServletContainer.service(ServletContainer.java:130)
> ... 19 more
> Caused by: java.lang.IllegalArgumentException: java.io.IOException:
> Error marshalling out JAXB object of type "class a.b.c.Profile".
> at
> com.sun.ws.rest.spi.container.AbstractContainerRequest.getEntity(AbstractContainerRequest.java:204)
> at
> com.sun.ws.rest.impl.model.method.dispatch.EntityParamDispatchProvider$EntityExtractor.extract(EntityParamDispatchProvider.java:57)
> at
> com.sun.ws.rest.impl.model.method.dispatch.EntityParamDispatchProvider$EntityParamInInvoker.getParams(EntityParamDispatchProvider.java:73)
> ... 28 more
> Caused by: java.io.IOException: Error marshalling out JAXB object of
> type "class a.b.c.Profile".
> at
> com.sun.ws.rest.impl.provider.entity.XMLJAXBElementProvider.readFrom(XMLJAXBElementProvider.java:50)
> at
> com.sun.ws.rest.spi.container.AbstractContainerRequest.getEntity(AbstractContainerRequest.java:201)
> ... 30 more
> Caused by: javax.xml.bind.UnmarshalException
> - with linked exception:
> [org.xml.sax.SAXParseException: Premature end of file.]
> at
> javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:315)
> at
> com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:481)
> at
> com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:199)
> at
> com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:168)
> at
> javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
> at
> javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:184)
> at
> com.sun.ws.rest.impl.provider.entity.XMLJAXBElementProvider.readFrom(XMLJAXBElementProvider.java:48)
> ... 31 more
> Caused by: org.xml.sax.SAXParseException: Premature end of file.
> at
> com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
> at
> com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.fatalError(ErrorHandlerWrapper.java:174)
> at
> com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:388)
> at
> com.sun.org.apache.xerces.internal.impl.XMLScanner.reportFatalError(XMLScanner.java:1411)
> at
> com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1044)
> at
> com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
> at
> com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
> at
> com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:508)
> at
> com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
> at
> com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
> at
> com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
> at
> com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
> at
> com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
> at
> com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:195)
> ... 35 more
>
>
> Any help would be appreciated. Thanks.

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109