Как зарегистрировать реализацию SPI при запуске exec:java

Я пытаюсь заставить работать VertX Mertrics при запуске через подключаемый модуль exec:java Maven. .

Все работает, как и ожидалось, когда я упаковываю приложение в фатжар и запускаю его с помощью java -jar fat.jar -conf config.json -Dvertx.metrics.options.enabled=true

Когда я запускаю его с помощью mvn clean package exec:java -DskipTests, я вижу: 2016-03-22 18:39:58.833 WARN i.v.c.i.VertxImpl:348 - Metrics has been set to enabled but no VertxMetricsFactory found on classpath

Я пробовал несколько подходов:

  • добавление io.vertx:vertx-dropwizard-metrics:3.2.1 в качестве зависимости компиляции
  • создать внутреннюю реализацию метрик и зарегистрировать ее с помощью файла src/main/resources/META-INF/services/io.vertx.core.spi.VertxMetricsFactory (перепроверил, что он действительно скопирован в target/classes/META-INF/services/io.vertx.core.spi.VertxMetricsFactory)
  • также добавление ${basedir}/src/main/resources в качестве дополнительного элемента пути к классам (в дополнение к предыдущему пункту)

Я дважды проверил в отладчике, что ServiceLoader на самом деле возвращает пустой итератор.

Это моя конфигурация exec-плагина: <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <configuration> <additionalClasspathElements> <element>${basedir}/src/main/resources</element> </additionalClasspathElements> <mainClass>io.vertx.core.Launcher</mainClass> <commandlineArgs>run ${vertx.mainVerticle} -conf ${vertx.config}</commandlineArgs> <systemProperties> <systemProperty> <key>vertx.logger-delegate-factory-class-name</key> <value>io.vertx.core.logging.SLF4JLogDelegateFactory</value> </systemProperty> <systemProperty> <key>vertx.metrics.options.enabled</key> <value>true</value> </systemProperty> </systemProperties> </configuration> </plugin>

Вот конфигурация exec:exec, которая работает, но я хочу понять, возможно ли и почему (не)возможно сделать это с exec:java

<profile> <id>exec</id> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <execution> <goals> <goal>exec</goal> </goals> <phase>process-classes</phase> <configuration> <executable>java</executable> <arguments> <argument>-Dvertx.metrics.options.enabled=true</argument> <argument>-Dvertx.logger-delegate-factory-class-name=${vertx.logger-delegate-factory-class-name}</argument> <argument>-classpath</argument> <classpath /> <argument>io.vertx.core.Launcher</argument> <argument>run</argument> <argument>${vertx.mainVerticle}</argument> <argument>-conf</argument> <argument>${vertx.config}</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile>


person Jakub Bochenski    schedule 22.03.2016    source источник


Ответы (1)


Вы пробовали exec:exec вместо exec:java?

exec:exec выполняется в отдельном процессе, и это может решить вашу проблему.

ServiceLoader использует загрузчик классов приложения для загрузки любых классов, перечисленных в META-INF/services. Вот почему ServiceLoader часто не работает в средах с пользовательскими загрузчиками классов (например, OSGi).

Поскольку Maven создает свой собственный загрузчик классов для каждого подключаемого модуля Maven, даже если вы объявите зависимости времени компиляции, содержащие ваш SPI, эти классы будут видны только загрузчику классов Maven, но не загрузчику классов приложения.

person Harald Wellmann    schedule 22.03.2016
comment
Я знаю, что мог бы использовать exec:exec (поскольку это было бы эквивалентно запуску java непосредственно из CLI). Мне было бы интересно узнать, как именно загрузчик классов Maven исключает использование ServiceLoader. Где я могу найти подробную информацию о том, как должен работать пользовательский загрузчик классов? Что, если я добавлю SPI в настройки плагинов? - person Jakub Bochenski; 23.03.2016
comment
Особых требований к пользовательскому загрузчику классов нет. Это разница между ServiceLoader.loadClass(Class) и ServiceLoader.loadClass(Class, ClassLoader). Если потребитель SPI использует первый вариант без явного загрузчика классов, то будет использоваться системный загрузчик классов. - person Harald Wellmann; 24.03.2016