如何在Quarkus中为外部模块中的类创建Jandex索引

2022-09-01 06:04:53

首先,我有一个像这样的多模块maven层次结构:

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

所以现在来看看问题:

我正在服务模块中编写一个 JAX-RS 端点,该模块使用 api 库中的类。
当我开始夸库时,我收到这个警告:

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.Fruitcom.example.Carapi-library

因此,我认为我需要将它们添加到 application.properties 中的 Jandex 索引依赖项中。

但是,如何将Jandex索引依赖关系添加到quarkus中呢?


答案 1

Quarkus 会自动为主模块编制索引,但是,当您有其他模块包含 CDI bean、实体、序列化为 JSON 的对象时,您需要显式索引它们。

有几个不同的(易于实现的)选项可以做到这一点。

使用Jandex Maven插件

只需将以下内容添加到附加模块 pom.xml:

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

如果您的依赖项位于项目外部,并且您希望一劳永逸地生成索引,则这是最有利的选择。

使用 Gradle Jandex 插件

如果您使用的是Gradle,则有一个第三方插件允许生成Jandex索引:https://github.com/kordamp/jandex-gradle-plugin

添加一个空的 META-INF/bean.xml

如果在附加模块中添加一个空文件,这些类也会被索引。META-INF/beans.xmlsrc/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>


答案 2

编辑 (11/02/2020)

现在,在我的微服务中,我广泛使用注释中的属性。这是根据文档的属性说明:targetsRegisterForReflection

/**
 * 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进行反射时处理基本情况。注释将自行注册 POJO,但不会从 POJO 的方法注册返回类型。RegisterForReflection

更高级的方法是使用注释,如此处所述。我正在将其与Reflections库和定制的实用程序包装器一起使用:ReflectUtils@AutomaticFeature

现在我可以做更复杂的任务:

@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索引,添加bean.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();
}

推荐