quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.4k stars 2.57k forks source link

Updating DJL extension #37122

Open PetoMichalak opened 8 months ago

PetoMichalak commented 8 months ago

Describe the bug

Hello, We have been attempting to update the support for Quarkus in Deep Java Library (DJL), a package which provides an engine-agnostic Java framework for deep learning. The 'djl-demo' package (https://github.com/deepjavalibrary/djl-demo/blob/master/quarkus/example/README.md contains a Quarkus Extension for DJL, plus demo of deep java learning utilizing the Extension, but is based on a rather old Quarkus, 1.13.0.Final. We have been attempting to update the demo to the latest versions of DJL (0.24.0) and Quarkus 3.5.1. But it appears there has been a change in how the DJL's Quarkus Extension now needs to accomplish Dependency and Context injection of the DjlPredictorProducer Bean, the basis of the integration.

Are there any particular issues which need to be addressed when updating old Quarkus Extensions, from around 1.13.0.Final, to Quarkus 3.5.1?

Expected behavior

mvn clean install runs green

Actual behavior

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  44.162 s
[INFO] Finished at: 2023-10-31T14:49:19Z
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:3.5.0:build (default) on project quarkus-djl-example: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR] [error]: Build step io.quarkus.arc.deployment.ArcProcessor#validate threw an exception: jakarta.enterprise.inject.spi.DeploymentException: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type ai.djl.quarkus.runtime.DjlPredictorProducer and qualifiers [@Default]
[ERROR] - java member: org.acme.getting.started.DjlResource#predictorProducer
[ERROR] - declared on CLASS bean [types=[org.acme.getting.started.DjlResource, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.getting.started.DjlResource]
[ERROR] at io.quarkus.arc.processor.BeanDeployment.processErrors(BeanDeployment.java:1447)
[ERROR] at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:311)
[ERROR] at io.quarkus.arc.processor.BeanProcessor.initialize(BeanProcessor.java:158)
[ERROR] at io.quarkus.arc.deployment.ArcProcessor.validate(ArcProcessor.java:471)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR] at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR] at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:849)
[ERROR] at io.quarkus.builder.BuildContext.run(BuildContext.java:282)
[ERROR] at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
[ERROR] at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
[ERROR] at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
[ERROR] at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR] at org.jboss.threads.JBossThread.run(JBossThread.java:501)
[ERROR] Caused by: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type ai.djl.quarkus.runtime.DjlPredictorProducer and qualifiers [@Default]
[ERROR] - java member: org.acme.getting.started.DjlResource#predictorProducer
[ERROR] - declared on CLASS bean [types=[org.acme.getting.started.DjlResource, java.lang.Object], qualifiers=[@Default, @Any], target=org.acme.getting.started.DjlResource]
[ERROR] at io.quarkus.arc.processor.Beans.resolveInjectionPoint(Beans.java:478)
[ERROR] at io.quarkus.arc.processor.BeanInfo.init(BeanInfo.java:624)
[ERROR] at io.quarkus.arc.processor.BeanDeployment.init(BeanDeployment.java:299)
[ERROR] ... 13 more
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] [http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException](https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fcwiki.apache.org%2Fconfluence%2Fdisplay%2FMAVEN%2FMojoExecutionException&data=05%7C01%7CPeter.Michalak%40newcastle.ac.uk%7C5935f785b0c144681f3d08dbe5334ad8%7C9c5012c9b61644c2a91766814fbe3e87%7C1%7C0%7C638355780687271800%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=i24l7HBzsSX7PSODdS42Zfp8vFUqJdqq3iYpjpgvsIE%3D&reserved=0)

How to Reproduce?

  1. clone the DJL-extension
  2. Update versions in the pom.xml to the latest
    <properties>
    <compiler-plugin.version>3.11.0</compiler-plugin.version>
    <failsafe-plugin.version>${surefire-plugin.version}</failsafe-plugin.version>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <djl.version>0.24.0</djl.version>
    <quarkus.version>3.5.1</quarkus.version>
    <surefire-plugin.version>3.0.0</surefire-plugin.version>
    </properties>
  3. run mvn clean install

Output of uname -a or ver

Darwin nicd 22.5.0 Darwin Kernel Version 22.5.0: Thu Jun 8 22:22:22 PDT 2023; root:xnu-8796.121.3~7/RELEASE_X86_64 x86_64

Output of java -version

openjdk version "17.0.8" 2023-07-18 OpenJDK Runtime Environment Temurin-17.0.8+7 (build 17.0.8+7) OpenJDK 64-Bit Server VM Temurin-17.0.8+7 (build 17.0.8+7, mixed mode, sharing)

Quarkus version or git rev

3.5.1

Build tool (ie. output of mvnw --version or gradlew --version)

No response

Additional information

No response

geoand commented 8 months ago

The problem is likely that classes under the javax. package need to be moved to jakarta.

StuartWheater commented 8 months ago

We have had a bit of a breakthrough. A change was made, I wish I know that, which means that quarkus-arc now indications the cause of the issue:

[ERROR] Failed to execute goal io.quarkus:quarkus-maven-plugin:3.5.2:build (default) on project quarkus-djl-example: Failed to build quarkus application: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[ERROR]     [error]: Build step io.quarkus.arc.deployment.ArcProcessor#registerBeans threw an exception: jakarta.enterprise.inject.spi.DefinitionException: Producer method ai.djl.inference.Predictor<? extends java.lang.Object, ? extends java.lang.Object> predictor() declared on class ai.djl.quarkus.runtime.DjlPredictorProducer contains a parameterized type with a wildcard. This type is not a legal bean type according to CDI specification.
[ERROR]     at io.quarkus.arc.processor.Types.containsWildcard(Types.java:579)
[ERROR]     at io.quarkus.arc.processor.Types.getTypeClosure(Types.java:623)
[ERROR]     at io.quarkus.arc.processor.Types.getTypeClosure(Types.java:683)
[ERROR]     at io.quarkus.arc.processor.Types.getProducerMethodTypeClosure(Types.java:439)
[ERROR]     at io.quarkus.arc.processor.BeanDeployment.findBeans(BeanDeployment.java:1209)
[ERROR]     at io.quarkus.arc.processor.BeanDeployment.registerBeans(BeanDeployment.java:272)

So we need to restructure DjlPredictorProducer into a legal bean type according to CDI specification.

@ApplicationScoped
public class DjlPredictorProducer {

    private volatile ZooModel<?, ?> model;

    void initialize(ZooModel<?, ?> model) {
        this.model = model;
    }

    @Produces
    public ZooModel<?, ?> model() {
        return model;
    }

    @Produces
    public Predictor<?, ?> predictor() {
        return model.newPredictor();
    }
}