Tomcat filter not being invoked for Atmosphere servlet

843 views Asked by At

I'm using Atmosphere 1.0.15 to handle push notifications under Tomcat and it's been been working fine for a few years now. Recently I added a simple filter to my Tomcat as a test, which (currently) just logs the incoming URL and continues. The problem is it the filter appears to simply not be invoked by Tomcat for any servlet path that is handled by my Atmosphere, yet the filter is invoked just fine for any other servlet path.

Here is the relevant portion of my web.xml:

<servlet>
    <description>AtmosphereServlet</description>
    <servlet-name>AtmosphereServlet</servlet-name>
    <servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
    <init-param>
        <param-name>org.atmosphere.atmosphereDotXml</param-name>
        <param-value>WEB-INF/config/atmosphere.xml</param-value>
    </init-param>
    <!-- Reduce memory usage by sharing ExecutorServices -->
    <init-param>
        <param-name>org.atmosphere.cpr.broadcaster.shareableThreadPool</param-name>
        <param-value>true</param-value>
    </init-param>
    <!-- Automatically free Broadcaster objects when the last client on the Broadcaster's channel disconnects -->
    <init-param>
        <param-name>org.atmosphere.cpr.broadcasterLifeCyclePolicy</param-name>
        <param-value>EMPTY_DESTROY</param-value>
    </init-param>
    <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>AtmosphereServlet</servlet-name>
    <url-pattern>/atmosphere/*</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>
        com.foobar.MyFilter
    </filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Here is my atmosphere.xml:

<atmosphere-handlers>
    <atmosphere-handler context-root="/atmosphere/client-notification"
                        class-name="com.foobar.MyClientNotificationAtmosphereHandler"
                        comet-support="org.atmosphere.container.Tomcat7CometSupport">
    </atmosphere-handler>
</atmosphere-handlers>

Here's the odd thing: if I hit any URL except for one under /atmosphere, my filter is invoked. For example, this works fine and my filter is invoked:

https://myserver:444/foo/bar

...however, for this URL (or any other URL under /atmosphere), my filter is not invoked for any of these:

https://myserver:444/atmosphere/client-notification
https://myserver:444/atmosphere 
https://myserver:444/atmosphere/foobar

My first thought was that the url-pattern was off, but it's set to "/*", and my filter is invoked for any other URLs besides those under /atmosphere. I also tried setting url-pattern explicitly:

<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/atmosphere/client-notification</url-pattern>
</filter-mapping>

...but still no dice. Am I missing something?? Is it possible for Atmosphere to prevent filters from running on it? As I understand it filters are always invoked before the servlet so the filter can "wrap" the call to it.

Any advice is much appreciated!

1

There are 1 answers

0
dbeachy1 On BEST ANSWER

So after a lot of digging around I figured out the issue: since the AtmosphereServlet class performs asynchronous I/O it implements the org.apache.catalina.comet.CometProcessor interface, and so Tomcat does not invoke the normal filter chain for it since it is an asynchronous servlet. Instead, my filter had to implement the CometFilter interface, which can process each Comet event as the long-running request remains active.

Once I figured out that CometProcessor was the culprit I found a similar SO post here: How do I get the requests for a servlet implementing CometProcessor interface to pass through a filter