To apply a logic globally before hitting the resource, an implementation of ContainerRequestFilter could be used.

Configuration
Java Compilation:
Java Runtime:
Web Server:
Maven:
Java Compilation:
Java Runtime:
Web Server:
Gradle:
JDK 11.0.12
JRE HotSpot 11.0.12
Tomcat 9.0.58
Maven 3.8.4
JDK 11.0.12
JRE HotSpot 11.0.12
Tomcat 9.0.58
Gradle 7.4.2
To apply a logic globally before hitting the resource, an implementation of ContainerRequestFilter could be used
Create the following folder structure:
folder structure of Jersey web service with Container Request Filter
pom.xml: (if using Gradle, replace pom.xml with build.gradle)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.maxjava</groupId> <artifactId>JerseyMessageBodyReaderWriter</artifactId> <version>1.0</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet-core</artifactId> <version>2.29.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>2.29.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> </plugins> </build> </project>
plugins { id 'java' id 'war' } sourceCompatibility = 11 targetCompatibility = 11 group 'net.maxjava' version '1.0' repositories { mavenCentral() } dependencies { implementation group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: '2.29.1' implementation group: 'org.glassfish.jersey.inject', name: 'jersey-hk2', version: '2.29.1' }
Some notes about pom.xml:
  • jersey-container-servlet-core and jersey-hk2 is needed for using Jersey as servlet
  • maven-compiler-plugin is for compiling the code using source version 11 and target version 11
  • A war artifact will be created for deployment to servlet containers
Some notes about gradle.build:
  • jersey-container-servlet-core and jersey-hk2 is needed for using Jersey as servlet
  • targetCompatibility is used to configure compilation with source version 11 and target version 11
  • A war artifact will be created for deployment to servlet containers
web.xml:
<web-app> <display-name>Jersey Web Service with Container Request Filter</display-name> <servlet> <servlet-name>JerseyWebServiceContainerFilter</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>application.MyApplication</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>JerseyWebServiceContainerFilter</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
MyApplication.java:
package application; import filter.MyAuthenticationFilter; import org.glassfish.jersey.server.ResourceConfig; import resource.MyResource; public class MyApplication extends ResourceConfig { public MyApplication() { register(MyResource.class); register(MyAuthenticationFilter.class); } }
Some notes about MyApplication.java:
  • This is main configuration class and has to be specified in web.xml
  • In the constructor, register the resource classes, which are annotated with JAX-RS for web services, and register the MyAuthenticationFilter class for request filtering
MyResource.java:
package resource; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.Calendar; @Path("/myapp") public class MyResource { @GET @Path("/currentTime") @Produces(MediaType.TEXT_PLAIN) public Response getCurrentTime() { return Response.ok("now: " + Calendar.getInstance().getTime().toString()).status(Response.Status.OK).build(); } }
Some notes about MyResource.java:
  • Provide a simple API to return the current time
MyAuthenticationFilter.java:
package filter; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.PreMatching; import javax.ws.rs.core.Response; import java.util.Base64; @PreMatching public class MyAuthenticationFilter implements ContainerRequestFilter { private static String USERNAME = "myusername"; private static String PASSWORD = "mypassword"; private static String encodedUsernamePassword = Base64.getEncoder().encodeToString((USERNAME + ":" + PASSWORD).getBytes()); @Override public void filter(ContainerRequestContext requestContext) { System.out.println("AuthenticationFilter"); String authorizationHeaderValue = requestContext.getHeaderString("Authorization"); String authorizationValue = authorizationHeaderValue != null ? authorizationHeaderValue.substring(6) : null; if (!encodedUsernamePassword.equals(authorizationValue)) { requestContext.abortWith(Response.ok("Incorrect username or password.").status(401).build()); } } }
Some notes about MyAuthenticationFilter.java:
  • Override filter to apply business logic before a request is served in any resource
  • The logic here is to check if the header has Basic Authorization with "myusername" and "mypassword"
  • @PreMatching for the filter to be executed before the resource matching process
Sample output:
curl --request GET 'http://localhost:8080/JerseyContainerFilter-1.0/myapp/currentTime'
Response:
Incorrect username or password.
curl --header 'Authorization: Basic bXl1c2VybmFtZTpteXBhc3N3b3Jk' --request GET 'http://localhost:8080/JerseyContainerFilter-1.0/myapp/currentTime'
Response:
now: Wed Oct 12 17:11:55 PDT 2022