Я хочу использовать диспетчер служб Guava для управления службами в моем приложении Dropwizard.

ServiceManagerProvider предоставляет менеджеру службы:

@Singleton
public class ServiceManagerProvider implements Provider<ServiceManager> {
    @Inject
    Set<Service> services;

    public static Multibinder<Service> serviceRegistry(Binder binder) {
        return Multibinder.newSetBinder(binder, Service.class);
    }

    @Override
    public ServiceManager get() {
        return new ServiceManager(services);
    }
}

ManagedGuavaServices - это объект Managed, который взаимодействует с Service Manager для запуска / остановки служб:

public class ManagedGuavaServices implements Managed {
    @Inject
    private ServiceManager _serviceManager;

    @Inject
    public ManagedGuavaServices(ServiceManager serviceManager) {
        _serviceManager = serviceManager;
    }

    @Override
    public void start() throws Exception {
        _serviceManager.startAsync();
    }

    @Override
    public void stop() throws Exception {
        _serviceManager.stopAsync();
    }
}

MyModule - это модуль, в котором указаны привязки Guice:

public class MyModule extends DropwizardAwareModule<MyConfig> {
  ...
  @Override
    protected void configure() {
      bind(ServiceManager.class).toProvider(ServiceManagerProvider.class);
      bind(Managed.class).to(ManagedGuavaServices.class).in(Singleton.class);
    }
}

А MyApplication - это приложение Dropwizard, которое зависит от MyModule:

public class MyApplication extends Application<MyConfig> {
  @Inject
  private Managed managedServices;

  ...

  @Override
  public void initialize(Bootstrap<MyConfig> bootstrap) {
    bootstrap.addBundle(GuiceBundle.builder()
                .printDiagnosticInfo()
                .printGuiceBindings()
                .enableAutoConfig(getClass().getPackage().getName())
                .modules(
                        new MyModule()
                )
                .build());
  }

  ...

  @Override
  public void run(MyConfig config, Environment environment) {
    environment.lifecycle().manage(managedServices);
  }
}

Кажется, что все было соединено вместе, но когда я запускаю приложение, я получаю сообщение об ошибке:

java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:221)
    at io.dropwizard.lifecycle.setup.LifecycleEnvironment.manage(LifecycleEnvironment.java:45)
    at com.example.MyApplication.run(MyApplication.java:188)
    at com.example.MyApplication.run(MyApplication.java:60)
    at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:44)
    at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:87)
    at io.dropwizard.cli.Cli.run(Cli.java:78)
    at io.dropwizard.Application.run(Application.java:94)
    at com.example.MyApplication.main(MyApplication.java:70)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at com.webobjects._bootstrap.WOBootstrap.main(WOBootstrap.java:118)

Что по существу означает, что введенный managedServices в MZPaymentApplication равен нулю при запуске приложения.

Что здесь не так? Это та же проблема, что и в этом вопросе SO? Если да, то где должен быть @PostConstruct?

1
umop apisdn 30 Мар 2021 в 18:00

1 ответ

Лучший ответ

Проблема заключается в том, что managedServices является полем в приложении, а не вводимым, поскольку объект приложения не настраивается Guice (обычно в Dropwizard он создается с помощью ключевого слова new). Таким образом, вы должны сохранить свой экземпляр GuiceBundle в методе initialize как поле, а затем получить доступ к любой привязке Guice в методе run с помощью guiceBundle.getInjector().getInstance(), например:

public class MyApplication extends Application<MyConfig> {

  private GuiceBundle<MyConfig> guiceBundle;

  public static void main(String[] args) throws Exception {
    new MyApplication().run(args);
  }

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

    guiceBundle = GuiceBundle.builder()
                .printDiagnosticInfo()
                .printGuiceBindings()
                .enableAutoConfig(getClass().getPackage().getName())
                .modules(
                        new MyModule()
                )
                .build();

    bootstrap.addBundle(guiceBundle);
  }

  @Override
  public void run(MyConfig config, Environment environment) throws Exception {
    environment.lifecycle().manage(guiceBundle.getInjector().getInstance(Managed.class));
  }
}
1
Yurii Melnychuk 30 Мар 2021 в 16:17