Skip to content

Overriding, Detaching and Skipping Components

Lahiru Sahan Jayasinghe edited this page Jan 5, 2014 · 3 revisions

Components such as serializers, deserializers and interceptors attached at the root of the endpoint are common to all requests. If a new request defined on the endpoint requires and an alternate component, you should be able to override the root definition. In contrast, if the new request wishes to skip the component, you should be able to detach the entire root definition or skip individual components. Without any special provision for overriding, detaching and skipping, component definitions would have to be repeated for every request to which it's attached.


####1. Overriding and Detaching Serializers and Deserializers

Serializers and deserializers are attached with the @Serialize and @Deserialize annotations. Obviously, a single request can only use a single serializer or deserializer. When either of these components are attached to the endpoint, it applies to all requests. If a single request needs to override the root definition, simply reattach the required serializer or deserializer to the request.

@Deserialize(JSON)
@Endpoint("https://api.github.com")
public interface GitHubEndpoint {

    @GET("/users/{user}")
    User getUser(@PathParam("user") String user);

    @GET("/users/{user}/gists")
    @Deserialize(type = GistDeserializer.class)
    List<Gist> getGists(@PathParam("user") String user);
}

JSON deserializer is overridden by GistDeserializer.

To detach the root definition all-together, use the @Detach annotation with the Class of the annotation used for attaching the component.

@Deserialize(JSON)
@Endpoint("https://api.github.com")
public interface GitHubEndpoint {

    @GET("/users/{user}")
    User getUser(@PathParam("user") String user);

    @Detach(Deserialize.class) //detach all components; directive: Deserialize
    @GET("/users/{user}/gists")
    HttpEntity getGists(@PathParam("user") String user);
}

JSON deserializer is detached; getGists() will not be using any deserializer.


####2. Detaching and Skipping Interceptors

Interceptors work a tad differently than serializers and deserializers. There is no concept of interceptor overriding. The interceptor(s) attached to the endpoint will be applied together with any interceptor(s) attached to the request. However, all interceptors, defined on the endpoint or request can be detached by using @Detach. Individual interceptors defined on the endpoint can be skipped by using @Skip on a request.

@Deserialize(JSON)
@Endpoint("https://api.github.com")
@Intercept({HeaderInterceptor.class, AuthInterceptor.class})
public interface GitHubEndpoint {

    @GET("/user/repos")
    @Intercept(RepoInterceptor.class)
    List<Repo> getRepos();

    @GET("/users/{user}")
    @Skip(AuthInterceptor.class)
    @Intercept(UserInterceptor.class)
    User getUser(@PathParam("user") String user);

    @GET("/emojis")
    @Detach(Intercept.class) //detach all components; directive: Intercept
    String getEmojis();
}

getRepos() will be using HeaderInterceptor, AuthInterceptor and RepoInterceptor.
getUser() will be using HeaderInterceptor and UserInterceptor, but not AuthInterceptor.
getEmojis() will not be using any interceptor.


####3. Detaching an Async Directive

An @Async annotation placed on an endpoint will cause all requests to be executed asynchronously. If a request should be exempted from this rule, the @Async directive can be detached with @Detach.

@Async 
@Deserialize(JSON)
@Endpoint("https://api.github.com")
public interface GitHubEndpoint {

    @GET("/users/{user}/repos")
    List<Repo> getRepos(@PathParam("user") String user, AsyncHandler<List<Repo>> asyncHandler);

    @GET("/meta")
    @Detach(Async.class)
    Meta getMetaInfo();
}


Although none of the above examples demonstrate multiple component-type detachment and skipping, keep in mind that this is possible.
@Detach({Async.class, Intercept.class, Serialize.class, Deserialize.class})
@Skip({HeaderInterceptor.class, AuthInterceptor.class})