2 Replies Latest reply on May 22, 2017 9:32 AM by Alessandro Hoss

    Identify PathParam inside an Undertow filter when the response entity is a String

    Alessandro Hoss Newbie

      I've already posted this on stackoverflow (Identify PathParam inside an Undertow filter... ), but maybe here is more apropriate:

       

      I need to identify @PathParam from a request inside an undertow filter to ignore them (metrics purpose)

      My filter looks like this:

      public class MetricsHandler implements HttpHandler {  private HttpHandler next;  public MetricsHandler(HttpHandler next) { this.next = next; }  @Override public void handleRequest(HttpServerExchange exchange) throws Exception { MetricsListener listener = new MetricsListener(); exchange.addExchangeCompleteListener(listener); next.handleRequest(exchange); }  private class MetricsListener implements ExchangeCompletionListener { @Override public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) { try { String metric = exchange.getRequestURI(); UriInfo uriInfo = ResteasyProviderFactory.getContextData(UriInfo.class); /* * When the response entity is a String, this UriInfo is null at this point. If it's another type, the UriInfo is ok and i'm able to identify path parameters ... */ if(uriInfo != null) { Collection<List<String>> pathParametersValues = uriInfo.getPathParameters(false).values(); for (List<String> list : pathParametersValues) { for (String pathParameter : list) { metric = metric.replace("/"+pathParameter, ""); } } }  Metrics.increment(metric); } finally { if (nextListener != null) { nextListener.proceed(); } } } } }

      This filter is packaged as a wildfly module and configured in domain.xml (Wildfly 10.1.0), inside the undertow subsystem, as follows:

              <subsystem xmlns="urn:jboss:domain:undertow:3.1"> <buffer-cache name="default"/> <server name="default-server"> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content"/> <filter-ref name="metricsFilter" /> </host> </server> <servlet-container name="default"> <jsp-config/> <websockets/> </servlet-container> <filters> <filter class-name="com.metrics.filter.MetricsHandler" module="com.metrics" name="metricsFilter"/> </filters> </subsystem>

      And here are my REST methods:

      @GET @Path("/path/num/{id}") @Produces(MediaType.APPLICATION_JSON) public Response pathNum(@PathParam("id") String id) { return Response.ok(123).build(); }  @GET @Path("/path/string/{id}") @Produces(MediaType.APPLICATION_JSON) public Response pathString(@PathParam("id") String id) { return Response.ok("abc").build(); }

      I'm able to identify the "id" path parameter when requesting for pathNum method, but I'm not for the pathString one. As of the code comment, calling ResteasyProviderFactory.getContextData(UriInfo.class) returns null for the pathString method.

      I've tested this behavior against resteasy 3.0.19.Final, 3.0.20.Final and 3.0.22.Final, all with the same results.

      Debugging resteasy I found that, when the response entity is Integer or another type, the MessageBodyWriter is ResteasyJackson2Provider (my rest @Produces json), and SynchronousDispatcher.clearContextData is called only after my filter's ExchangeCompletionListener.exchangeEvent.

      BUT, when the response entity is a String, the MessageBodyWriter is a StringTextStar and the clearContextData is called after the MessageBodyWriter and before my ExchangeCompletionListener, so there is no more contextData to look.

      I don't know if I'm doing something wrong or if this is a possible bug on resteasy, or on wildfly...