quarkus: The repairing error message is not correct and bug of custom-quarkus-extension continue exists.

Describe the bug

I wrote the simple Quarkus extension to “play” with code. And after compile I receive:

"You cannot invoke beanInstance() directly on an object returned from the byte code recorder, you can only pass it back into the recorder as a parameter"

but i don’t invoke it into Recorder. Recorder is:

public class MergeableClassRecorder {

    Logger log = Logger.getLogger("org.mapins.cloud");


    void cacheMergeableClasses(MergeUtil mergeUtil, List<String> classPaths){
        log.debugf("List of mergeable items found by Quarkus deployment: %n%s", classPaths);

        classPaths.stream()
                .filter(Objects::nonNull)
                .map(
                    n -> {
                        try {return Class.forName(n);}
                        catch (Throwable ignore) { return null;}
                    })
                .filter(Objects::nonNull)
                .forEach(mergeUtil::cacheClass);

        log.infof("%n%s classes cached", classPaths);
    }
}

and @BuidlStep is:

    @BuildStep
    @Record(ExecutionTime.RUNTIME_INIT)
    void CacheAllMergeableClasses(List<MergeableClassCacheItem> classes,
                                  MergeableClassRecorder recorder,
                                  BeanContainerBuildItem containerItem){

        final List<String> listOfCachedClasses = classes.stream().map(e -> e.get().name().toString()).toList();

        MergeUtil mergeUtilObj = containerItem.getValue().beanInstance(MergeUtil.class);

        recorder.cacheMergeableClasses(mergeUtilObj, listOfCachedClasses);
    }

Earlier I try to make code by example like this:

    @BuildStep
    @Record(ExecutionTime.RUNTIME_INIT)
    void createMergeUtilClass(List<MergeableClassCacheItem> classes,
                              BuildProducer<AdditionalBeanBuildItem> additionalBeanProducer,
                              BuildProducer<BeanContainerListenerBuildItem> containerListener,
                              MergeableClassRecorder recorder) {

        additionalBeanProducer.produce(
                AdditionalBeanBuildItem.builder()
                        .addBeanClass(MergeUtil.class)
                        .setUnremovable()
                        .setDefaultScope(DotNames.SINGLETON)
                        .build()
        );

        final List<String> listOfCachedClasses = classes.stream().map(e -> e.get().name().toString()).toList();

        containerListener.produce(
                new BeanContainerListenerBuildItem(
                        recorder.cacheMergeableClasses(listOfCachedClasses)
                )
        );
    }

and this @Recorder:


@Recorder
public class MergeableClassRecorder {
    Logger log = Logger.getLogger("org.mapins.cloud");

    BeanContainerListener cacheMergeableClasses(List<String> classPaths){

        return container -> {
            log.debugf("List of mergeable items found by Quarkus deployment: %n%s", classPaths);

            MergeUtil mergeUtil = container.beanInstance(MergeUtil.class);

            classPaths.stream()
                    .filter(Objects::nonNull)
                    .map(
                            n -> {
                                try {return Class.forName(n);}
                                catch (Throwable ignore) { return null;}
                            })
                    .filter(Objects::nonNull)
                    .forEach(mergeUtil::cacheClass);

            log.infof("%n%s classes cached", classPaths);
        };
    }
}

but in result had other exception like:

Unable to serialize objects of type class org.test.mapins.MergeableClassRecorder$$Lambda$15232/0x000000080253b040 to bytecode as it has no default constructor

So what wrong I do?

Expected behavior

The program compiles without exceptions and continue to run the app.

Actual behavior

Fails with

Execution failed for task ':quarkusBuild'.
> io.quarkus.builder.BuildException: Build failure: Build failed due to errors
  	[error]: Build step org.test.mapins.MergeToolResourceProcessor#CacheAllMergeableClasses threw an exception: java.lang.RuntimeException: You cannot invoke beanInstance() directly on an object returned from the bytecode recorder, you can only pass it back into the recorder as a parameter
  	at io.quarkus.deployment.recording.BytecodeRecorderImpl$3.invoke(BytecodeRecorderImpl.java:444)
  	at io.quarkus.deployment.recording.BytecodeRecorderImpl$$ReturnValueProxy107.beanInstance(Unknown Source)
  	at org.test.mapins.MergeToolResourceProcessor.CacheAllMergeableClasses(MergeToolResourceProcessor.java:112)
  	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  	at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
  	at io.quarkus.builder.BuildContext.run(BuildContext.java:281)
  	at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
  	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
  	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
  	at java.base/java.lang.Thread.run(Thread.java:833)
  	at org.jboss.threads.JBossThread.run(JBossThread.java:501)

How to Reproduce?

Reproducer:

  1. Get code from https://github.com/Ferrociraptus/quarkus-bug-publication
  2. Install application to maven local and try to use or write the simple test for quarkus extension

Output of uname -a or ver

Linux ferri 6.2.13-100.fc36.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 26 20:11:01 UTC 2023 x86_64 GNU/Linux

Output of java -version

openjdk version “17.0.7” 2023-04-18 OpenJDK Runtime Environment (Red_Hat-17.0.7.0.7-4.fc38) (build 17.0.7+7) OpenJDK 64-Bit Server VM (Red_Hat-17.0.7.0.7-4.fc38) (build 17.0.7+7, mixed mode, sharing)

GraalVM version (if different from Java)

No response

Quarkus version or git rev

https://github.com/Ferrociraptus/quarkus-bug-publication

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

------------------------------------------------------------ Gradle 8.1.1 ------------------------------------------------------------ Build time: 2023-04-21 12:31:26 UTC Revision: 1cf537a851c635c364a4214885f8b9798051175b Kotlin: 1.8.10 Groovy: 3.0.15 Ant: Apache Ant™ version 1.10.11 compiled on July 10 2021 JVM: 17.0.7 (Red Hat, Inc. 17.0.7+7) OS: Linux 6.2.13-100.fc36.x86_64 amd64

Additional information

No response

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (9 by maintainers)

Commits related to this issue

Most upvoted comments

The problem turns out to be that you the recorder method is package private - if you turn it into a public method, it works just fine.

#34006 adds a warning against the type of use you are performing in order to try to nudge people towards the proper pattern usage.

Thanks a lot!