简体   繁体   English

异步完成创建的Java对象 - 对象在构造函数完成后的某个时间准备就绪

[英]Java object that completes creation asynchronously - object is ready some time after constructor finishes

I have to wrap an proprietary java api into something more useful. 我必须将专有的java api包装成更有用的东西。 The central class is a "client" object The signature is something like this: 中心类是“客户端”对象签名是这样的:

public class ProprietaryClient {

    private final IEvents eventHandler;
    private Object one;
    private Object two;

    public ProprietaryClient(ProprietaryClient.IEvents eventHandler){
        this.eventHandler = eventHandler;
    }

    //returns immediately
    public void connect(String url){
        //doing nasty stuff that triigers
        //on success
        //will be called from somewhere at anytime
        // eventHandler.onStateChange( State.CONNECTED );
    }

    //returns immediately
    public void login(String user, String password){
        //doing nasty stuff that sets fields one and two
        //will be called from somewhere at anytime
        //eventHandler.onStateChange( State.LOGGED_IN );
        //eventHandler.onLogin( one, two );
    }

    public interface IEvents {

        void onStateChange(State state);

        void onLogin(Object one, Object two);
    }

    public enum State{
        CONNECTED,
        LOGGED_IN,
        UNKNOWN;
    }
}

This Object is only useful in state "LOGGED_IN" but there is no getter for this field. 此对象仅在状态“LOGGED_IN”中有用,但此字段没有getter。 The only way to know if the object is usable is: 了解对象是否可用的唯一方法是:

  1. call connect 呼叫连接
  2. wait for state change to CONNECT 等待状态更改为CONNECT
  3. call login 呼叫登录
  4. wait for state change to LOGGED_IN (or call of onLogin) 等待状态更改为LOGGED_IN(或调用onLogin)

I want to wrap this into a class that does connecting and login in constructor and tells the user if it is ready. 我想将它包装成一个连接并在构造函数中登录的类,并告诉用户它是否准备就绪。 My idea is to have a method that returns a CompletableFuture or Future: This is what i have so far. 我的想法是有一个返回CompletableFuture或Future的方法:这是我到目前为止所拥有的。 the stuff with the events is working this way. 事件的东西就是这样的。 The implementation of IEvents wraps all evants into messages that are identified by user (this part is working). IEvents的实现将所有evants包装成由用户标识的消息(这部分正在工作)。 But how to create and maintain the CompletableFuture based on arriving events (parts with ///????) Is there a way to create my own future that gets ready if events arrived or correct condition is met? 但是如何根据到达事件创建和维护CompletableFuture(带有/// ????的部分)有没有办法创建我自己的未来,如果事件到达或满足正确条件就可以准备好?

public class MyClient implements Client, MessageHandler {


    private final String password;
    private final IEvents eventHandler;
    private final SubscribableChannel eventBus;
    private final String user;
    private final ProprietaryClient propClient;

    public SikomClient( String user, String password, IEvents eventHandler, SubscribableChannel eventBus) {
        this.eventHandler = checkNotNull( eventHandler );
        this.eventBus = checkNotNull( eventBus );
        eventBus.subscribe( this );
        this.password = password;
        this.user = user;
        propClient = new ProprietaryClient(eventHandler);
        ///????
        propClient.connect("url");
        //have to wait until message received and state is "CONNECT"
        propClient.login(user, password);

    }

    public CompletableFuture<Boolean> amIready(){
        //???
    }

    @Override
    public void handleMessage( Message<?> message ) throws MessagingException {
        if( message instanceof OnClientStateMessage && belongsToMe( message )){
            // ????
        } else if( message instanceof OnLoginMessage && belongsToMe( message )) {
            // ????
            //complete CompletableFuture with true
        }
    }

    private boolean belongsToMe(Message<?> message){
        return ((AbstractStringJsonMessage) message).getUserId().equals( user );
    }
}

Or is there a better way to solve this without "Future". 或者,没有“未来”,有没有更好的方法来解决这个问题。 I want to give the caller the responsibility how long to wait but my Class should maintain the state and know about it. 我想让调用者有责任等待多久但我的班级应该保持状态并了解它。

The solution is rather simple. 解决方案相当简单。 Now i understand "CompletableFuture" better. 现在我更了解“CompletableFuture”。

i added a login method, a field with Completable future an a getter for it: 我添加了一个登录方法,一个具有Completable future的字段,它是一个getter:

private CompletableFuture<ReturnCode> loggedIn = new CompletableFuture<>();
...
private void login() {
    //as per sikom settings each user gets a fixed workplace identified by user name
    if( loggedIn.isDone() ) {
        loggedIn = new CompletableFuture<>();
    }
    propClient.login( user, user, password, 0 );
}

public CompletableFuture<ReturnCode> loggedIn() {
    return loggedIn;
}

My handleMessage does this: 我的handleMessage执行此操作:

public void handleMessage( Message<?> message ) throws MessagingException {
    if( message instanceof OnClientStateMessage && belongsToMe( message ) ) {
        state = ( (OnClientStateMessage) message ).getState();
        if( state.equals( ClientState.CONNECT ) ) {
            login();
        }
    } else if( message instanceof OnLoginMessage && belongsToMe( message ) ) {
        ReturnCode rc = ( (OnLoginMessage) message ).getRc();
        loggedIn.complete( rc );
    }
}

I just manually complete the future manually if the message arrives (since it has no task attached get would never return). 如果消息到达,我只需手动完成未来(因为它没有附加任务,get将永远不会返回)。

A user of this class will instantiate it and could instantly call loggedIn. 此类的用户将实例化它,并可立即调用loggedIn。 The calle can decide how long to wait for loggedIn.get(). calle可以决定等待loggedIn.get()的时间。

Don't know if its a good idea: The class it self could extend CompletableFuture and could complete itself?! 不知道它是不是一个好主意:它自己的类可以扩展CompletableFuture并且可以自己完成?!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM