尝试从其方法访问Vertx实例变量时为null

时间:2018-09-13 13:22:55

标签: vert.x

下面是垂直线

package com.api.redis.gateway.verticle;

import java.util.UUID;

import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;

public class SimpleRestChild extends SimpleRestServer{

     RedisClient client;


@Override
public void start() {
    // TODO Auto-generated method stub
    super.start();

    client = RedisClient.create(vertx, new RedisOptions().setHost("127.0.0.1").setPort(6379));
    client.subscribe("channelForServiceToPublish", handler -> {
        if(handler.succeeded())
            System.out.println("SimpleRestServer subscibed to the channel successfully");
    });

}

public void handleSubscription(RoutingContext routingContext) {
    JsonObject requestAsJson = routingContext.getBodyAsJson();

    requestAsJson.put("uuid", getUUID());

    // this client object is null.
    client.set("request", requestAsJson.toString(), handler ->{
        System.out.println("Simple server is setting value to redis client");
        if(handler.succeeded()) {
            System.out.println("Key and value is stored in Redis Server");
        }else if(handler.failed()) {
            System.out.println("Key and value is failed to be stored on Redis Server with cause : "+ handler.cause().getMessage());
        }
    });


    client.publish("channelForServerToPublish", "ServiceOne", handler -> {
        if(handler.succeeded()) {
            System.out.println("Simple Server published message successfully");
        }else if(handler.failed()) {
            System.out.println("Simple Server failed to published message");
        }
    });

    routingContext.vertx().eventBus().consumer("io.vertx.redis.channelForServiceToPublish", handler -> {
        client.get("response", res ->{
            if(res.succeeded()) {
                JsonObject responseAsJson = new JsonObject(res.result());
                if(responseAsJson.getString("uuid").equalsIgnoreCase(requestAsJson.getString("uuid"))) {
                    routingContext.response().setStatusCode(200).end(res.result());
                }
            }else if(res.failed()) {
                System.out.println("Failed to get message from Redis Server");
                routingContext.response().setStatusCode(500).end("Server Error ");
            }
        });


    });
}

private String getUUID() {
    UUID uid = UUID.randomUUID();
    return uid.toString();
}

}

下面是主要版本,上面的版本将从该主要版本中部署,并且在对httpserver的任何请求中,都会调用hanlder方法。

package com.api.redis.gateway.verticle;

import io.vertx.core.AbstractVerticle;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;


public class SimpleRestServer extends AbstractVerticle{



@Override
public void start(){
    int http_port = 9001;

    vertx.deployVerticle("com.api.redis.gateway.verticle.SimpleRestChild", handler -> {
        if(handler.succeeded()) {
            System.out.println(" SimpleRestChild deployed successfully");
        }
    });

    Router router = Router.router(vertx);
    router.route().handler(BodyHandler.create());

    SimpleRestChild child = null;

    try {
        child = (SimpleRestChild) Class.forName("com.api.redis.gateway.verticle.SimpleRestChild").newInstance();
    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
        e.printStackTrace();
    }

    router.route("/subscription").handler(child::handleSubscription);
    vertx.createHttpServer().requestHandler(router::accept).listen(http_port);
    System.out.println("Server started at port : " + http_port);
}

}

在为任何“ / subscription”请求调用handleSubscription时。客户对象为空。

据我了解,这里创建了两个对象。一个带有start(),另一个不带有start()。

我想一次初始化Redisclient。并在对“ / subscription”的任何请求被调用handleSubscription()时使用此对象。

如何实现?

如何解决此问题。

1 个答案:

答案 0 :(得分:0)

请求可能会在客户端初始化实际完成之前进入。

AbstractVerticlestart()的两个变体:

  • start()
  • start(Future<Void> startFuture)

带有Future参数的重载版本应用于执行可能长时间运行的初始化,这在认为Verticle已部署并准备就绪之前必须进行。 (docs中有一个专门讨论此主题的部分)。

所以您可以尝试如下更改代码:

public class SimpleRestChild extends SimpleRestServer {

    RedisClient client;

    @Override
    public void start(Future<Void> startFuture) {
        client = ...

        // important point below is that this Verticle's
        // deployment status depends on whether or not
        // the client initialization succeeds

        client.subscribe("...", handler -> {
            if(handler.succeeded()) {
                startFuture.complete();
            } else {
                startFuture.fail(handler.cause());
            }
        );
    }

}

和:

public class SimpleRestServer extends AbstractVerticle {

@Override
public void start(Future<Void> startFuture) {
    int http_port = 9001;

    vertx.deployVerticle("...", handler -> {
        // if the child Verticle is successfully deployed
        // then move on to completing this Verticle's
        // initialization

        if(handler.succeeded()) {
            Router router = ...

            ...

            // if the server is successfully installed then
            // invoke the Future to signal this Verticle
            // is deployed

            vertx.createHttpServer()
                .requestHandler(router::accept)
                .listen(http_port, handler -> {
                    if(handler.succeeded()) {
                        startFuture.complete();
                    } else {
                        startFuture.fail(handler.cause());
                    }
                });

    } else {
        startFuture.fail(handler.cause());
    }
}

使用这种方法,您的Verticles仅在请求的所有相关资源都已完全初始化时才为其提供服务。