dev@jsr311.java.net

RE: Representation<T> and Entity<T>

From: Jerome Louvel <jerome.louvel_at_noelios.com>
Date: Tue, 10 Apr 2007 10:51:43 +0200

Marc,

> (i)
>
> @UriTemplate("someuri")
> @ProduceMime("application/foo")
> @ConsumeMime("application/bar")
> public class SomeBean {
> @HttpMethod
> Foo postData(Bar bar) {
> ...
> }
> }
>
> (ii)
>
> @UriTemplate("someuri")
> @ProduceMime("application/foo")
> @ConsumeMime("application/bar")
> public class SomeBean {
> @HttpMethod
> Representation<Foo> postData(Entity<Bar> bar) {
> ...
> }
> }
>
> Jerome would prefer a pure annotation approach and suggested
> a couple
> of alternatives:
>
> (iii)
>
> @UriTemplate("someuri")
> public class SomeBean {
> @HttpMethod
> Foo postData(Bar bar) {
> ...
> }
> }
>
> @Representation(mediaType="application/foo")
> public class Foo {
> ...
> }
>
> @Representation(mediaType="application/bar")
> public class Bar {
> ...
> }
>
> or (I'm interpreting here since the example only had one type rather
> than two but I think this is what was being proposed and I'm sure
> Jerome will correct me if I missunderstood)
>
> (iv)
>
> @UriTemplate("someuri")
> public class SomeBean {
> @HttpMethod
> @Representation(mediaType="application/foo")
> Foo postData(@Representation(mediaType="application/bar")Bar bar) {
> ...
> }
> }

Actually, I was proposing a combination of (iii) and (iv). If you don't have
control on the source code of the representation classes, it should be
possible to annotate them externally, either at the return type or parameter
type level, or via an external annotation file (similar to JAXB approach).

> Now for some additional comments:
>
> Approach (iii) would work well for custom types where the developer
> has access to the source code and where the type has only one media
> type. It doesn't work when the types being used are from an external
> library or where the same type could be serialized using a
> variety of
> media types. E.g. consider the following variant of (i) above where
> both the input and output are Strings:
>
> @UriTemplate("someuri")
> @ProduceMime("application/foo")
> @ConsumeMime("application/bar")
> public class SomeBean {
> @HttpMethod
> String postData(String bar) {
> ...
> }
> }
>
> To use approach (iii) the developer would have to write two
> subclasses of String just to have something to attach the
> @Representation to.

Beside, my suggestion to rely on (iv) in this case, it is also important to
note that it unlikely that you would want to expose POJOs as RESTful Web
services if you don't even have control on the source case. Is it possible
to persist a POJO in a RDBMS if you don't have access to its source code to
annotate it? If this is indeed an important use case, we should consider the
possibility of external annotations. There might even be space for a
cross-JSR approach to external annotation definitions.

> Approach (iii) also fails when the Java class is auto generated as
> part of the build. E.g. when working with JAXB its common to
> generate
> the JAXB classes from the schema during the build process.
> That means
> you can't edit the generated classes to add the @Representation
> annotation and the developer is again left having to write a
> subclass
> to attach the annotation to.

Note that I consider the usage of JAXB to serialize representations as an
important use case. But if you autogenerate your POJOs from an XSD schema,
then it is unlikely that your POJOs will expose media types other than XML
ones, otherwise you would need to have control on them to generate them
(JSON for example). BTW, JAXB can also work using POJOs as an input instead
of an XSD schema.

> Approach (iv) is actually quite similar to approach (i), it just
> moves the annotations and uses the same annotation for input and
> output data. Approaches (i) and (iv) have very similar
> properties and
> both work well when the media types are known and are static. I'd
> argue that (i) is better since it allows a developer to specify the
> input and output media types once at the class level rather than on
> every method but that is a relatively small point.

We could perfectly extend (iv) to support the definition of default input
and output representation metadata:

@ParentRef("someuri")
@Input("application/bar")
@Output(mediaType="application/foo", characterSet="UTF-8")
public class SomeBean {
   @Method
   Foo postData(Bar bar) {
     ...
   }
}

> Where the pure
> annotation approach falls down is in dealing with non-static types,
> e.g. consider a method to add an Atom media entry:
>
> @UriTemplate("{feed}")
> @ProduceMime("application/atom+xml")
> public class AtomFeed {
>
> @HttpMethod
> public Entry postEntry(Entity<InputStream> media) {
> ...
> }
>
> ...
> }
>
> The above is similar to approach (ii) above except the ConsumeMime
> annotation has been removed so the method will be called for any
> media type. Here the media method parameter contains an input stream
> from which to read the entity body and additional metadata including
> the media type and language. Without the Entity class the developer
> would either have to create a new class to do the same job
> along with
> a serializer and deserializer for that class or use a low level API
> to extract the Content-Type (and possibly other) header from the
> request. The same problems occur when a method needs to return
> something where the metadata isn't known in advance. I think these
> are common enough use cases that its worthwhile standardizing the
> Entity interface and Representation class to save developers the
> additional effort their omission would cause.

I agree that this is an important case to consider. There are annotation
based solution like:

@Method
public Entry postEntry(@Input InputStream data, @MediaType String type) {

Note that @Input is a specialized version of @Representation pointing to the
representation received as request entity.

Best regards,
Jerome