How can I define a global servlet filter for all WEB applications deployed in EAP 6/7?
Environment
- Red Hat JBoss Enterprise Application Platform (EAP)
- 8.x
- 7.x
- 6.x
Issue
- We created several servlet filters using the
@WebFilterannotation and made it available in a global module in EAP 6, however, it's not getting invoked when accessing the mapped context. - We added a global filter to deployers/jbossweb.deployer/web.xml in EAP 5. How to add a global filter to EAP 6 ?
Resolution
EAP 8 / 7 / EAP 6.3+
EAP 7+ / 6.3+ has a Content from issues.jboss.org is not included.feature to use annotated servlet filters defined in shared modules without defining them explicitly in your web.xml.
An example filter that uses the annotation @WebFilter can be packaged in a jar and added a JBoss Module
@WebFilter(filterName = "ExampleFilter",
urlPatterns = {"/*"},
initParams = {}
)
public class ExampleFilter implements Filter {
...
In this example, the @WebFilter class is packaged in a jar and put into a custom JBoss Module named globalfilter and then the globalfilter module can be added as a global module with annotations=true, which will allow all deployments to see the classes in the globalfilter module and also see the annotations, which will cause the filter to be registered with all applications.
[standalone@embedded /] /subsystem=ee:write-attribute(name=global-modules,value=[{name=globalfilter,annotations=true}])
The resulting xml from the CLI command would look like:
<subsystem xmlns="urn:jboss:domain:ee:4.0">
<global-modules>
<module name="globalfilter" annotations="true"/>
</global-modules>
Prior to EAP 6.3
Prior to EAP 6.3 there are two workarounds to use servlet filters defined in shared modules.
Define servlet filter in your web.xml
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<filter>
<filter-name>GlobalFilter</filter-name>
<filter-class>com.example.FilterClassInGlobalModule</filter-class>
</filter>
<filter-mapping>
<filter-name>GlobalFilter</filter-name>
<url-pattern>/context/*</url-pattern>
</filter-mapping>
</web-app>
Use
ServletContainerInitializer
See complete working example attached to this article. The following are the steps involved to get this working:
-
Implement a
ServletContainerInitializeras the example below:package com.redhat.gss; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletException; import javax.servlet.ServletContext; import javax.servlet.FilterRegistration; public class ServletFilterConfigurator implements ServletContainerInitializer { public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException { FilterRegistration fReg = ctx.addFilter("myGlobalFilter", com.myapp.MyGlobalFilter.class); fReg.addMappingForUrlPatterns(null, true, "/*"); } } -
Note that could be expanded to add a global servlet event listener as well:
ctx.addListener(com.myapp.MyGlobalListener.class); -
There is a
META-INF/services/javax.servlet.ServletContainerInitializerin the jar that initialize theServletFilterConfiguratorclass. The contents of this file is merely one line:com.redhat.gss.ServletFilterConfigurator -
Add the jar as a static module named e.g.
globalfilter:module add --name=globalfilter --resources=/path/to/SCI.jar --dependencies=sun.jdk,javax.servlet.api -
Add the module as global in
eesubsystem:
[standalone@embedded /] /subsystem=ee:write-attribute(name=global-modules,value=[{name=globalfilter,services=import}])
<subsystem xmlns="urn:jboss:domain:ee:1.1">
<global-modules>
<module name="globalfilter" slot="main" services="import"/>
</global-modules>
...
</subsystem>
Use a Global Valve / Handler
- EAP 7: A HttpHandler can be used instead of a Filter. This article describes how to configure a
Global Undertow HttpHandler: How to create an Undertow Handler in JBoss EAP 7. - EAP 6: A Valve can be used instead of a Filter. This article describes how to configure a
Global Valve: How to enable valve in JBoss EAP 6.
Root Cause
The Content from download.oracle.com is not included.Servlet 3.0 specification says that filter class should be packaged in the Web Archive.
Quote of the 6.2 specification's section regarding web filters:
The application developer creates a filter by implementing the javax.servlet.Filter interface and providing a public constructor taking no arguments. The class is packaged in the Web Archive along with the static content and servlets that make up the Web application.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.