Well, a lot of loosely related words in a title. But this set makes sense. I got quite a headache when I tried to figure out all those components at once. As finally came out, it was probably just because of my lame knowledge of whole Servlet framework. Anyway, I would like to share few remarks which helped me to understand what is going on.
Disclaimer: sorry for the poor quality of this post. It was created primarily as a way to organize all pieces of information which I had and to help me understand the whole system.
So I have an application. Nothing fancy, few REST resources. It uses three first frameworks mentioned in the subject. I had a rough idea what does what, but I didn’t know demarcation lines, and when I had to plug in the last one it got a bit messy. Especially that lot of things in those frameworks are kind of hidden from the developer.
As I mentioned, the application consists few REST Resources served by jersey with use of Guice. But wait, Guice? It’s dependency injection framework, what the hell is it content part? The answer is, Guice is providing GuiceFilter, which, when placed on top of web.xml (or on top of other servlet filters configuration) will serve matching requests some injected content after you inject Guice’s ServletModule. The mentioned module is an alternative for web.xml. All further Filters and Servlets may be declared in code. For more information about that, I recommend reading https://github.com/google/guice/wiki/ServletModule
Okay, enough about Guice, what about Jetty? What it’s doing in this set? Jetty is lightweight, fast Java HTTP server. It can nicely be embedded into an application, what is beneficial for both clarity and complexity. For me, a little annoying thing when working with it was a fact that almost all of the webapp tutorials and issues on the internet are written in classical, deployable way, what makes a bit harder to find proper solutions quickly. Well, and here we have an example 🙂
What Jetty does in this setup is launching server itself and launching GuiceFilter. Note, that things that typically are done in ServletContextListener should be done in the application before server starting (what is obvious, but easy to overlook).
Next part of this puzzle is Jersey. Jersey is JAX-RS implementation. So, long story short, it provides REST part of an application: Resources, paths, available methods and finally also authorization. Especially last part is noteworthy because authentication is a task of HTTP Server (at least in last iteration of application I am writing).
And the latter is Shiro. It’s a new element in the application, and I want to fit it to allow seamless migration to other protocols. How should it be connected to other parts of the system? As it has excellent integration also with web containers, there is ShiroWebContainer which you can extend to get your configuration working. But here we have some problems: you cannot install Shiro module in Guice’s ServletModule. Why? Because when ServletModule is created directly (not via GuiceServletContextListener, what is a case when using standard webapp deployment pipeline), it doesn’t have access to ServletContext. It has getServletContext() method, but it always returns null. Well, aftermatch everything makes sense, but it was quite confusing for a while.
So the resolution is very easy: just put your Jetty server out of Guice’s tree. And from server handler get ServletContext – and use it as a parameter to main application injector creation. And that’s it – as simple as that. After setting up authorization part (this task was relegated from Jetty) you can change all annotations from Jersey’s to Shiro’s (this part was taken apart Jersey). And now migration to new protocol will be painless, at least in the security domain.