了解Java播放中的异步调用

问题描述 投票:0回答:1

[尝试在Java播放框架2.8中制作API。我不知道我写的代码有什么问题,但它不起作用。

我在localhost:9000中得到此响应

{"result":null,"stack":null,"done":false,"cancelled":false,"completedExceptionally":false,"numberOfDependents":0}

我认为我在异步调用方面缺少一些东西,因为当我尝试单独运行代码时,它可以工作(使用邮递员或其他游乐场类)。

我正在上传代码,很高兴知道代码有什么问题。预先感谢!

package utils;

import com.fasterxml.jackson.databind.JsonNode;
import models.Commit;
import play.libs.ws.WSResponse;

import javax.inject.Inject;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;


public class CommitsService {

    private BBService bbService;

    @Inject
    public CommitsService(BBService bbService) {
        this.bbService = bbService;
    }

    public CompletionStage<CompletableFuture<List<Commit>>> retrieveCommitsForUser(String username) {
        CompletionStage<List<String>> reposPromise = getRepos();
        return reposPromise
                .thenApplyAsync(repos -> sequence(repos.stream()
                .map(repo -> getRepoCommits(repo))
                .collect(Collectors.toList()))
                    .thenApplyAsync(responses -> {
                    List<Commit> allCommits = responses.stream()
                            .map(wsResponse -> extractCommits(wsResponse))
                            .flatMap(List::stream).filter(commit -> isByUser(commit, username) && isLastDay(commit))
                            .collect(Collectors.toList());
                    return allCommits;
                }));
    }

    private CompletionStage<List<String>> getRepos() {
        return bbService.getRepos()
                .thenApplyAsync(response -> extractRepos(response));
    }

    private List<String> extractRepos(WSResponse wsResponse) {
        Vector<String> repos = new Vector<>();
        JsonNode reposAsJson = wsResponse.asJson().findValue("values");

        for (JsonNode repo : reposAsJson) {
            String repoName = repo.path("name").asText();
            repos.add(repoName);
        }

        return repos;
    }

    private CompletableFuture<WSResponse> getRepoCommits(String repo) {
        return bbService.getRepoCommits(repo).toCompletableFuture();
    }

    private boolean isByUser(Commit commit, String username) {
        return commit.getAuthor().equals(username);
    }

    private boolean isLastDay(Commit commit) {
        String sDate = commit.getDate().substring(0, commit.getDate().indexOf('T'));
        String sTime = commit.getDate().substring(commit.getDate().indexOf('T'), commit.getDate().length() - 1);
        return true;
    }

    private List<Commit> extractCommits(WSResponse wsResponse) {
        Vector<Commit> allCommits = new Vector<>();
        JsonNode commits = wsResponse.asJson().findValue("values");

        for (JsonNode commit : commits) {
            String HASH = commit.path("hash").asText();
            String date = commit.path("date").asText();
            String repo = commit.path("repository").path("name").asText();
            String message = commit.path("message").asText();
            String author = commit.path("author").path("user").path("display_name").asText();

            Commit currCommit = new Commit(HASH, date, repo, message, author);
            allCommits.add(currCommit);
        }

        return allCommits;
    }

    public <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futuresList) {
        return CompletableFuture
                .allOf(futuresList.toArray(new CompletableFuture[0])) // (1)
                .thenApply(v ->
                        futuresList.stream()
                                .map(CompletableFuture::join)
                                .collect(Collectors.toList())
                );
    }
}

package controllers;

import play.libs.Json;
import play.mvc.*;
import utils.CommitsService;

import javax.inject.Inject;
import java.util.concurrent.CompletionStage;

/**
 * Commits controller is handling in and out http traffic regarding bitbucket commits.
 * Supporting get but can be expanded to other crud operations.
 */
public class CommitsController extends Controller {

    private final CommitsService commitsService;

    @Inject
    public CommitsController(CommitsService commitsService) {
        this.commitsService = commitsService;
    }

    public CompletionStage<Result> showCommits(String username) {
        return commitsService.retrieveCommitsForUser(username)
                .thenApplyAsync(res -> ok(Json.toJson(res)));
    }
}


package utils;

import com.fasterxml.jackson.databind.JsonNode;
import play.libs.ws.*;
import play.mvc.Result;

import javax.inject.Inject;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;


public class BBService {

    private final String BB_BASE_URL = "https://api.bitbucket.org/2.0/";
    private final String URL = BB_BASE_URL + "repositories/******/";
    private final String COMMITS = "commits";

    private final String bbUsername = "*******";
    private final String bbPassword = "*******";
    private final WSClient ws;

    @Inject
    public BBService(WSClient ws) {
        this.ws = ws;
    }

    public CompletionStage<WSResponse> getAsync(String url) {
        WSRequest req = ws.url(url).setAuth(bbUsername, bbPassword);
        return req.get();
    }

    public List<String> extractNames(WSResponse wsResponse) {
        Vector<String> usersNames = new Vector<>();
        JsonNode users = wsResponse.asJson().findValue("values");

        for (JsonNode user : users) {
            String userName = user.findValue("display_name").asText();
            usersNames.add(userName);
        }

        return usersNames;
    }

    public CompletionStage<WSResponse> getRepos() {
        return getAsync(URL);
    }

    public CompletionStage<WSResponse> getRepoCommits(String repoName) {
        return getAsync(URL + repoName + "/" + COMMITS);
    }

    public Result withFullAccess(Result noAccessibleRes) {
        return noAccessibleRes.withHeader("Access-Control-Allow-Origin", "*");
    }

    public <T> CompletableFuture<List<T>> sequence(List<CompletableFuture<T>> futuresList) {
        return CompletableFuture
                .allOf(futuresList.toArray(new CompletableFuture[0])) // (1)
                .thenApply(v ->
                        futuresList.stream()
                                .map(CompletableFuture::join)
                                .collect(Collectors.toList())
                );
    }
}

java asynchronous playframework
1个回答
0
投票

考虑到您得到的响应,问题是您将类型设为CompletableFuture<List<Commit>>的响应对象而不是您可能想要的List<Commit>

我的代码主要问题在CommitsController

retrieveCommitsForUser(username)
                .thenApplyAsync(res -> ok(Json.toJson(res)))

您给res类型为CompletableFuture<List<Commit>>的位置-这就是为什么您在响应中看到此类的所有字段的原因。

您要做的是在方法CommitsService.retrieveCommitsForUser中返回以返回CompletionStage<List<Commit>>而不是CompletionStage<CompletableFuture<List<Commit>>>

希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.