Java api - How to compose 3 CompletionStage

java
sbt

(Juan José Sosa Osuna) #1

Hello!
I’m really new using Java Play Framework and I have some doubts creating this API. I need to do 1 request to my database (to check if token got a real user ID) and then 2 HTTP request to an external service. I want to create a response using this logic:
I need to get every workplaces from a workers list from a user code (dni) and then I need to create a response with all data like this JSON ->

{
	"status": "OK",
	"error": "",
	"result": [
		{
			"id_entorno": 1,
			"worker": {
				"id_worker": 654,
				"firstName": "Juanjo",
				"secondName": "Sosa"
			},
			"workplace": {
				"id_workplace": 1234,
				"description": "Edificio Centris",
				"latitude": 123.123,
				"longitude": 123.123,
				"street": "Glorieta Fernando Quiñones",
				"city": "Tomares",
				"state": "Andalucía",
				"country": "España"
			},
			"favorite": false
		},
		{
			"id_entorno": 2,
			"worker": {
				"id_worker": 654,
				"firstName": "Juan José",
				"secondName": "Sosa Osuna"
			},
			"workplace": {
				"id_workplace": 542,
				"description": "Edificio Plaza Mayor",
				"latitude": 21.123,
				"longitude": 12.123,
				"street": "Avenida San Juan",
				"city": "Madrid",
				"state": "Comunidad de Madrid",
				"country": "España"
			},
			"favorite": true
		}
	]
}

And here is my code ->

public CompletionStage<Result> getWorkplaces(Long idEnv) {
    if(request().getHeaders().get(AUTH).isPresent()) {
        if(idEnv != 0 && idEnv != null){
            String token = request().getHeaders().get(AUTH).get().replace("Bearer ", "");
            String idUser = AuthorizationUtil.getUserFromJwt(jwtValidator, token);
            if (idUser != null) {
                CompletionStage<User> searchService = userRepository.findById(String.valueOf(idUser));
                CompletionStage<Result> result = searchService.thenComposeAsync(u -> {
                    if (u != null) {
                        String dni = u.getDni();
                        if(dni != null){
                            // TODO ...
                            return thirdPartyWs.peopleLocator(idEnv, dni, Long.parseLong(idUser)).thenComposeAsync(workerStream -> {
                                if (workerStream != null) {
                                    // TODO ...
                                    workerStream.collect(Collectors.toList()).forEach(worker -> {
                                        Long workerId = worker.getIdWorker();
                                        List<ResponseGetWorkplaces> listaWorkplaces = new ArrayList<>();
                                        return thirdPartyWs.getWorkplaces(idEnv, workerId).thenApplyAsync(workplaceStream -> {
                                            if (workplaceStream != null) {
                                                workplaceStream.collect(Collectors.toList()).forEach(workplace -> {
                                                    ResponseWorker resw = new ResponseWorker(worker.getIdWorker(), worker.getFirstName(), worker.getSecondName());
                                                    ResponseWorkplace reswp = new ResponseWorkplace(workplace.getIdWorkplace(), workplace.getDescription(), workplace.getLatitude(), workplace.getLongitude(), workplace.getStreet(), workplace.getCity(), workplace.getState(), workplace.getCountry());
                                                    //TODO ...
                                                    ResponseGetWorkplaces res = new ResponseGetWorkplaces(idEnv, resw, reswp, false);
                                                    listaWorkplaces.add(res);
                                                });
                                                return ok(JsonUtil.responseFromJsonNode(true, Json.toJson(listaWorkplaces), ""));
                                            } else {
                                                return notFound(JsonUtil.responseFromJsonNode(false, Json.toJson(ENTITY_NOT_FOUND), ""));
                                            }
                                        }, executionContext.current());
                                    });
                                } else {
                                    return CompletableFuture.supplyAsync(() -> notFound(JsonUtil.responseFromJsonNode(false, Json.toJson(ENTITY_NOT_FOUND), "")));
                                }
                            }, executionContext.current());
                        } else {
                            return CompletableFuture.supplyAsync(() -> badRequest(JsonUtil.responseFromJsonNode(false, Json.toJson(ERROR_EMPTY_DNI), "")));                            }
                    } else {
                        return CompletableFuture.supplyAsync(() -> forbidden(JsonUtil.responseFromJsonNode(false, Json.toJson(ERROR_INVALID_TOKEN), "")));                        }
                }, executionContext.current());
                return result.thenApplyAsync(finishResult -> finishResult);
            } else {
                return CompletableFuture.supplyAsync(() -> forbidden(JsonUtil.responseFromJsonNode(false, Json.toJson(ERROR_INVALID_TOKEN), "")));
            }

            // TODO ...

        } else {
            return CompletableFuture.supplyAsync(() -> badRequest(JsonUtil.responseFromList(false, new ArrayList<>(), INVALID_PARAMETERS)));
        }
    } else {
        return CompletableFuture.supplyAsync(() -> forbidden(JsonUtil.responseFromJsonNode(false, Json.toJson(ERROR_NOT_AUTH), "")));
    }
}

I have errors that say “Unexpected return value” and “Missing return statement”. What am I doing wrong? Can someone help me please?


(Aditya Athalye) #2

I would suggest refactoring that large chunk of code.

  • Put the code to execute in thenApplyAsync, thenComposeAsync in separate methods and call them.

  • Too many return statements can be confusing. Avoid if possible. Most of your error responses only differn in error code. Use an error variable and write a method to switch on the error code to get the actual response call forbidden, badRequest etc.

Once you are done with the refactoring, you will be able to figure out the issue yourself.

HTH.
Aditya