Метод возвращает неправильное значение, потому что возвращение слишком рано - PullRequest
0 голосов
/ 22 мая 2019

Извините за этот странный заголовок темы, но я не знал, как описать мою проблему лучше, чем эта.

В настоящее время я работаю над проектом Java, который использует Microsoft Graph API (это мой первый разя использую Microsoft Graph API).

Я думаю, что моя проблема - общая проблема с Java.У меня есть класс, который предоставляет клиент Graph API и второй класс со всеми операциями, которые я хочу выполнить с Graph API.Класс с методами операции должен возвращать результаты клиентскому классу.

Некоторый код.Мой клиентский класс (соответствующая часть, где я вызываю операцию):

client = GraphServiceClientManager.getInstance().getGraphServiceClient();
Operations task = new Operations(client);
System.out.println(task.getUsernamebyUPN("USER UPN"));

Мой класс с операциями:

public String username = "0";

    public String getUsernamebyUPN(String UPN) {
       client.users(UPN).buildRequest().get(new ICallback<User>() {
            @Override
            public void success(User user) {
                username = user.displayName;

            }

            @Override
            public void failure(ClientException ex) {
                ex.printStackTrace();
            }
        });
        return username;
    }

Так что проблема в том, что когда я запускаю код, он возвращаетимя пользователя со значением 0 вместо имени пользователя, который я хочу.Переменная username будет изменена после возврата.

Если я добавлю System.out.prntln (имя пользователя) под "username = user.displayName;"строка в методе успеха будет иметь следующий вывод:

0
The username I want

Как я могу решить эту проблему?Вам нужно больше кода?

Большое спасибо за вашу помощь.:)

1 Ответ

0 голосов
/ 22 мая 2019

Значение будет возвращено асинхронно в функцию обратного вызова, но вы можете заставить вашу программу ждать возврата, когда ей понадобится значение. Один из способов сделать это - вернуть класс держателя значения, который блокируется, когда вы пытаетесь получить значение, пока оно не будет установлено, и обратный вызов устанавливает значение.

Например, следующие пользователи класса Phaser для управления этим режимом ожидания:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Phaser;

public class FutureValue<T> {

    private T value = null;
    private Exception ex = null;
    private Phaser phaser = new Phaser(1);

    /**
     * Get blocks until a value or an exception is set, after that it always
     * returns immediately
     *
     * @return the value
     * @throws ExecutionException
     */
    public T get() throws ExecutionException {
        phaser.register();
        phaser.arriveAndAwaitAdvance();
        if (ex != null) {
            throw new ExecutionException(ex);
        }
        return value;
    }

    /**
     * Sets the value and unblocks awaiting threads
     *
     * @param val
     */
    public void set(T val) {
        this.value = val;
        phaser.forceTermination();
    }

    /**
     * Sets an exception and unblocks awaiting threads
     */
    public void setException(InterruptedException ex) {
        this.ex = ex;
        phaser.forceTermination();
    }
}

И вы можете изменить свой метод, чтобы он возвращал FutureValue:

    public FutureValue<String> getUsernamebyUPN(String UPN) {

       final FutureValue<String> future = new FutureValue<String>();
       client.users(UPN).buildRequest().get(new ICallback<User>() {
            @Override
            public void success(User user) {
                future.set(user.displayName);
            }

            @Override
            public void failure(ClientException ex) {
                future.setException(ex);
            }
        });
        return future;
    }

Другой вариант - изменить логику, чтобы не получать значения, а наблюдать за событиями с помощью обратных вызовов, отправляющих события.

...