I started out with AEM in 2013. On my first project, I remember having to do something with CORS headers. I remember doing it with a "whiteboard filter". At that time didn't have a good grasp on OSGi and Sling. I don't remember if the Granite CORS filter was around either. All I knew is that this type of filter let me bypass that pesky authentication on the author. In retrospect, not a good idea!
I moved on to the next project, but I never forgot that "whiteboard" thing. Until recently when I was doing research for my last post. I had to disambiguate between The Whiteboard Pattern and the HTTP Whiteboard Specification. As implemented by Apache Felix.
Explore the HTTP Service Console
Open up your local instance at http://localhost:4502/system/console/httpservice. It follows the pattern of listing out servlets, filters and listeners, by context. Each of these services has a rank, ensuring it runs ahead of the others. For example, the 'default' context ranks last.
There is the Sling context named org.apache.sling with one servlet. The Sling Engine Main Servlet and Sling Engine Servlet Context Helper are also open-source. As an AEM developer, this is the context you live in.
I also see that every context has the I18NFilter enabled. This is open-source and as you can see, it wraps the request. I bring this up because this filter will behave slightly differently based on the type of request and response. And that depends on our context. More on that later.
Create a New Project
It is not mandatory, you can fall back to adding properties to the @Component annotation,
Create a Context Helper
I am going to create a new class that extends the ServletContextHelper. I will not override anything. I am just creating it to show that our servlet and filter can work within multiple contexts.
You can find more info on Servlet contexts here.
Create a Servlet & Filter
You can find more info on registering servlets here.
You can find more info on registering filters here.
I could have used @HttpWhiteboardContextSelect("(osgi.http.whiteboard.context.name=*)") to register the servlet and filter will all the contexts. However, I wanted to be specific. I wanted to register it with mycontext and org.apache.sling. Refer to the filter syntax documentation.
Use Case 1: My Context & Servlet
Use curl to test MyServlet within MyContext
Use Case 2: Sling Context & My Servlet
Use curl to test MyServlet within the Sling Context
curl -u admin:admin -I http://localhost:4502/myservlet
Now that we are in the Sling context, we are subject to its authentication. Hence the -u admin:admin. Because MyFilter is in a different filter chain, it reports a different request type. MyServlet executes as before.
Use Case 3: Sling Context & Script Resolution
Use curl to test MyFilter within the normal sling context and script resolution
curl -u admin:admin -I http://localhost:4502/us/en.html
With the first 2 use cases, you may think to build microservices outside of Sling. One example is the System Ready/Alive servlets. It is within the org.osgi.service.http context. You might even try to adapt these enRoute tutorials to build JAX-RS microservices. But I would not recommend this. First, you should not be running anything else on the same Felix instance as AEM. Second, there are much cooler technology stacks on which to build microservices i.e. Adobe.IO.
The third use case will be the most useful. A filter can augment a response or wrap the request. Or stop the chain altogether. Without ever needing to fall into Sling, its authentication and resolution.