5

I'm using the latest Spring Data Rest and I'm handling the event "before create". The requirement I have is to capture also the HTTP Headers submitted to the POST endpoint for the model "Client". However, the interface for the RepositoryEventHandler does not expose that.

@Component
@RepositoryEventHandler
public class ClientEventHandler {

  @Autowired
  private ClientService clientService;

  @HandleBeforeCreate
  public void handleClientSave(Client client) {
    ...
    ...
  }
}

How can we handle events and capture the HTTP Headers? I'd like to have access to the parameter like Spring MVC that uses the @RequestHeader HttpHeaders headers.

Marcello DeSales
  • 21,361
  • 14
  • 77
  • 80
  • I haven't tested but can you `@Autowired` the `HttpServletRequest ` directly like `@Autowired private HttpServletRequest request;` then use `request.getHeader("user-agent")` .Can you pls check example here https://www.mkyong.com/java/how-to-get-http-request-header-in-java/ – Navoneel Talukdar Dec 22 '16 at 08:14
  • HttpServletRequest is not a Spring managed bean so cannot be autowired. – Alan Hay Dec 22 '16 at 09:30
  • Without a custom controller one idea would be a Servlet filter that binds the required values to the current Thread using a ThreadLocal and makes them available via a static call. See for example http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/ or http://blog.smartbear.com/programming/how-and-when-to-use-javas-threadlocal-object/ – Alan Hay Dec 22 '16 at 09:35
  • @AlanHay yes the request can be autowired. – Jens Schauder Dec 22 '16 at 11:51

1 Answers1

7

You can simply autowire the request to a field of your EventHandler

@Component
@RepositoryEventHandler
public class ClientEventHandler {
    private  HttpServletRequest request;

    public ClientEventHandler(HttpServletRequest request) {
        this.request = request;
    }

    @HandleBeforeCreate
    public void handleClientSave(Client client) {
        System.out.println("handling events like a pro");
        Enumeration<String> names = request.getHeaderNames();
        while (names.hasMoreElements())
            System.out.println(names.nextElement());
    }
}

In the code given I used Constructor Injection, which I think is the cleanest, but Field or Setter injection should work just as well.

I actually found the solution on stackoverflow: Spring: how do I inject an HttpServletRequest into a request-scoped bean?

Oh, and I just noticed @Marc proposed this in thecomments ... but I actually tried it :)

Community
  • 1
  • 1
Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
  • You forgot to add `@Autowired` – Navoneel Talukdar Dec 22 '16 at 14:03
  • 1
    It's not necessary if there is a single constructor – Jens Schauder Dec 22 '16 at 14:18
  • 3
    One may ask himself (I did) how it is possible that the injected `HttpServletRequest` actually references the current request although the `ClientEventHandler` class is a `@Component` (and thus a singleton). Well, when a scoped bean (e.g. request-scoped like `HttpServletRequest`) is injected into a bean of a longer-lived scope (like `@Component`) then in fact an AOP proxy is injected in place of the bean. The proxy then dispatches calls to the actual bean instance in the current scope. – jannis Dec 22 '16 at 21:13
  • 1
    [Reference](http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/beans.html#beans-factory-scopes-other-injection) – jannis Dec 22 '16 at 21:13