【问题标题】:Micronaut DI does not work with Graal Native Image built in MavenMicronaut DI 不适用于 Maven 中内置的 Graal Native Image
【发布时间】:2021-03-21 18:59:47
【问题描述】:

我在 Micronaut 上有一个最小的应用程序,它看起来像这样:

@Introspected
public class BookRequestHandler extends MicronautRequestHandler<Book, BookSaved> {

    @Inject
    private BookService service;

    @Override
    public BookSaved execute(Book input) {
        return service.process(input);
    }

}

@Singleton
@Introspected
public class BookService {

  public BookSaved process(Book input) {
    BookSaved bookSaved = new BookSaved();
    bookSaved.setName(input.getName());
    bookSaved.setIsbn(UUID.randomUUID().toString());
    return bookSaved;
  }

}
  • 运行时和 DTO 类。

我的项目使用 Micronaut 的插件成功构建并在 Graal Native Image 上运行 - ./mvnm

但我正在尝试使用 native-image 直接通过 Docker 容器构建。图像正在运行!但是如果我尝试调用 lambda,我会收到一个错误,即找不到依赖注入的字段:( 此文件是从 Micronaut 的 Gradle 版本重新制作的:

# STEP 1: Packaging project .jar in Docker image 'builder'
FROM maven:3.6.3-jdk-8 as build

COPY . /home/application
WORKDIR /home/application

RUN mvn clean package

# STEP 2: Downloading Graal and C libraries in Docker image 'graalvm'
FROM amazonlinux:2018.03 as graal

ENV LANG en_US.UTF-8
ENV JDK_VERSION java8
ENV GRAAL_VERSION 21.0.0.2
ENV GRAAL_FILENAME graalvm-ce-${JDK_VERSION}-linux-amd64-${GRAAL_VERSION}.tar.gz

RUN yum install -y gcc gcc-c++ libc6-dev zlib1g-dev curl bash zlib zlib-devel zip
RUN curl -4 -L https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-${GRAAL_VERSION}/${GRAAL_FILENAME} -o /tmp/${GRAAL_FILENAME}
RUN tar -zxvf /tmp/${GRAAL_FILENAME} -C /tmp
RUN mv /tmp/graalvm-ce-${JDK_VERSION}-${GRAAL_VERSION} /usr/lib/graalvm
RUN rm -rf /tmp/*

CMD ["/usr/lib/graalvm/bin/native-image"]

# STEP 3: Building and zipping a Native Image with bootstrap file
FROM graal

COPY --from=build /home/application/ /home/application/
WORKDIR /home/application

RUN /usr/lib/graalvm/bin/gu install native-image
RUN /usr/lib/graalvm/bin/native-image --no-fallback --no-server -jar target/MicronautGraal-0.1.jar -H:Name=micronaut-graal -H:Class=com.example.BookLambdaRuntime
RUN chmod 777 bootstrap
RUN chmod 777 micronaut-graal
RUN zip -j micronaut-graal.zip bootstrap micronaut-graal

EXPOSE 8080
ENTRYPOINT ["/home/application/complete"]

错误本身:

io.micronaut.context.exceptions.DependencyInjectionException: Failed to inject value for field [service] of class: com.example.BookRequestHandler
Message: Error setting field value: No field 'service' found for type: com.example.BookRequestHandler

我确定问题不在代码中,因为它将通过 ./mvnm 插件运行和工作。我在应用程序构建中遗漏了什么吗?我通过插件获得的图片比直接通过 native-image 多 500kb。

我非常感谢任何帮助。谢谢!

【问题讨论】:

    标签: java docker maven micronaut graalvm


    【解决方案1】:

    这是 JVM 的限制,我们不能在不使用反射的情况下注入私有字段。

    你有两个选择:

    1. 将字段包设为私有而不是私有
    2. 将@ReflectiveAccess 添加到字段中以生成必要的graal 反射元数据

    【讨论】:

      【解决方案2】:

      在添加注释处理器路径 - graal 并显式声明验证并在继承器中注入后,问题就消失了:

      <annotationProcessorPaths>
        <path>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-graal</artifactId>
          <version>${micronaut.version}</version>
        </path>
        <path>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-inject-java</artifactId>
          <version>${micronaut.version}</version>
        </path>
        <path>
          <groupId>io.micronaut</groupId>
          <artifactId>micronaut-validation</artifactId>
          <version>${micronaut.version}</version>
        </path>
      </annotationProcessorPaths>
      

      【讨论】:

        【解决方案3】:

        使用时应考虑通过构造函数进行注入,这是 GraalVM 原生应用程序的推荐方式。

        @Introspected
        public class BookRequestHandler extends MicronautRequestHandler<Book, BookSaved> {
        
            private final BookService service;
        
            @Inject
            public BookRequestHandler(BookService service) {
              this.service = service;
            }
        
            @Override
            public BookSaved execute(Book input) {
                return service.process(input);
            }
        }
        

        【讨论】:

        • 由于 Micronaut 初始化 MicronautRequestHandler 实例的方式,构造函数注入不起作用。扩展 AbstractMicronautLambdaRuntime 的入口点类创建请求处理程序的实例并通过它获取应用程序上下文(请参阅 MicronautRequestHandler 的空构造函数)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-27
        • 2020-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多