Restlet using custom media type

323 views Asked by At

In Restlet 2.3 (SE) I am trying to use media types to control versions. My current attempt involves registering new extensions in my inbound route:

@Override
public Restlet createInboundRoot() {

        ...
        getTunnelService().setExtensionsTunnel(true);

        getMetadataService().addExtension("vnd.myapp.v1", MediaType.valueOf("application/vnd.myapp.v1+json"));
        getMetadataService().addExtension("vnd.myapp.v2", MediaType.valueOf("application/vnd.myapp.v2+json"));

        ...
}

My resource interface is then setup as follows:

public interface UsersResource {

    @Options
    void getCorsSupport();

    @Get("vnd.myapp.v1")
    Collection<User> representV1() throws Exception;

    // Should be the default if */* is specified
    @Get("json | vnd.myapp.v2")
    Collection<User> representV2() throws Exception;

}

I then tried specifying the media types as follows:

http://localhost:8080/api/users?media=vnd.myapp.v1

The idea is that if somebody specifies the media type as vnd.myapp.v1 they get representV1() (JSON), if they specify the media type as vnd.myapp.v2 they get representV2() (JSON) and (optionally) if they ask for nothing specific they get representV2(). With the above setup no matter what is requested I always get back representV2().

2

There are 2 answers

0
Thierry Templier On BEST ANSWER

Here is what I had when testing:

  • Accept: application/vnd.myapp.v1+json -> representV1 is called
  • Accept: application/vnd.myapp.v2+json -> representV2 is called
  • Accept: application/application/json -> representV1 is called
  • Accept: */* -> representV1 is called

It seems that the expression json | vnd.myapp.v2 doesn't work properly. The workaround is to split representV2 into two methods with json and vnd.myapp.v2.

When no accept header is specified, it seems that Restlet calls the first method with annotation Get it finds.

Something that could help you is to enable traces to see the scores of the different methods:

public class RestletLauncher {
    public static void main(String[] args) {
        Engine.getInstance().setLogLevel(Level.FINEST);
        launchApplication();
    }
}

You'll see traces like that:

Score of annotation "MethodAnnotationInfo [javaMethod: public org.restlet.representation.Representation test.MyServerResource1.testGetVnd1(), javaClass: class test.MyServerResource1, restletMethod: GET, input: vnd.myapp.v1, value: vnd.myapp.v1, output: vnd.myapp.v1, query: null]"= 0.5
Total score of variant "[application/vnd.myapp.v1+json]"= 0.04191667
Score of annotation "MethodAnnotationInfo [javaMethod: public org.restlet.representation.Representation test.MyServerResource1.testGetJson(), javaClass: class test.MyServerResource1, restletMethod: GET, input: json, value: json, output: json, query: null]"= 0.5
Total score of variant "[application/json]"= 0.04191667
Score of annotation "MethodAnnotationInfo [javaMethod: public org.restlet.representation.Representation test.MyServerResource1.testGetVnd2(), javaClass: class test.MyServerResource1, restletMethod: GET, input: vnd.myapp.v2, value: vnd.myapp.v2, output: vnd.myapp.v2, query: null]"= 0.5
Total score of variant "[application/vnd.myapp.v2+json]"= 0.04191667

Hope it helps you, Thierry

1
Thierry Boileau On

It gets better when removing the spaces character in the annotation such as:

@Get("json|vnd.myapp.v2")

I've entered an issue to fix this. https://github.com/restlet/restlet-framework-java/issues/1099

best regards, Thierry Boileau