2

So I'm trying to do some benchmarking on Spring MVC (mainly just with REST controllers) without and container; just Spring and its request processing. With Jersey I am able to do something like this:

private volatile ApplicationHandler handler;
private volatile ContainerRequest request;

@Setup
public void start() throws Exception {
    handler = new ApplicationHandler(new JerseyAppConfig());
    request = ContainerRequestBuilder
            .from("/hello?test=HelloWorld", "GET")
            .build();
}

@Setup(Level.Iteration)
public void request() {
    request = ContainerRequestBuilder
            .from("/hello?test=HelloWorld", "GET")
            .build();
}

@Benchmark
public Future<ContainerResponse> measure() throws Exception {
    return handler.apply(request);
}

The ApplicationHandler is the main entry point into a Jersey request processing. All my Jersey configuration is in the JerseyConfig. Basically all that happens is that I create the request (ContainerRequest), then to process the request is just a matter of making a call on the handler, passing in the request. After the request goes through the request processing cycle, the response is returned.

I'm trying to mimic this same functionality with Spring MVC. Really I had no idea how I would even go about doing it. I just started throwing stuff against the wall hoping it would stick. I kinda had the idea that maybe I could do this with the DispatcherServlet (or more accurately the FrameworkSevlet). But in order to do it, the only way I could see was to make the protected processRequest accessible through reflection. Here's my attempt

private volatile AnnotationConfigWebApplicationContext appContext;
private volatile FrameworkServlet dispatcherServlet;
private volatile HttpServletRequest request;
private volatile HttpServletResponse response;
private volatile Method processRequest;

@Setup
public void start() throws Exception {
    appContext = new AnnotationConfigWebApplicationContext();
    appContext.register(SpringAppConfig.class);
    dispatcherServlet = new DispatcherServlet(appContext);

    processRequest = dispatcherServlet.getClass().getSuperclass()
            .getDeclaredMethod("processRequest",
                    HttpServletRequest.class,
                    HttpServletResponse.class);
    processRequest.setAccessible(true);
}

@Setup(Level.Iteration)
public void request() throws Exception {
    request = new MockHttpServletRequest("GET", "/hello");
    response = new MockHttpServletResponse();
}

@Benchmark
public void measure() throws Exception {
    processRequest.invoke(dispatcherServlet, request, response);
}

This isn't working though. I'm getting an NPE at this line, which I'm guessing means the webApplicationContext is null. But I am setting it above.

NPE or not, I am not even sure I am going about this the correct way; if there is some other component I should be looking into rather than the DispatcherServlet.

Anybody have any Idea how to make this work? Should I be looking into another component, calling a different method? Any configuration I might be missing to actually make my above attempt work?

Requirement stands

  • Use JMH
  • Test throughput of only Spring processing of request to response.

See complete runnable project on GitHub

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720

1 Answers1

1

You can take a look at test case for DispatcherServlet provided in the Spring framework code base here which can give you pointer on proper setup required and request/response mocks. Also you can have an example of proper setup here.

Community
  • 1
  • 1
Shailendra
  • 8,874
  • 2
  • 28
  • 37