Search code examples
javajsonrestletrestlet-2.0media-type

Restlet using custom media type


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


Solution

  • 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