users@jersey.java.net

Plugging in any String-based reading for _at_*Param <was> Re: [Jersey] Jersey Client: How can I POST an object? I'm getting an HTTP 415 error.

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 19 Feb 2009 18:46:28 +0100

Hi,

This email thread got me thinking that we should be able to support a
general plugable solution similar to the message body reader approach.

So.. i just committed to the trunk the support for
StringReaderProvider (see end of email).

The support for the string constructors and valueOf rules are
implemented using this approach.

TODO add support for JAXB and java.util.Date (where the date format
can be expressed as an annotation).

Paul.


/**
  * Read a string value and convert to a Java type.
  * <p>
  * A {_at_link StringReaderProvider} is responisble for providing an
instance
  * of this interface.
  *
  * @param <T> the Java type to convert to.
  *
  * @author Paul.Sandoz_at_Sun.Com
  */
public interface StringReader<T> {

     /**
      * Read a string value and convert to a Java type.
      *
      * @param value The string value.
      * @return the instance of the Java type.
      */
     T fromString(String value);
}

/**
  * Contract for a provider that supports the conversion of a string
to a
  * Java type. To add a <code>StringReaderProvider</code>
implementation,
  * annotate the implementation class with <code>Provider</code>.
  * <p>
  * Such providers will be used when converting a String value to a
java type
  * annotated by the *Param annotations such as {_at_link
javax.ws.rs.QueryParam}.
  *
  * @param <T> The Java type.
  * @see javax.ws.rs.ext.Provider
  * @see com.sun.jersey.server.spi.StringReaderWorkers
  * @author Paul.Sandoz_at_Sun.Com
  */
public interface StringReaderProvider<T> {

     /**
      * Obtain a StringReader that can produce an instance of a
particular type
      * from a string.
      *
      * @param type the class of object to be produced.
      *
      * @param genericType the type of object to be produced. E.g. if
the
      * string is to be converted into a method parameter, this will be
      * the formal type of the method parameter as returned by
      * <code>Class.getGenericParameterTypes</code>.
      *
      * @param annotations an array of the annotations on the
declaration of the
      * artifact that will be initialized with the produced instance.
E.g. if the
      * string is to be converted into a method parameter, this will be
      * the annotations on that parameter returned by
      * <code>Class.getParameterAnnotations</code>.
      *
      * @return the string reader, otherwise null.
      */
     StringReader<T> getStringReader(Class<?> type, Type genericType,
Annotation annotations[]);
}

Paul.

On Feb 16, 2009, at 4:17 PM, Paul Sandoz wrote:

>
> On Feb 13, 2009, at 11:52 PM, JavaGeek_Boston wrote:
>
>>
>> Hello All,
>> This is probably a remedial question, but I can't get my object to
>> POST? I
>> can return my entity via a @GET call, but I can't seem to post it
>> as a form
>> param. When I execute my POST, I get either an HTTP 415 or 400
>> error,
>> depending on what I set for @Consumes
>>
>> My object is a bean
>> @XmlRootElement
>> public class MyDocumentType implements Serializable{
>> //some fields and getters and setters.
>> }
>>
>> Here's my service:
>> @POST
>> @Path(DOC)
>> @Consumes("application/xml")
>> public String updateDocument(@HeaderParam(SESSION_ID_HEADER_KEY)
>> String
>> sessionId,
>> @FormParam(DOC_OBJ) MyDocumentType doc) {
>> confirmSessionIsValidAndAuthorIsLoggedIn(sessionId, doc);
>> storeService.updateDocument(doc);
>> return "SUCCESS: " + doc.getId();
>> }
>>
>> Here's my client:
>> Client client = new Client();
>> resource = client.resource(serverURL);
>> final WebResource finalPath = resource.path(path);
>> Form form = new Form();
>> form.add("doc", doc);
>> return finalPath.type("application/
>> xml").header(SESSION_ID_HEADER_KEY,
>> sessionId).post(String.class, form);
>>
>>
>> I get an HTTP 400 with that combination.
>>
>
> The problem is that you are first using the media type "application/
> xml" (Jersey should not allow this or should warn you).
>
> Second, you seem to want to add an XML document as a form parameter
> value. It is only possible to support the same rules as for say
> @QueryParam. See the following for more details on the rules:
>
> http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features#OverviewofJAX-RS1.0Features-ExtractingRequestParameters
>
>
>> I think my bean is OK as I can retrieve a MyDocumentType via @GET.
>>
>> When I call:
>> return
>> finalPath
>> .type
>> (MediaType.APPLICATION_FORM_URLENCODED).header(SESSION_ID_HEADER_KEY,
>> sessionId).post(String.class, form);
>> with
>> @Consumes("application/x-www-form-urlencoded")
>> on the service, I get:
>> SEVERE: A message body reader for Java type, class MyDocumentType,
>> and MIME
>> media type, application/x-www-form-urlencoded, was not found
>>
>
> Are you sure you had the @FormParam present in such a case? If you
> did not then i can reproduce what you observe.
>
>
>>
>> Is there something I'm missing? Any help would be greatly
>> appreciated:
>>
>
> If you only ever need to POST the XML document then you do not need
> to use a form:
>
> @Consumes("multipart/form-param")
> @POST
> public String updateDocument(
> @HeaderParam(SESSION_ID_HEADER_KEY) String sessionId,
> DocumentType doc) { ... }
>
>
> If you do want to POST the XML document and some other values as
> well i recommend you utilize the "multipart/form-data" media type.
> When using this type you can reuse all the supported message body
> readers like those for JAXB:
>
> @Consumes("multipart/form-param")
> @POST
> public String updateDocument(
> @HeaderParam(SESSION_ID_HEADER_KEY) String sessionId,
> @FormParam(DOC_OBJ) MyDocumentType doc) { ... }
>
>
> The reason for this difference is that the media type "application/x-
> www-form-urlencoded" defines parameters in terms of strings and
> there is no content-type associated with each parameter, thus the
> general message body readers/writers cannot, like those for JAXB, be
> utilized in such cases. Now, arguably we could improve JAX-RS to
> work well with JAXB in such cases.
>
> When using "multipart/form-param" the parameters are encoded as
> bytes and are associated with a content type thus we can reuse all
> the message body reader functionality, such as that for JAXB.
>
> Hope that helps,
> Paul.
>
>> Thanks,
>> Steven
>> Harvard Children's Hospital Informatics Program
>> --
>> View this message in context: http://n2.nabble.com/Jersey-Client%3A--How-can-I-POST-an-object---I%27m-getting-an-HTTP-415-error.-tp2324279p2324279.html
>> Sent from the Jersey mailing list archive at Nabble.com.
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>