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

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

    alehoss

      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...

        • 1. Re: Identify PathParam inside an Undertow filter when the response entity is a String
          ctomc

          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.

          This because your filter executes much much earlier in request lifecycle than when RestEasy kicks in.

          • 2. Re: Identify PathParam inside an Undertow filter when the response entity is a String
            alehoss

            Tomaz Cerar escreveu:

            This because your filter executes much much earlier in request lifecycle than when RestEasy kicks in.

            Thanks Tomaz,

             

            Actually, it executes after Resteasy (the Handler executes earlier and adds an ExchangeCompleteListener, that executes after (or in between) resteasy.

            The problem is... When the response entity is a String, the ResteasyUriInfo is cleared before hit this ExchangeCompleteListener.

             

            But why it works with response types other than String? Shouldn't the lifecycle be the same?