Marc Hadley wrote:
> On Feb 2, 2008, at 5:26 PM, Bill Burke wrote:
>
>> I do think you need some inheritance rules though. For example, in
>> the EJB 3 specification you may override a business method in a
>> subclass and provide different metadata.
>>
>> I also wish that JAX-RS annotations could be extracted from an
>> implemented interface. i.e.:
>>
>> public class StoreBean implements ShoppingStore {
>>
>> public Book getBook(int id) {...}
>> }
>>
>> @Path("/shopping")
>> public interface ShoppingStore {
>>
>> @GET @Path("bookstore/books/{id}")
>> public Book getBook(@PathParam("id") int id);
>> }
>>
>> This would be very similar to the EJB3/JAX-WS integration style.
>>
> I agree that we should be explicit about how inheritance is handled, we
> already have issue 16 which we can use to track this:
>
> https://jsr311.dev.java.net/issues/show_bug.cgi?id=16
>
> I'm a little conflicted on what we should do here and much of that
> conflict revolves around the relationship between a Java contract and a
> HTTP one
What does
, specifically how wise it is to tie the two together. Let say I
> want to define a re-usable Atom feed component. At first blush you might
> define a Java interface like this:
>
> @ProduceMime("application/atom+xml")
> @ConsumeMime("application/atom+xml")
> @Path("feeds/{feed_id}")
> public interface AtomFeed {
>
> @GET
> Feed getFeed(@PathParam("feed_id") String feedId);
>
> @POST
> Entry addEntry(@PathParam("feed_id") String feedId, Entry newEntry);
> }
>
> The problem with the above is that you've restricted the shape of the
> URI that can be used. What if a user of your component wanted:
> /users/{userId}/feeds/{feedId} or /feeds?feed={feed_id}. For the first
> case a user could override the @Path with one on the implementation
> class but for the second, the use of @PathParam requires the feedId to
> be embedded in the path so they would also have to override the
> annotation on the method parameter (not simply the annotation value -
> actually change @PathParam to @QueryParam). You've also fixed the type
> of the feed id, if a user always uses numeric ids then you've forced
> they to do the String->int conversion themselves rather than letting the
> runtime do it for them.
>
> You might think about dropping the URI related annotations from the
> interface:
>
> @ProduceMime("application/atom+xml")
> @ConsumeMime("application/atom+xml")
> public interface AtomFeed {
>
> @GET
> Feed getFeed();
>
> @POST
> Entry addEntry(Entry newEntry);
> }
>
> A user could now implement the interface and use a constructor to
> extract whatever identifier they require:
>
> @Path("feeds")
> public class Feeds implements AtomFeed {
>
> public Feeds(@QueryParam("feed_id") String) {...}
>
> public Feed getFeed() {...}
>
> public Entry addEntry(Entry newEntry) {...}
> }
>
> This is better but you've still made some decisions for the end user of
> the interface. E.g. they might or might not support use of a slug
> header, the interface doesn't include a parameter for one so if one is
> supported you've forced the user to inject HttpHeaders rather than use
> @HeaderParam.
>
> Essentially, the above use of an interface is imposing constraints on an
> implementing class but not really adding much value beyond saying what
> methods they have to support (which the Atom protocol spec already does).
>
I was gonna say, copy what JAX-WS has done, but our rep for that spec
told me their rules are broken and/or horrible and we should come up
with our own.
I hope you're not saying that we shouldn't support JAX-RS on interfaces
at all. I'm fine with KISS too. either you put it on the interface or
the bean class. Sure makes the spec simpler :)
Bill
--
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com