dev@jsr311.java.net

RE: JSR311: The best practice to return primitive types from a RESTful service?

From: Liu, Jervis <jliu_at_iona.com>
Date: Tue, 4 Dec 2007 05:00:45 -0500

> -----Original Message-----
> From: Marc.Hadley_at_Sun.COM [mailto:Marc.Hadley_at_Sun.COM]
> Sent: 2007123 22:50
> To: dev_at_jsr311.dev.java.net
> Subject: Re: JSR311: The best practice to return primitive types from a
> RESTful service?
>
> On Dec 3, 2007, at 2:37 AM, Liu, Jervis wrote:
> >>> a). in JSR-311 section 3.1.2, "An implementation MUST include pre-
> >>> packaged EntityProvider implementations for the following Java and
> >>> media type combinations:", add the support for Java Primitive types:
> >>>
> >>> Java primitive types All text media types (text/*).
> >>>
> >>> But with an statement that returning a fine grained primitive type
> >>> is not a recommended practice.
> >>>
> >>> Essentially this means a JSR-311 runtime implementation needs to
> >>> provide a PrimitiveEntityProvider to read and write primitive types
> >>> to/from entity body using text/plain content type, same as what we
> >>> do with String.
> >>>
> >>> b). Do not provide any support for Java Primitive types but
> >>> explicitly stated in JSR-311 section 3.1.2 that no default support
> >>> for returning Java Primitive types is because this is not a
> >>> recommended practice. But if users really want to do this, they
> >>> really understand the design choice they have made, they can do this
> >>> by registering their own PrimitiveEntityProvider on the JSR-311
> >>> container.
> >>>
> >> c) Use one of the primitive type wrapper classes (e.g.
> >> java.lang.Integer) along with a corresponding MessageBodyWriter.
> >>
> >> Thinking about it we could remove the need for a MessageBodyWriter by
> >> requiring the runtime to use the toString method when there's no
> >> MessageBodyWriter. The problem with that is that Object provides a
> >> default toString so it would be easy for an application to exhibit
> >> unexpected behavior if the MessageBodyWriter they provide isn't
> >> picked
> >> up for some reason. Essentially a class of error (missing
> >> MessageBodyWriter) would be hard to detect.
> >>
> >
> > Hi Marc, did you suggest that the JSR-311 runtime provides a
> > behavior such that when there is no MessageBodyWriter selected for
> > the return type, Object.toString will be used to form an
> > output( does this also suggest that in the case of no
> > MessageBodyWriter selected, the default output content type is text/
> > plain?).
>
> Yes and no respectively. Yes, I was suggesting use of Object.toString
> in the case of no MessageBodyWriter though I'm not convinced its a
> good idea due to the issue I describe above. No, the media type would
> still be determined based on the criteria I described in the mail I
> sent last week with the subject "Determining the media type of
> responses".

[Liu, Jervis]
Agreed. This does not look like a good approach. This is inconsistent with what you suggested last week (subject "Determining the media type of responses"): "If the list is empty an error is signaled via a 406 Not Acceptable.". I do believe a 406 makes more sense when there is MessageBodyWriter selected.

>
> > Or instead what you meant is defining a pre-packaged
> > MessageBodyWriter in JSR-311 spec to handle primitive types. For the
> > later, I dont see the difference between this and approach a).
> > Using primitive type wrapper classes is the implementation detail of
> > PrimitiveTypeMessageBodyWriter.
> >
> There's a difference between implementing support for int someMethod()
> vs Integer someMethod(). E.g. a primitive type can't be the
> parameterized type of MessageBodyWriter so you have to use the
> primitive wrapper class instead.
>
[Liu, Jervis]
I think we do need to support " int someMethod ()", this make it a lot easier when people migrating their existing code to JSR-311. For example, I may have following method in my POJO, it is just a matter of adding extra JSR-311 annotations then I can expose this POJO as a RESTful service.

int getEmployeeAge(String employeeName) {
...
}

Have to ask people changing their method signature to Integer getEmployeeAge(String employeeName) sounds unreasonable. Lets talk about the implementation details in a JSR-311 runtime a little bit, I should be able to provide a PrimitiveWrapperMessageBodyWriter as below:

public final class PrimitiveWrapperMessageBodyWriter implements MessageBodyWriter<Object> {

    public boolean supports(Class<?> type) {
        //expect a primitive type wrapper class
        if (type is a primitive type wrapper class)
            return true;
        return false;
    }

    public void writeTo(Object obj, MediaType m, MultivaluedMap<String, Object> headers, OutputStream os) {
        try {
            os.write(obj.toString());
        } catch (IOException e) {
            //TODO: better exception handling
        }

    }
}

Not sure about Jersey, but this works in CXF because the invoking result of int getEmployeeAge(String employeeName) is always wrapped in an Integer as the invoking is done through reflection.

IMHO the JSR-311 spec section 3.1.2 should state that "An implementation MUST include pre-packaged EntityProvider implementations for "Java primitive type wrappers (i.e., Integer) ". And it is the responsibly of JSR-311 runtime to convert from Java primitive types to corresponding Java primitive type wrappers to suit the need of PrimitiveWrapperMessageBodyWriter/Reader.

Cheers,
Jervis

> Marc.
>
> ---
> Marc Hadley <marc.hadley at sun.com>
> CTO Office, Sun Microsystems.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_jsr311.dev.java.net
> For additional commands, e-mail: dev-help_at_jsr311.dev.java.net

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