How to access Jersey's contextual objects in an aspect when using Spring?

357 Views Asked by At

I am working with Spring 5.2.x together with Jersey 2.30.x for JAX-RS.

I have an annotation as following:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyAnnotation {
}

In my service, I use this annotation as following:

@Service
public class MyService {
    @MyAnnotation
    public Response get() {
        ...
    }
}

I want to execute certain logic when the @MyAnnotation annotation is present. For this, I created an aspect:

@Aspect
@Component
public class MyAspect {
    @Context
    private ContainerRequest request;

    @Pointcut("@annotation(so.MyAnnotation)")
    public void annotated() {
    }

    @Before("annotated()")
    public void test() {
        System.out.println("I need access to the HTTP headers: " + request);
    }
}

In this aspect, I need access to the HTTP headers. I tried injecting Jersey's ContainerRequest, but this seems to fail: the reference is always null.

So my question is: how can I access Jersey's contextual objects, such as ContainerRequest, in Spring's managed beans?

minimal example

I created a minimal example, see https://github.com/pbillen/playground-so-61750237. You can build it with mvn clean install -U and then start a Tomcat container with mvn cargo:run. If you then point your browser to http://localhost:8080/, you will see in the console:

I need access to the HTTP headers: null

working solution, by bypassing Jersey and using HttpServletRequest

I tried wiring HttpServletRequest in the aspect and then accessing the Authorization header:

@Aspect
@Component
public class MyAspect {
    @Autowired
    private HttpServletRequest request;

    @Pointcut("@annotation(so.MyAnnotation)")
    public void annotated() {
    }

    @Before("annotated()")
    public void test() {
        System.out.println(request.getHeader("authorization"));
    }
}

I also added to web.xml:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

This basically bypasses Jersey completely. This seems to work, I can now read out the Authorization header in the aspect. Great!

But, my question still stands: is there a way to inject Jersey's context objects into a Spring-managed aspect?

0

There are 0 best solutions below