Sharing data between JAX-RS filters

This is a quick post which points out how to share contextual user-defined (custom) data between JAX-RS filters

Filter execution

  • It is chain based: one filter gets executed after another
  • Request filters are executed before Response filters
  • If a filter throws an exception, the chain breaks and other filters are skipped i.e. an exception from a Request filter will auto-abort all other Request filters. The same is applicable to Response filters

For more info, please do check out one of my existing blog posts which discussed JAX-RS server side processing pipeline in depth

Sharing data b/w filters

JAX-RS API enables sharing of user-defined data amongst filters associated with a particular request

  • It is abstracted in the form of a Map<String,Object> (pretty natural choice) via the ContainerRequestContext interface
  • Get all the custom properties using the getPropertyNames() method
  • The value of a specific property can be fetched (from the Map) using getProperty(String name)
  • Overwrite an existing property or a add a new one using setProperty(String name, Object val)

Examples

Here is how multiple Request filters can share user-defined contextual data amongst themselves

public class ReqFilter_1 implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext cReqCtx) throws IOException {
cReqCtx.setProperty("prop1", "value1");
}
}
public class ReqFilter_2 implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext cReqCtx) throws IOException {
String val1 = (String) cReqCtx.getProperty("prop1");
cReqCtx.setProperty("prop1", "value1");
cReqCtx.setProperty("prop2", "value2");
}
}
public class ReqFilter_3 implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext cReqCtx) throws IOException {
String val1 = (String) cReqCtx.getProperty("prop1");
String val2 = (String) cReqCtx.getProperty("prop2");
Collection<String> customProperties = cReqCtx.getPropertyNames();
}
}

Another example where a Response filter uses the contextual data set by a Request filter

@Priority(Priorities.AUTHENTICATION)
public class ReqFilter_1 implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext cReqCtx) throws IOException {
cReqCtx.setProperty("random-token", "token-007"); //generated and used internally
}
}
public class ResponseFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext cReqCtx, ContainerResponseContext cRespCtx) throws IOException {
String responseToken = (String) cReqCtx.getProperty("random-token"); //get the property
if(responseToken!=null){
cRespCtx.getHeaders.put("random-token-header" , responseToken); //set it to HTTP response header
}
}
}

To be noted…

The same capability is available in the Client side JAX-RS filters as well. The only difference is that you would be interacting with an instance of the ClientRequestContext

Further reading

Cheers !

About Abhishek

Loves Go, NoSQL DBs and messaging systems
This entry was posted in Java EE and tagged , , , . Bookmark the permalink.

4 Responses to Sharing data between JAX-RS filters

  1. Tushar Goel says:

    HI Abhishek, thanks for the article. You have written 3 filter classes and in 2 of them you set some value and in 3rd one you get some value. You have also mentioned that filters are also working in a chain but i am unable to understand that how does JAX-RS know which filter to be executed first. You can have chaining start from any filter. But in your example, it should started from 1, 2 and 3. Could you plz explain?

    Like

  2. Pingback: JSON Web Token in action with JAX-RS | Thinking in Java EE (at least trying to!)

  3. Pingback: JSON Web Token in Action with JAX-RS | Voxxed

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s