Danail Alexiev
Danail Alexiev

Reputation: 7772

Process custom annotation in implementing class of an Resource interface

I am trying to process a custom annotation on a class that implements an external interface that defines a Resource. The setup is the following:

A Resource interface, I can't modify it:

@Path("/v1")
public interface Resource {

    @GET
    @Path("/foo")
    Response foo();

}

An implementation that I can modify:

public class ResourceImpl implements Resource {

    @Override
    @CustomAnnotation // has Retention.RUNTIME
    public Response foo() {
        // foo logic
    }
}

I've implemented a filter to try and process the @CustomAnnotation on the overriden foo() method:

@Provider
@ServerInterceptor
@Precedence("SECURITY")
public class CustomAnnotationInterceptor implements ContainerRequestFilter {

    @Context
    ResourceInfo resourceInfo;

    @Override
    public void filter(ContainerRequestContext containerRequestContext) throws IOException {
        // check if the invoked resource method is annotated with @CustomAnnotation and do logic
    }
}

However, when I try to get the matched resource class from the ResourceInfo instance, I get the Resource interface, and when I get the matched method, I get the foo() method from the interface which is lacking the @CustomAnnotation. Is there any way around this?

I'm using RESTEasy as an implementation of JAX-RS.

Upvotes: 1

Views: 541

Answers (1)

MiKo
MiKo

Reputation: 2146

You could implement an interceptor, where you can get hold of the actual resource (method and class) being called. The interceptor should be bound to your annotation using @InterceptorBinding (see 54.2.4 Binding Interceptors to Components).

// Interceptor
@Interceptor
@CustomAnnotation
@Priority(Interceptor.Priority.APPLICATION)
public class CustomAnnotationInterceptor {

    @AroundInvoke
    public Object interceptCustomAnnotation(InvocationContext ctx) throws Exception {
        CustomAnnotation customAnnotation = null;
        
        // The actual method being called
        Method method = ctx.getMethod();
        if (method != null) {
            customAnnotation = method.getAnnotation(CustomAnnotation.class);
        }

        // ... do stuff with the annotation

        return ctx.proceed();
    }
}

To get the instance of the class that implements your interface you could use ctx.getMethod().getDeclaringClass() or ctx.getTarget().getClass().getSuperclass().

Upvotes: 1

Related Questions