package org.learning.by.example.reactive.microservices.handlers; import org.learning.by.example.reactive.microservices.model.GeographicCoordinates; import org.learning.by.example.reactive.microservices.model.LocationRequest; import org.learning.by.example.reactive.microservices.model.LocationResponse; import org.learning.by.example.reactive.microservices.model.SunriseSunset; import org.learning.by.example.reactive.microservices.services.GeoLocationService; import org.learning.by.example.reactive.microservices.services.SunriseSunsetService; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; public class ApiHandler { private static final String ADDRESS = "address"; private static final String EMPTY_STRING = ""; private final ErrorHandler errorHandler; private final GeoLocationService geoLocationService; private final SunriseSunsetService sunriseSunsetService; public ApiHandler(final GeoLocationService geoLocationService, final SunriseSunsetService sunriseSunsetService, final ErrorHandler errorHandler) { this.errorHandler = errorHandler; this.geoLocationService = geoLocationService; this.sunriseSunsetService = sunriseSunsetService; } public Mono<ServerResponse> postLocation(final ServerRequest request) { return request.bodyToMono(LocationRequest.class) .flatMap(locationRequest -> Mono.just(locationRequest.getAddress())) .onErrorResume(throwable -> Mono.just(EMPTY_STRING)) .transform(this::buildResponse) .onErrorResume(errorHandler::throwableError); } public Mono<ServerResponse> getLocation(final ServerRequest request) { return Mono.just(request.pathVariable(ADDRESS)) .transform(this::buildResponse) .onErrorResume(errorHandler::throwableError); } Mono<ServerResponse> buildResponse(final Mono<String> address) { return address .transform(geoLocationService::fromAddress) .and(this::sunriseSunset, LocationResponse::new) .transform(this::serverResponse); } private Mono<SunriseSunset> sunriseSunset(GeographicCoordinates geographicCoordinates) { return Mono.just(geographicCoordinates).transform(sunriseSunsetService::fromGeographicCoordinates); } Mono<ServerResponse> serverResponse(Mono<LocationResponse> locationResponseMono) { return locationResponseMono.flatMap(locationResponse -> ServerResponse.ok().body(Mono.just(locationResponse), LocationResponse.class)); } }