我正在编写可在MongoDB数据库中获取数据的Dropwizard微服务。微服务可以正常工作,但是我在DAO中努力使用来自Dropwizard配置Java类的配置。目前我有

public class XDAO implements IXDAO {

    protected DB db;
    protected DBCollection collection;

    /* singleton */
    private static XDAO instance;

    /* Get singleton */
    public static synchronized XDAO getSingleton(){
       if (instance == null){
         instance = new XDAO();
       }
      return instance;
    }

    /* constructor */
    public XDAO(){
       initDatabase();
       initDatabaseIndexes();
    }

    private void initDatabase(){
       MongoClient client = null;

       try {
           client = new Mongo("10.126.80.192",27017);
           db = client.getDB("terre");
           //then some other code
       }

       catch (final MongoException e){
         ...
       }

       catch (UnknownHostException e){
         ...
       }

     }

 }


我想对这两行中的三个参数进行硬编码:

  client = new Mongo("10.126.80.192", 27017);
  db = client.getDB("terre");


我的MongoConfiguration Java类是:

public class MongoConfiguration extends Configuration {

@JsonProperty
@NotEmpty
public String host;

@JsonProperty
public int port = 27017;

@JsonProperty
@NotEmpty
public String db_name;

public String getMongohost() {
    return host;
}

public void setMongohost(String host) {
    this.host = host;
}

public int getMongoport() {
    return port;
}

public void setMongoport(int port) {
    this.port = port;
}

public String getDb_name() {
    return db_name;
}

public void setDb_name(String db_name) {
    this.db_name = db_name;
}

}


我的使用DAO的Resource类是:

@Path("/mongo")
@Produces(MediaType.APPLICATION_JSON)
public class MyResource {

private XDAO xDAO = XDAO.getSingleton();

private String mongohost;
private String db_name;
private int mongoport;

public MyResource(String db_name, String mongohost, int mongoport) {
    this.db_name = db_name;
    this.mongohost = mongohost;
    this.mongoport = mongoport;
}

public MyResource() {
}

@GET
@Path("/findByUUID")
@Produces(value = MediaType.APPLICATION_JSON)
@Timed
public Entity findByUUID(@QueryParam("uuid") String uuid) {

    return xDAO.findByUUid(uuid);
  }
}


在我的应用程序类中

  @Override
  public void run(final MongoConfiguration configuration, final Environment environment) {

    final MyResource resource = new MyResource(configuration.getDb_name(), configuration.getMongohost(), configuration.getMongoport());
    environment.jersey().register(resource);
   }


为了解决我的问题,我尝试了很多事情。我尝试的最后一件事是在XDAO中添加这四个字段

  private String mongohost;
  private String db_name;
  private int mongoport;
  private static final MongoConfiguration configuration = new MongoConfiguration();


在XDAO的构造函数中附带以下代码:

public XDAO(){
    instance.mongohost = configuration.getMongohost();
    instance.mongoport = configuration.getMongoport();
    instance.db_name = configuration.getDb_name();
    /* then like before */
    initDatabase();
    initDatabaseIndexes();
}


尝试此操作时,调用initDatabase方法时会出现空指针异常:mongoHost和db_name为null

最佳答案

问题是您正在使用private static final MongoConfiguration configuration = new MongoConfiguration();在XDAO中创建新配置,而不是使用Dropwizard的run方法中的配置。

执行此操作时,新配置中的字段hostdb_name为空,这就是为什么在实例化XDAO时获得NPE的原因

您需要将从应用程序类中的Dropwizard获得的MongoConfiguration实例传递给XDAO,理想情况下,是在创建单例XDAO时,它对db_namehost具有非空值

问题下面的这段代码-您正在创建单例而不给XDAO配置实例。

public class XDAO implements IXDAO {

//... snip

/* Get singleton */
public static synchronized XDAO getSingleton(){
   if (instance == null){
     instance = new XDAO(); // no configuration information is included!
   }
  return instance;
}

/* constructor */
public XDAO(){
   initDatabase(); // this call needs db_name & host but you haven't set those yet!!
   initDatabaseIndexes();
}


我建议您按照以下方式修改应用程序类以创建XDAO:

@Override
public void run(final MongoConfiguration configuration, final Environment environment) {

  XDAO XDAOsingleton = new XDAO(configuration);
  XDAO.setSingletonInstance(XDAOsingleton); // You need to create this static method.

  final MyResource resource = new MyResource(configuration.getDb_name(), configuration.getMongohost(), configuration.getMongoport()); // MyResource depends on XDAO so must be created after XAO's singleton is set
  environment.jersey().register(resource);
}


您可能还需要从XDAO的构造函数中取出MongoConfiguration等,具体取决于是否保留initDatabase()

我还建议您将public static synchronized XDAO getSingleton()的构造函数更改为MyResource。资源类似乎不需要配置信息,最好使对XDAO的依赖关系显式(然后,您也不必将XDAO单例保持在XDAO类内的静态字段中)。

10-06 03:54