Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Hystrix Java Servlet & Servlet Filter in Jersey 2

I'm using Netflix' Hystrix libraries to act as a circuit breaker when connecting to remote services in a REST client I am building. I would like to setup the event streaming and dashboard monitoring via the libraries they provide. Looking at their example application here, it appears that I need to apply their servlet filters and servlet classes to my web application.

I'm using Spring Boot with Jersey 2 and wiring up my resources and filters in a JerseyConfig.java (no web.xml). I know that Jersey Filters are not the same as Servlet Filters and am struggling to integrate the two together.

So, how do you take a Java Servlet Filter and make it work as a Jersey Filter and how do you take a Java Servlet and make it work as a Jersey Resource?

My current strategy for the Servlets is to wrap them like so. One for each.

@Path("/hystrix.stream")
public class HystrixResource extends HystrixUtilizationSseServlet {

    @Context
    HttpServletRequest httpRequest;

    @Context
    HttpServletResponse httpResponse;

    //This returns void because it is a text/stream output that must remain open, 
    //so the httpResponse is continually written to until the conenction is closed
    @GET
    public void doGet() throws ServletException, IOException {
        doGet(httpRequest, httpResponse);
    }
}

This might be working, but the data is basically empty for some reason. I am guessing that reason is because the Filters are not working.

data: {"type":"HystrixUtilization","commands":{},"threadpools":{}}

It is less clear to me how to wrap the Servlet Filters because they expect different inputs and outputs than a Jersey ContainerRequestFilter. The following implementation in my JerseyConfig seems to do nothing because the logs are not indicating that the filters are being registered and I cannot break on lines in these files in debug mode.

@Component
@ApplicationPath("/")
public class JerseyConfig extends ResourceConfig {
    private static final Logger LOGGER = Logger.getLogger("JerseyConfig");
    public JerseyConfig(){
        //filter to provide a bridge between JAX-RS and Spring request attributes
        register(RequestContextFilter.class);
        register(SpringComponentProvider.class);
        //handles custom serialization
        register(new ObjectMapperContextResolver());
        //try to register the filters - which doesn't work because these aren't Jersey Filters
        register(HystrixRequestContextServletFilter.class);
        register(HystrixRequestLogViaResponseHeaderServletFilter.class);
        registerResources();

        /*
         * Enable the logging filter to see the HTTP response for each request.
         */
        register(new LoggingFilter(LOGGER, true));
    }
}
like image 321
th3morg Avatar asked May 22 '26 19:05

th3morg


1 Answers

Servlets and Servlet filters should not be registered in the Jersey config. They will simply be ignored. You should instead be registering them with Spring Boot with ServletRegistrationBeans and FilterRegistrationBeans.

In you Spring configuration, you can do something like

@Bean
public ServletRegistrationBean someServlet() {
    ServletRegistrationBean registration = ServletRegisrationBean(
            new HystrixMetricsStreamServlet(), "/hystrix.stream");
    registration.setName("HystrixMetricsStreamServlet");
    return registration;
}

@Bean
public FilterRegistrationBean someFilter() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new HystrixRequestContextServletFilter());
    registration.setUrlPatterns(Arrays.asList("/*"));
    registration.setName("HystrixRequestContextServletFilter");
    // you can also set the order of filters if you need to 
    return registration;
}

Also:

  • you don't need to register the SpringComponentProvider. This is automatically registered.
  • If you get a 404 on trying to access the servlet being registered this way, it will be because you are using the default Jersey mapping /*, which hogs up all the request. You can change the mapping or register Jersey as a filter to forward not found requests. See this post
like image 121
Paul Samsotha Avatar answered May 24 '26 12:05

Paul Samsotha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!