Как создать индекс Jandex в Quarkus для классов во внешнем модуле

Прежде всего, у меня есть многомодульная иерархия Maven, например:

├── project (parent pom.xml)
│   ├── service
│   ├── api-library

Итак, теперь к проблеме:

Я пишу JAX-RS Endpoint в сервисном модуле, который использует классы в API-библиотеке.
Когда я начинаю quarkus, я получаю это предупреждение:

13:01:18,784 WARN  [io.qua.dep.ste.ReflectiveHierarchyStep] Unable to properly register the hierarchy of the following classes for reflection as they are not in the Jandex index:
- com.example.Fruit
- com.example.Car
Consider adding them to the index either by creating a Jandex index for your dependency or via quarkus.index-dependency properties.

Это к занятиям com.example.Fruit а также com.example.Car расположены в api-library модуль.

Поэтому я думаю, что мне нужно добавить их в индексную зависимость Jandex в application.properties.

Но как я могу добавить индексные зависимости Jandex в quarkus?

1 ответ

Решение

Quarkus автоматически индексирует основной модуль, но, когда у вас есть дополнительные модули, содержащие компоненты CDI, сущности, объекты, сериализованные как JSON, вам необходимо явно проиндексировать их.

Для этого есть несколько различных (простых в реализации) вариантов.

Использование плагина Jandex Maven

Просто добавьте следующее в ваш pom.xml:

<build>
  <plugins>
    <plugin>
      <groupId>org.jboss.jandex</groupId>
      <artifactId>jandex-maven-plugin</artifactId>
      <version>1.0.5</version>
      <executions>
        <execution>
          <id>make-index</id>
          <goals>
            <goal>jandex</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Это наиболее выгодный вариант, если ваша зависимость является внешней по отношению к вашему проекту, и вы хотите создать индекс раз и навсегда.

Добавление пустого META-INF/beans.xml

Если вы добавите пустой META-INF/beans.xml файл в вашем src/main/resources, классы также будут проиндексированы.

Классы будут проиндексированы самим Quarkus.

Индексирование других зависимостей

Если вы не можете изменить зависимость (например, подумайте о сторонней зависимости), вы все равно можете проиндексировать ее, добавив запись в свой application.properties:

quarkus.index-dependency.<name>.group-id=
quarkus.index-dependency.<name>.artifact-id=
quarkus.index-dependency.<name>.classifier=(this one is optional)

с <name> будучи именем, вы выбираете, чтобы определить свою зависимость.

Изменить (02.11.2020)

Сейчас в своих микросервисах я широко использую targets собственность от RegisterForReflectionаннотация. Это объяснение свойства согласно документации:

/**
 * Alternative classes that should actually be registered for reflection instead of the current class.
 *
 * This allows for classes in 3rd party libraries to be registered without modification or writing an
 * extension. If this is set then the class it is placed on is not registered for reflection, so this should
 * generally just be placed on an empty class that is not otherwise used.
 */

Это отлично работает с проектами на основе кваркуса и может обрабатывать базовые случаи, когда вы хотите зарегистрировать несколько POJO для отражения. ВRegisterForReflection аннотация зарегистрирует POJO самостоятельно, но не будет регистрировать типы, возвращаемые из методов POJO.

Более продвинутый способ - использовать @AutomaticFeatureаннотацию, как описано здесь. Я использую его с библиотекой отражений и с пользовательской оболочкой утилиты: ReflectUtils

Теперь я могу выполнять более сложные задачи:

@AutomaticFeature
@RegisterForReflection(targets = {
        com.hotelbeds.hotelapimodel.auto.convert.json.DateSerializer.class,
        TimeDeserializer.class,
        DateSerializer.class,
        TimeSerializer.class,
        RateSerializer.class,
})
public class HotelBedsReflection implements Feature {
    public static Logger log = Utils.findLogger(Reflections.class);

    @Override
    public void beforeAnalysis(BeforeAnalysisAccess access) {
        ReflectUtils.registerPackage(LanguagesRQ.class.getPackage().getName(), Object.class);
        ReflectUtils.registerPackage(AvailabilityRQ.class.getPackage().getName(), Object.class);
        ReflectUtils.registerPackage(Occupancy.class.getPackage().getName(), Object.class);
    }
}

Первоначальный ответ

Я попытался добавить индекс Jandex, добавить beans.xml, а также для индексирования других зависимостей, как описано в ответе @emre-iÅŸÄ ± k, однако мой сторонний класс (EpAutomationRs) не был зарегистрирован для отражения в собственном режиме. В итоге я нашел быстрое и грязное решение для его регистрации (см. Ниже). Я создал неиспользуемую конечную точку REST JSON, которая возвращает класс.

/**
 * the purpose of this method is to register for reflection EpAutomationRs class
 *
 * @return
 */
@GET
@Path(GET_EMPTY_RS)
@Produces(MediaType.APPLICATION_JSON)
public EpAutomationRs entry() {
    return new EpAutomationRs();
}

Для пользователей Gradle вы можете использовать этот плагин в build.gradle модуля, от которого вы зависите.

Другие вопросы по тегам