4

We used org.glassfish.jersey.server.model.ResourceMethod$Builder

to register the method and the handler.

ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod(httpMethod);
methodBuilder.produces(restContext.getProduceContent()).handledBy(inflector);
methodBuilder.consumes(restContext.getConsumeContent()).handledBy(inflector);

The handler class implements the org.glassfish.jersey.process.Inflector<ContainerRequestContext, Response>

public class CommonMethodInflector implements Inflector<ContainerRequestContext, Response>
{
 @Override
    public Response apply(ContainerRequestContext request)
    {
      //sync bloc
      //using resqest object we do processing in different maner
        incRestFeRequestCounters(request.getMethod());
        Response response = processIncoming(request);`enter code here`
     }
}

Could you please help us in creating the async handler.

our requirement in short:

  1. At runtime only we know the http method and other resources to register. So, we can not use annotations for resource & httpMethod registration. We need only programmatic resource registration.

  2. In handler We need the request object so that we can access what method and what json body in it.

  3. we need to make the async response as we are doing huge operation in the processing request.

Cœur
  • 37,241
  • 25
  • 195
  • 267

1 Answers1

6

The first thing you need to do is to suspend the resource method:

ResourceMethod.Builder methodBuilder = resourceBuilder.addMethod(httpMethod)
    .suspend(AsyncResponse.NO_TIMEOUT, TimeUnit.Seconds);

Then you have few choices how to process the request in async mode:

"Arbitrary" handler class

builder.addMethod("GET")
        // Suspend without time limit.
        .suspended(AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS)
        .handledBy(MyHandler.class, MyHandler.class.getMethod("handle", AsyncResponse.class));

and

public class MyHandler {

    public void handle(final @Suspended AsyncResponse response) {
        Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                // Simulate long-running operation.
                try {
                    Thread.sleep(1000);
                } catch (final InterruptedException ie) {
                    // NOOP
                }

                response.resume("Hello World!");
            }
        });
    }
}

Inflector class

Resource.builder("helloworld")
        .addMethod("GET")
        // Suspend without time limit.
        .suspended(AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS)
        // Can be registered only as a class otherwise the
        // @Context injection would be out of request scope.
        .handledBy(MyAsyncInflector.class);

and

public class MyAsyncInflector implements Inflector<ContainerRequestContext, Response> {

    @Context
    private AsyncResponse response;

    @Override
    public Response apply(final ContainerRequestContext context) {
        Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                // Simulate long-running operation.
                try {
                    Thread.sleep(1000);
                } catch (final InterruptedException ie) {
                    // NOOP
                }

                response.resume("Hello World!");
            }
        });

        return null;
    }
}

Annonymous Inflector

Resource.builder("helloworld")
        .addMethod("GET")
        // Suspend without time limit.
        .suspended(AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS)
        .handledBy(new Inflector<ContainerRequestContext, Response>() {

            @Inject
            private javax.inject.Provider<AsyncResponse> responseProvider;

            @Override
            public Response apply(final ContainerRequestContext context) {
                // Make sure we're in request scope.
                final AsyncResponse response = responseProvider.get();

                Executors.newSingleThreadExecutor().submit(new Runnable() {
                    @Override
                    public void run() {
                        // Simulate long-running operation.
                        try {
                            Thread.sleep(1000);
                        } catch (final InterruptedException ie) {
                            // NOOP
                        }

                        response.resume("Hello World!");
                    }
                });

                return null;
            }
        });
Michal Gajdos
  • 10,339
  • 2
  • 43
  • 42
  • We are thinking about this asynchronous solution to increase our system tps(transaction per second). If I use Executors.newSingleThreadExecutor() then I guess it will become bottle neck. could you please suggest us to make it multi threaded. also I could see the @Context private AsyncResponse response; is instance level attribute , It fails in multi threaded environment. Thanks and Regards Venu – Komanduri Venugopalacharyulu Jul 31 '15 at 11:59
  • well can some one post an example where instead of providing Inflector class an inflector instance is provided, will the @context annotation work correctly and thus AsyncResponse be injected? this is the piece of code i am specifically talking about .suspended(AsyncResponse.NO_TIMEOUT, TimeUnit.SECONDS) // Can be registered only as a class otherwise the // Context injection would be out of request scope. .handledBy(MyAsyncInflector.class); //can it be new MyInflectorClass() – JayD Jan 01 '21 at 10:41