private Future<Recommendation> getDestinationWithReccomendation(Destination destination) { ActorRef pricingActor = SpringAppContext.actorSystem().actorOf(Props.create(PriceCalculationActor.class)); ActorRef foreCastActor = SpringAppContext.actorSystem().actorOf(Props.create(WeatherForecastActor.class)); final Future<Calculation> calculationFuture = toPrice( Patterns.ask( pricingActor, new PriceRequest("moon", destination.getDestination()), new Timeout(Duration.create(5, TimeUnit.SECONDS)))); final Future<Forecast> forecastFuture = toForecast( Patterns.ask( foreCastActor, new WeatherRequest(destination.getDestination()), new Timeout(Duration.create(5, TimeUnit.SECONDS)))); return calculationFuture .zip(forecastFuture) .map( new Mapper<Tuple2<Calculation, Forecast>, Recommendation>() { @Override public Recommendation apply(Tuple2<Calculation, Forecast> tuple) { return new Recommendation( destination.getDestination(), tuple._2().getForecast(), tuple._1().getPrice()); } }, SpringAppContext.actorSystem().dispatcher()); }
private Future<List<Destination>> toVisits(Future<Object> visits) { return visits.map( new Mapper<Object, List<Destination>>() { public List<Destination> apply(Object result) { ResponseVisit visits = (ResponseVisit) result; return visits.getVisitedDestination(); } }, SpringAppContext.actorSystem().dispatcher()); }
private Future<List<Destination>> toDestinations(Future<Object> recommendations) { return recommendations.map( new Mapper<Object, List<Destination>>() { public List<Destination> apply(Object result) { RecommendationResponse response = (RecommendationResponse) result; return response.getRecommendDestination(); } }, SpringAppContext.actorSystem().dispatcher()); }
private Future<Forecast> toForecast(Future<Object> futureResponse) { return futureResponse.map( new Mapper<Object, Forecast>() { public Forecast apply(Object result) { WeatherResponse weather = (WeatherResponse) result; return weather.getForecast(); } }, SpringAppContext.actorSystem().dispatcher()); }
private Future<Calculation> toPrice(Future<Object> futureResponse) { return futureResponse.map( new Mapper<Object, Calculation>() { public Calculation apply(Object result) { PriceResponse price = (PriceResponse) result; return price.getPrice(); } }, SpringAppContext.actorSystem().dispatcher()); }
private Future<AgentResponse> toAgentResponse( Future<List<Destination>> visitedFutures, Future<Iterable<Recommendation>> reccomendationsFuture) { return visitedFutures .zip(reccomendationsFuture) .map( new Mapper<Tuple2<List<Destination>, Iterable<Recommendation>>, AgentResponse>() { @Override public AgentResponse apply( Tuple2<List<Destination>, Iterable<Recommendation>> tuple) { return new AgentResponse(tuple._1(), toList(tuple._2())); } }, SpringAppContext.actorSystem().dispatcher()); }
private Future<Iterable<Recommendation>> toTravelRecommendationWithInfo( Future<List<Destination>> destinationsFutures) { return destinationsFutures.flatMap( new Mapper<List<Destination>, Future<Iterable<Recommendation>>>() { @Override public Future<Iterable<Recommendation>> apply(List<Destination> destinations) { return Futures.traverse( destinations, new Function<Destination, Future<Recommendation>>() { @Override public Future<Recommendation> apply(Destination d) throws Exception { return getDestinationWithReccomendation(d); } }, SpringAppContext.actorSystem().dispatcher()); } }, SpringAppContext.actorSystem().dispatcher()); }
@RequestMapping("/api/akkaActorTravelAgent") public DeferredResult<AgentResponse> processRequest() { final DeferredResult<AgentResponse> deferredResult = new DeferredResult<>(); final long time = System.nanoTime(); final Future<Object> visitedRequest = Patterns.ask( recommenderActor, new RequestVisit(), new Timeout(Duration.create(5, TimeUnit.SECONDS))); final Future<Object> recommendations = Patterns.ask( recommenderActor, new RecommendationRequest(), new Timeout(Duration.create(5, TimeUnit.SECONDS))); final Future<List<Destination>> destinationsFutures = toDestinations(recommendations); final Future<List<Destination>> visitedFutures = toVisits(visitedRequest); final Future<Iterable<Recommendation>> recommendationsFuture = toTravelRecommendationWithInfo(destinationsFutures); final Future<AgentResponse> agentResponseFuture = toAgentResponse(visitedFutures, recommendationsFuture); agentResponseFuture.onComplete( new OnComplete<AgentResponse>() { @Override public void onComplete(Throwable failure, AgentResponse response) throws Throwable { if (response != null) { response.setProcessingTime((System.nanoTime() - time) / 1000000); deferredResult.setResult(response); } else { deferredResult.setErrorResult(failure); } } }, SpringAppContext.actorSystem().dispatcher()); return deferredResult; }
@RestController public class AkkaTravelAgentController { final ActorRef recommenderActor = SpringAppContext.actorSystem() .actorOf(Props.create(RecommenderActor.class).withRouter(new RoundRobinPool(5))); @RequestMapping("/api/akkaActorTravelAgent") public DeferredResult<AgentResponse> processRequest() { final DeferredResult<AgentResponse> deferredResult = new DeferredResult<>(); final long time = System.nanoTime(); final Future<Object> visitedRequest = Patterns.ask( recommenderActor, new RequestVisit(), new Timeout(Duration.create(5, TimeUnit.SECONDS))); final Future<Object> recommendations = Patterns.ask( recommenderActor, new RecommendationRequest(), new Timeout(Duration.create(5, TimeUnit.SECONDS))); final Future<List<Destination>> destinationsFutures = toDestinations(recommendations); final Future<List<Destination>> visitedFutures = toVisits(visitedRequest); final Future<Iterable<Recommendation>> recommendationsFuture = toTravelRecommendationWithInfo(destinationsFutures); final Future<AgentResponse> agentResponseFuture = toAgentResponse(visitedFutures, recommendationsFuture); agentResponseFuture.onComplete( new OnComplete<AgentResponse>() { @Override public void onComplete(Throwable failure, AgentResponse response) throws Throwable { if (response != null) { response.setProcessingTime((System.nanoTime() - time) / 1000000); deferredResult.setResult(response); } else { deferredResult.setErrorResult(failure); } } }, SpringAppContext.actorSystem().dispatcher()); return deferredResult; } private Future<List<Destination>> toDestinations(Future<Object> recommendations) { return recommendations.map( new Mapper<Object, List<Destination>>() { public List<Destination> apply(Object result) { RecommendationResponse response = (RecommendationResponse) result; return response.getRecommendDestination(); } }, SpringAppContext.actorSystem().dispatcher()); } private Future<List<Destination>> toVisits(Future<Object> visits) { return visits.map( new Mapper<Object, List<Destination>>() { public List<Destination> apply(Object result) { ResponseVisit visits = (ResponseVisit) result; return visits.getVisitedDestination(); } }, SpringAppContext.actorSystem().dispatcher()); } private Future<AgentResponse> toAgentResponse( Future<List<Destination>> visitedFutures, Future<Iterable<Recommendation>> reccomendationsFuture) { return visitedFutures .zip(reccomendationsFuture) .map( new Mapper<Tuple2<List<Destination>, Iterable<Recommendation>>, AgentResponse>() { @Override public AgentResponse apply( Tuple2<List<Destination>, Iterable<Recommendation>> tuple) { return new AgentResponse(tuple._1(), toList(tuple._2())); } }, SpringAppContext.actorSystem().dispatcher()); } private Future<Iterable<Recommendation>> toTravelRecommendationWithInfo( Future<List<Destination>> destinationsFutures) { return destinationsFutures.flatMap( new Mapper<List<Destination>, Future<Iterable<Recommendation>>>() { @Override public Future<Iterable<Recommendation>> apply(List<Destination> destinations) { return Futures.traverse( destinations, new Function<Destination, Future<Recommendation>>() { @Override public Future<Recommendation> apply(Destination d) throws Exception { return getDestinationWithReccomendation(d); } }, SpringAppContext.actorSystem().dispatcher()); } }, SpringAppContext.actorSystem().dispatcher()); } private Future<Recommendation> getDestinationWithReccomendation(Destination destination) { ActorRef pricingActor = SpringAppContext.actorSystem().actorOf(Props.create(PriceCalculationActor.class)); ActorRef foreCastActor = SpringAppContext.actorSystem().actorOf(Props.create(WeatherForecastActor.class)); final Future<Calculation> calculationFuture = toPrice( Patterns.ask( pricingActor, new PriceRequest("moon", destination.getDestination()), new Timeout(Duration.create(5, TimeUnit.SECONDS)))); final Future<Forecast> forecastFuture = toForecast( Patterns.ask( foreCastActor, new WeatherRequest(destination.getDestination()), new Timeout(Duration.create(5, TimeUnit.SECONDS)))); return calculationFuture .zip(forecastFuture) .map( new Mapper<Tuple2<Calculation, Forecast>, Recommendation>() { @Override public Recommendation apply(Tuple2<Calculation, Forecast> tuple) { return new Recommendation( destination.getDestination(), tuple._2().getForecast(), tuple._1().getPrice()); } }, SpringAppContext.actorSystem().dispatcher()); } private Future<Calculation> toPrice(Future<Object> futureResponse) { return futureResponse.map( new Mapper<Object, Calculation>() { public Calculation apply(Object result) { PriceResponse price = (PriceResponse) result; return price.getPrice(); } }, SpringAppContext.actorSystem().dispatcher()); } private Future<Forecast> toForecast(Future<Object> futureResponse) { return futureResponse.map( new Mapper<Object, Forecast>() { public Forecast apply(Object result) { WeatherResponse weather = (WeatherResponse) result; return weather.getForecast(); } }, SpringAppContext.actorSystem().dispatcher()); } public static <T> List<T> toList(final Iterable<T> iterable) { return StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); } }