On 20/06/2011, at 6:59 PM, Gili wrote:
> On 20/06/2011 12:56 PM, Cameron Heavon-Jones [via Jersey] wrote:
>>
>> Hey Gili,
>>
>> Aren't you consuming\returning JSON?
>>
>> Why do you want to introduced new media types? (For reasons other than dispatch!)
>
> Because of http://stackoverflow.com/questions/972226/how-to-version-rest-uris/975394#975394
>
> 1. It helps with versioning resources.
> 2. The way I see it, the MimeType indicates the class name, the path indicates the property. If you specify application/json across the board then you can't differentiate between creating different kinds of devices. For example:
>
> @POST /devices
>
> without custom mime types you have no way of knowing which kind of device. For resources with a JSON body you could embed the resource type into the @POST entity body but (in my opinion) it is much cleaner to specify the resource type using MimeType and dedicate the entity body to the actual value of the resource. Now, I can use @POST /devices to create as many different kinds of devices as I want.
>
Ahhh, fair enough :)
I read about this too and it sounds like a very pragmatic solution. I also see a few issues with it too thought, which is what makes me hesitate from implementing something based on it myself.
The main problem i have is that this isn't how media types have been used...not a very god reason but when you look at, for example, text\html no-one would put a version in that media type. Html, and for that matter, java, get around the version problem by maintaining backwards compatibility. Then the version of the data is of lower importance and can be embedded within, instead of needing to be supplemented in order for the correct service to be called.
I guess that's maybe the real problem i have with versioning media types... it's being used to select which service to run, instead of customising the service to handle evolving versions.
Isn't this the case between implicit vs explicit versioning? Implicit versioning is evolution by only adding new information, whereas explicit versioning allows for revolutionary changes.
>> This can be enforced as you showed through created new methods with consume\produce annotations, but since there will always be a device with id=5, and no duplicate ids, i'm not sure what you're really accomplishing if this is just to return data?
>
> Because each subclass contains different fields, I need to issue different database queries to retrieve the data (remember, each subclass is mapped to a different table).
>
Isn't there a polymorphic load available with multiple table persistence? I seem to remember doing something similar in hibernate years ago, something like:
MySpecifcClass obj = session.load(MySpecifcClass.class, id);
>>
>> >
>> > 4. Now that I think about it, I don't want to have to declare @Consumes,
>> > @Produces twice (once on the parent resource, and one on the actual
>> > resource). Ideally I just want to provide Jersey with a list of possible
>> > sub-resources and it should select the correct one by matching the user's
>> > Accepts header to a sub-resource @Consumes/_at_Produces.
>> >
>> > Gili
>> >
>>
>> How about this?
>>
>> @Consumes(IPHONE_TYPE)
>> public IPhoneDevice getIphone(String id){
>> return new IphoneDevice(id);
>> }
>>
>> @Consumes(ANDROID_TYPE)
>> public AndroidDevice getAndroid(String id){
>> return new AndroidDevice(id);
>> }
>>
>> Any @Consumes annotation on the sub-resource is not used, as this has already been restricted on the locator.
>>
>> I think i'd prefer using a path name but this would work ok.
>
> Okay I assume this is no different from doing this:
>
> @Consumes(ANDROID_TYPE)
> public Response getAndroid(String id)
> {
> return new AndroidDevice(id).get();
> }
>
> The only benefit of sub-resources would be if I could funnel multiple methods (GET, PUT, DELETE, etc) through a single method in the parent resource.
This is exactly what sub-resources are for :)
> Assuming the child resource contains the following methods:
>
> @GET
> @Produces(ANDROID_TYPE)
>
> @PUT
> @Consumes(ANDROID_TYPE)
>
> @DELETE
> @Consumes(ANDROID_TYPE)
>
> is there a way for me to funnel requests to it? If I declare:
>
> @Consumes(ANDROID_TYPE)
> @Produces(ANDROID_TYPE)
> public AndroidDevice getAndroid(String id)
>
> doesn't this imply adding a @Consumes to @GET and @Produces to @PUT and @DELETE? That's not really what I'm going for.
>
> Thanks,
> Gili
To continue the dispatch process on a new sub-resource you have to use what is called a "sub-resource locator" which is essentially a @Path annotation on it's own - it can't have any http method annotation.
You *might* be able to have a @Consumes or @Produces, but i'm just not sure... maybe someone from jersey team can confirm?
if you can, then you should be able to do this, which is exactly what you want, no?
@Path("id")
@Produces(ANDROID_TYPE)
public AndroidDevice getAndroid(@PathParam("id) String id){
return new AndroidDevice(id);
}
@Path("id")
@Produces(IPHONE_TYPE)
public IPhoneDevice getIPhone(@PathParam("id) String id){
return new IPhoneDevice(id);
}
thanks,
cam