【问题标题】:Dropwizard quartz jobs won't work with GuiceyDropwizard 石英工作不适用于 Guicey
【发布时间】:2018-08-18 15:15:33
【问题描述】:

我正在使用 dropwizard 1.0.5、dropwizard-guicey 4.0.1 (https://github.com/xvik/dropwizard-guicey)、spinscale quartz implementation 3.0.0 (https://github.com/spinscale/dropwizard-jobs)。

我希望能够将我的依赖项注入到quartz/spinscale 创建的作业实例中。为此,我尝试在以下库中加载https://github.com/spinscale/dropwizard-jobs/tree/master/dropwizard-jobs-guice

问题在于,当创建 Guice dropwizard 作业包时,Guice 注入器尚未初始化,所以我得到了一个 NPE。

示例: MyApplication.java

  @Override
  public void initialize(Bootstrap<MyConfiguration> bootstrap) {

    // Initialize Guice for dependency injection

    GuiceBundle guiceBundle = GuiceBundle.builder()
            .bindConfigurationInterfaces()
            .enableAutoConfig(getClass().getPackage().getName())
            .modules(new MyModule(bootstrap.getMetricRegistry()))
            .build();
    bootstrap.addBundle(guiceBundle);

    bootstrap.addBundle(new GuiceJobsBundle(guiceBundle.getInjector()));

例外:

Exception in thread "main" java.lang.NullPointerException: Guice not initialized
    at com.google.common.base.Preconditions.checkNotNull(Preconditions.java:226)

为了解决这个问题,我尝试创建自己的GuiceJobsBundle 版本,它接收GuiceBundle,并且在调用bundle.run() 之前不设置注入器。但是,我仍然获得了 NPE。

MyApplication

  @Override
  public void initialize(Bootstrap<MyConfiguration> bootstrap) {
    // Substitute environment variable references in the configuration file
    bootstrap.setConfigurationSourceProvider(new SubstitutingSourceProvider(
        bootstrap.getConfigurationSourceProvider(),
        new EnvironmentVariableSubstitutor(false, true)
    ));

    // Initialize Guice for dependency injection

    GuiceBundle guiceBundle = GuiceBundle.builder()
            .bindConfigurationInterfaces()
            .enableAutoConfig(getClass().getPackage().getName())
            .modules(new MyModule(bootstrap.getMetricRegistry()))
            .build();
    bootstrap.addBundle(guiceBundle);

    bootstrap.addBundle(new GuiceyJobsBundle(guiceBundle));
  }

GuiceyJobsBundle

public class GuiceyJobsBundle extends JobsBundle {

    private GuiceBundle guiceBundle;

    public GuiceyJobsBundle(GuiceBundle guiceBundle) {
        this.guiceBundle = guiceBundle;
    }

    @Override
    public void run(Environment environment) {
        JobManager jobManager = new GuiceJobManager(guiceBundle.getInjector());
        environment.lifecycle().manage(jobManager);
    }
}

什么时候调用 bundle 的 run() 方法?有没有人找到一个可行的解决方案?

【问题讨论】:

    标签: java java-8 quartz-scheduler guice dropwizard


    【解决方案1】:

    您对上次修复几乎是正确的,您只是忘记绑定配置jobManager.configure(configuration)(这就是抛出 NPE 的原因)。

    但是您完全可以在没有捆绑包的情况下进行集成。我看到你已经使用了类路径扫描,所以只需将这些扩展放在某个地方:

    @Singleton
    public class JobsManager extends GuiceJobManager {
    
        @Inject
        public JobsManager(Injector injector, JobsAppConfiguration configuration) {
            super(injector);
            configure(configuration);
        }
    }
    

    这将被识别为 Manged bean 并将启动/停止石英上下文。在内部,它在已注册的 guice 绑定中搜索作业(使用 dropwizard-jobs 逻辑)。

    public class JobsInstaller implements FeatureInstaller<Job>, TypeInstaller<Job> {
    
        private final Reporter reporter = new Reporter(JobsInstaller.class, "jobs =");
    
        @Override
        public boolean matches(Class<?> type) {
            return FeatureUtils.is(type, Job.class);
        }
    
        @Override
        public void install(Environment environment, Class<Job> type) {
            // here we can also look for class annotations and show more info in console
            // (omitted for simplicity)
            reporter.line("(%s)", type.getName());
        }
    
        @Override
        public void report() {
            reporter.report();
        }
    }
    

    此安装程序只是将所有作业绑定到 guice 上下文,因此 JobsManager 可以安装它们(只是为了避免手动绑定作业)。

    我将竞争示例添加到 guicey-examples 存储库:https://github.com/xvik/dropwizard-guicey-examples/tree/master/dropwizard-jobs

    【讨论】:

    • 这很好用。但是,您能解释一下JobsInstaller 的更多功能吗? bootstrap.addBundle(new JobsBundle(jobInstance)); 是您所指的手动绑定的示例吗?它是如何做到的?从我读过的关于安装程序的内容来看,它所做的只是将它绑定到 guice(即:bind(SampleJob.class).in(Singleton))。我不明白这样做是如何做到的,所以我不需要将工作注册到工作包。你能再解释一下这是如何工作的吗?
    • 原始 dropwizard-jobs 捆绑包手动注册托管对象 (GuiceJobManager) 以启动/停止石英和 search in all registered guice bindings 作业 bean 以注册它们。所以每个任务都必须绑定在guice模块中才能在quartz中注册。我将这些绑定称为“手动”,因为您必须在 guice 模块中手动注册所有作业 bean。
    • 使用 guicey 我们不需要 bundle,因为我们的托管 bean (JobsManager) 可以通过类路径扫描自动安装。但是我们仍然需要在 guice 上下文中手动绑定所有作业,以便可以在 guice 上下文中找到它们。为了避免这个手动步骤,我们使用安装程序,它将在类路径扫描期间找到所有作业类,并将它们隐式绑定到 guice 上下文(因此 dropwizard-jobs 可以“看到”它们)。此外,安装程序会打印所有使用过的作业,这在某些情况下可能非常有用。
    猜你喜欢
    • 2018-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-14
    • 2019-06-20
    相关资源
    最近更新 更多