2

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?

  • 1
    `SecurityContextHolder.getContext().getAuthentication()` gives access to the `Authentication` object . Is this what you are looking for ? [SecurityContextHolder](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/core/context/SecurityContextHolder.html) associates a given SecurityContext with the current execution thread. – R.G May 12 '20 at 15:05
  • I am not using the `spring-security` project, so I cannot use `SecurityContextHolder`. My question is not necessarily about just accessing the `Authorization` header (which I guess `SecurityContextHolder` does), but rather about getting access to the Jersey contextual objects in the aspect implementation. Keep in mind I am using Jersey/JAX-RS (and not Spring MVC). –  May 12 '20 at 15:47
  • Oh ok , I understand .With pure `aspectj` it should be possible. If you wish you may add the tag to get the right attention. Also a [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) would help the experts who are not spring devs to help you out. – R.G May 12 '20 at 15:56
  • 2
    Thanks for the tip! I added the `aspectj` tag to my question. I also added a minimal example which demonstrates my question. See update of my question, at the very bottom. –  May 12 '20 at 16:39
  • 2
    I also added a working solution which bypasses Jersey. I am still curious if it's possible to autowire Jersey's objects into Spring's beans. –  May 12 '20 at 21:05
  • Any solution to this? – Luiz Apr 12 '21 at 01:30

0 Answers0