dev@jsr311.java.net

Representation<T> and Entity<T>

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Fri, 06 Apr 2007 11:16:12 -0400

I thought it would be worth extracting the discussion on the
Representation<T> class into a separate thread so its easier to track
the discussion.

First a summary of the discussion so far:

In the current API a method can include an Entity<T> parameter that
will receive the entity body of a request and a method can return a
Representation<T> that will form the entity body of the response. Use
of Entity<T> and Representation<T> are both optional and a developer
can also use the raw T instead if they are not interested in the
additional metadata supplied by the two interfaces. E.g. both of the
following are OK:

(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) {
     ...
   }
}

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.

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.

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. 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.

Marc.

---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.