0

I need to make a WS petition when I start play so I can log in a external service to obtain a token. I need that token for make future petitions. I know how to make WS petitions, I don't know where to place that code to execute on start. At this time, it is in a function of a controller.

If you want some code of this:

// login data
  ObjectNode tvdbaccount = Json.newObject();
  tvdbaccount.put("apikey", "*****");
  tvdbaccount.put("username", "*****");
  tvdbaccount.put("userkey", "*****");

  // try to login
  String token = "";
  CompletionStage<JsonNode> request = WS.url("https://api.thetvdb.com/login")
                                        .post(tvdbaccount)
                                        .thenApply(WSResponse::asJson);

  try {
    JsonNode response = request.toCompletableFuture()
                               .get(5, TimeUnit.SECONDS);

    token = response.get("token").asText();
  } catch (Exception ex) {
    System.out.println(ex.getMessage());
  }

That token expires after 24 hours so I want for example to call a function every 12 hours that refreshes that token. That function is similar to the previous one, it's only a WS petition.

I'm using playframework 2.5 where GlobalSettings is deprecated and I see multiple answers not very clear for 2.5 so I fail to get it done.

rcanovas
  • 318
  • 2
  • 9
  • Added code to show what i'm doing – rcanovas Oct 27 '16 at 19:11
  • You might want to have a look at: https://stackoverflow.com/questions/31007478/was-asynchronous-jobs-removed-from-the-play-framework-what-is-a-better-alternat/31019858#31019858 Should be the same for play 2.5, Eager Singletons would be what you want to use for start up instead of deprecated GlobalSettings. See migration guide as well: https://www.playframework.com/documentation/2.5.x/GlobalSettings#Java – Alexander B Oct 28 '16 at 07:08
  • For repeating the task to fetch the token you can create an actor in the eager binding on startup that is called every 12 hours following the docs at https://www.playframework.com/documentation/2.5.x/JavaAkka#Scheduling-asynchronous-tasks for periodically executed tasks. – Alexander B Oct 28 '16 at 07:17
  • Thank you, if I get something consistent, I will post it as a response – rcanovas Oct 28 '16 at 13:41

1 Answers1

1

Thanks to Alexander B, I've been able to get what I wanted.

Eager Singleton

I resolved the on start function call with the eager singleton.

What I've done is a class for the TVDB things and the important part is to write what you want to do on start inside the constructor of this class. And then to bind it on a module:

bind(TVDB.class).asEagerSingleton();

Akka actors

For the periodically function call I used an Akka actor.

I've implemented an actor which calls itself every 12 hours, so I placed the scheduling code in the same actor on the preStart void. I think the Playframework documentation for the Scheduling asynchronous tasks isn't updated and doesn't work the way it is (at least for me).

Then, I binded it on the module:

bindActor(TVDBActor.class, "TVDBActor");

If someone need the actor code here it is:

public class TVDBActor extends UntypedActor {

  @Inject
  public void preStart(final ActorSystem system, @Named("TVDBActor") ActorRef tvdbActor) {
    system.scheduler().schedule(
      Duration.create(12, TimeUnit.HOURS),
      Duration.create(12, TimeUnit.HOURS),
      tvdbActor,
      "tick",
      system.dispatcher(),
      null
    );
  }

  @Override
  public void onReceive(Object msg) throws Exception {
    TVDB.refreshToken();
  }

}
rcanovas
  • 318
  • 2
  • 9