0
votes

I want to generate event on start and end of the method to log time stamp for QOS & instrumentation purpose. In spring framework that it is easy to achieve using AOP without writing boiler plate code in each of the methods.

I want to do similar in play. I looked in action & @with annotation however it is not giving desired result.

What is best way to log event & time stamp on start (before) and on completion (after) method?

Below is my action class:

import play.libs.F.Promise;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.SimpleResult;

public class PublishEventAction extends Action<PublishEvent> {

    @Override
    public Promise<SimpleResult> call(Http.Context context) throws Throwable
    {


        try { 
            before(context); 
            Promise<SimpleResult> result = delegate.call(context); // This part calls your real action method 
            after(context); 
            return result; 
          } catch (RuntimeException e) { 
            throw e; 
          } catch (Throwable t) { 
            throw new RuntimeException(t); 
          } 


    }

    private void before(Http.Context context) { 
        // Do the before things here

        System.out.println("Before: " + context.request().path()+context.toString()+"current time : "+System.currentTimeMillis());
      } 

      private void after(Http.Context context) { 
        // Do the after things here
          System.out.println("After: " + context.request().path()+context.toString()+"current time : "+System.currentTimeMillis());
      } 

}

Thanks in advance!

4

4 Answers

1
votes

You can intercept before and after the request like shown below and log all your requests:

public Action onRequest(final Http.Request request, Method method) {

    Action action =  new Action.Simple() {
        public Promise<Result> call(Http.Context ctx) throws Throwable {
            Long start = System.currentTimeMillis();
            Promise<Result> result = delegate.call(ctx);

            //This part is not executed immediately
            Long finish = System.currentTimeMillis();
            Logger.info("method=" + request.method() + " uri=" + request.uri() + " remote-address=" + request.remoteAddress() + " time=" + (finish-start));

            return result;
        }
    };
    return action;
}
0
votes

You can define an action composition. In the play documentation is explained how to execute any code BEFORE the action is fired. But you can also use for AFTER like described in Google Groups.

0
votes

You can create a Global class extending GlobalSettings at the root of your "app" package and intercept every request:

public class Global extends GlobalSettings {

public Action onRequest(Request request, Method actionMethod) {
    Logger.debug("Request starts:" + request.toString());
    Action action = super.onRequest(request, actionMethod);
    Logger.debug("Request ends.");

    return action;
}

}

0
votes

As has been mentioned you want to extend the Global Settings object.

Play's documentation is solid: Application Global Settings and Intercepting Requests

import play.*;
import play.mvc.Action;
import play.mvc.Http.Request;
import java.lang.reflect.Method;

public class Global extends GlobalSettings {

    public Action onRequest(Request request, Method actionMethod) {
        System.out.println("before each request..." + request.toString());
        return super.onRequest(request, actionMethod);
    }

}

The documentation explains that if you want to intercept a specific action, you can do so with action composition.