diff --git a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/DelegatingGrpcBeanBuildItem.java b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/DelegatingGrpcBeanBuildItem.java index 2ae80b07ba62e..8c040383eb5db 100644 --- a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/DelegatingGrpcBeanBuildItem.java +++ b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/DelegatingGrpcBeanBuildItem.java @@ -4,9 +4,9 @@ import io.quarkus.builder.item.MultiBuildItem; -final class DelegatingGrpcBeanBuildItem extends MultiBuildItem { - final ClassInfo generatedBean; - final ClassInfo userDefinedBean; +public final class DelegatingGrpcBeanBuildItem extends MultiBuildItem { + public final ClassInfo generatedBean; + public final ClassInfo userDefinedBean; DelegatingGrpcBeanBuildItem(ClassInfo generatedBean, ClassInfo userDefinedBean) { this.generatedBean = generatedBean; diff --git a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/devmode/GrpcDevConsoleProcessor.java b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/devmode/GrpcDevConsoleProcessor.java index e4f28696c1b49..0e22f8efce87c 100644 --- a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/devmode/GrpcDevConsoleProcessor.java +++ b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/devmode/GrpcDevConsoleProcessor.java @@ -11,6 +11,8 @@ import java.util.Map; import java.util.Set; +import javax.inject.Singleton; + import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; import org.jboss.jandex.IndexView; @@ -26,6 +28,10 @@ import io.grpc.MethodDescriptor.PrototypeMarshaller; import io.grpc.ServiceDescriptor; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.arc.deployment.GeneratedBeanBuildItem; +import io.quarkus.arc.deployment.GeneratedBeanGizmoAdaptor; +import io.quarkus.arc.deployment.UnremovableBeanBuildItem; +import io.quarkus.arc.profile.IfBuildProfile; import io.quarkus.arc.runtime.BeanLookupSupplier; import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildProducer; @@ -39,8 +45,12 @@ import io.quarkus.dev.console.DevConsoleManager; import io.quarkus.dev.testing.GrpcWebSocketProxy; import io.quarkus.devconsole.spi.DevConsoleRuntimeTemplateInfoBuildItem; +import io.quarkus.gizmo.ClassCreator; +import io.quarkus.gizmo.MethodCreator; +import io.quarkus.grpc.deployment.DelegatingGrpcBeanBuildItem; import io.quarkus.grpc.deployment.GrpcDotNames; import io.quarkus.grpc.protoc.plugin.MutinyGrpcGenerator; +import io.quarkus.grpc.runtime.devmode.DelegatingGrpcBeansStorage; import io.quarkus.grpc.runtime.devmode.GrpcDevConsoleRecorder; import io.quarkus.grpc.runtime.devmode.GrpcServices; import io.quarkus.vertx.http.deployment.NonApplicationRootPathBuildItem; @@ -57,6 +67,39 @@ public void devConsoleInfo(BuildProducer beans, new BeanLookupSupplier(GrpcServices.class))); } + @IfBuildProfile("dev") + @BuildStep + void prepareDelegatingBeanStorage( + List delegatingBeans, + BuildProducer unremovableBeans, + BuildProducer generatedBeans) { + String className = "io.quarkus.grpc.internal.DelegatingGrpcBeansStorageImpl"; + try (ClassCreator classCreator = ClassCreator.builder() + .className(className) + .classOutput(new GeneratedBeanGizmoAdaptor(generatedBeans)) + .superClass(DelegatingGrpcBeansStorage.class) + .build()) { + classCreator.addAnnotation(Singleton.class.getName()); + MethodCreator constructor = classCreator + .getMethodCreator(io.quarkus.gizmo.MethodDescriptor.ofConstructor(className)); + constructor.invokeSpecialMethod(io.quarkus.gizmo.MethodDescriptor.ofConstructor(DelegatingGrpcBeansStorage.class), + constructor.getThis()); + + for (DelegatingGrpcBeanBuildItem delegatingBean : delegatingBeans) { + constructor.invokeVirtualMethod( + io.quarkus.gizmo.MethodDescriptor.ofMethod(DelegatingGrpcBeansStorage.class, "addDelegatingMapping", + void.class, + String.class, String.class), + constructor.getThis(), + constructor.load(delegatingBean.userDefinedBean.name().toString()), + constructor.load(delegatingBean.generatedBean.name().toString())); + } + constructor.returnValue(null); + } + + unremovableBeans.produce(UnremovableBeanBuildItem.beanClassNames(className)); + } + @BuildStep(onlyIf = IsDevelopment.class) public void collectMessagePrototypes(CombinedIndexBuildItem index, // Dummy producer to ensure the build step is executed diff --git a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/DelegatingGrpcBeansStorage.java b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/DelegatingGrpcBeansStorage.java new file mode 100644 index 0000000000000..136260d7623b3 --- /dev/null +++ b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/DelegatingGrpcBeansStorage.java @@ -0,0 +1,18 @@ +package io.quarkus.grpc.runtime.devmode; + +import java.util.HashMap; +import java.util.Map; + +public abstract class DelegatingGrpcBeansStorage { + + private final Map userClassesByGeneratedBean = new HashMap<>(); + + @SuppressWarnings("unused") // used from generated code + public void addDelegatingMapping(String userClassName, String delegatingBeanName) { + userClassesByGeneratedBean.put(delegatingBeanName, userClassName); + } + + public String getUserClassName(String delegatingBeanName) { + return userClassesByGeneratedBean.get(delegatingBeanName); + } +} diff --git a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/GrpcServices.java b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/GrpcServices.java index 436e7a3088d32..dd075a6283408 100644 --- a/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/GrpcServices.java +++ b/extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/devmode/GrpcServices.java @@ -31,6 +31,9 @@ public class GrpcServices extends AbstractMap getInfos() { List services = GrpcServerRecorder.getServices(); List infos = new ArrayList<>(services.size()); @@ -70,7 +73,12 @@ public String getServiceClass() { if (definition.service instanceof Subclass) { instanceClass = instanceClass.getSuperclass(); } - return instanceClass.getName(); + + String grpcBeanClassName = instanceClass.getName(); + + String userClass = delegatingBeansMapping.getUserClassName(grpcBeanClassName); + + return userClass != null ? userClass : grpcBeanClassName; } public Collection> getMethods() {