diff --git a/testsuite/integration/basic/pom.xml b/testsuite/integration/basic/pom.xml index bbfae0389760..256259077de5 100644 --- a/testsuite/integration/basic/pom.xml +++ b/testsuite/integration/basic/pom.xml @@ -606,6 +606,11 @@ wildfly-naming-client test + + org.wildfly + wildfly-weld-common + test + org.wildfly.core wildfly-cli @@ -782,6 +787,11 @@ wildfly-core-management-subsystem test + + org.wildfly.core + wildfly-subsystem + test + org.wildfly.discovery wildfly-discovery-client @@ -816,6 +826,11 @@ jakarta.servlet.jsp-api test + + org.kohsuke.metainf-services + metainf-services + test + @@ -921,6 +936,32 @@ weldTest bootableJar + + create-module-cdidBcExtensionModule + + jar + + ${bootable-jar-maven-jar-plugin.create.modules.phase} + + ${project.build.directory}/extraContent/modules/test/build-compatible-extension/main + ${project.build.testOutputDirectory} + + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension$BCEDeploymentUnitProcessor.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension$BCESubsystemModel.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension$BCESubsystemRegistrar.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension$BCESubsystemRegistrar$1.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension$BCESubsystemRegistrar$1$1.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension$BCESubsystemSchema.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredExtension.class + **/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredBean.class + **/META-INF/services/jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension + **/META-INF/services/org.jboss.as.controller.Extension + **/META-INF/beans.xml + + bce-extension + bootableJar + create-module-test-alpha diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension.java new file mode 100644 index 000000000000..5f5810265082 --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/BCEExtension.java @@ -0,0 +1,169 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.weld.extensions.buildcompatible.subsystem; + +import org.jboss.as.controller.Extension; +import org.jboss.as.controller.ModelVersion; +import org.jboss.as.controller.OperationContext; +import org.jboss.as.controller.OperationFailedException; +import org.jboss.as.controller.PathElement; +import org.jboss.as.controller.PersistentResourceXMLDescription; +import org.jboss.as.controller.PersistentSubsystemSchema; +import org.jboss.as.controller.ResourceDefinition; +import org.jboss.as.controller.ResourceRegistration; +import org.jboss.as.controller.SubsystemModel; +import org.jboss.as.controller.SubsystemRegistration; +import org.jboss.as.controller.SubsystemSchema; +import org.jboss.as.controller.capability.CapabilityServiceSupport; +import org.jboss.as.controller.descriptions.ParentResourceDescriptionResolver; +import org.jboss.as.controller.descriptions.SubsystemResourceDescriptionResolver; +import org.jboss.as.controller.registry.ManagementResourceRegistration; +import org.jboss.as.controller.registry.OperationEntry; +import org.jboss.as.controller.xml.VersionedNamespace; +import org.jboss.as.server.AbstractDeploymentChainStep; +import org.jboss.as.server.DeploymentProcessorTarget; +import org.jboss.as.server.deployment.Attachments; +import org.jboss.as.server.deployment.DeploymentPhaseContext; +import org.jboss.as.server.deployment.DeploymentUnit; +import org.jboss.as.server.deployment.DeploymentUnitProcessingException; +import org.jboss.as.server.deployment.DeploymentUnitProcessor; +import org.jboss.as.server.deployment.Phase; +import org.jboss.as.version.Stability; +import org.jboss.as.weld.Capabilities; +import org.jboss.as.weld.WeldCapability; +import org.jboss.dmr.ModelNode; +import org.jboss.staxmapper.IntVersion; +import org.kohsuke.MetaInfServices; +import org.wildfly.subsystem.SubsystemConfiguration; +import org.wildfly.subsystem.SubsystemExtension; +import org.wildfly.subsystem.SubsystemPersistence; +import org.wildfly.subsystem.resource.ManagementResourceRegistrar; +import org.wildfly.subsystem.resource.ManagementResourceRegistrationContext; +import org.wildfly.subsystem.resource.ResourceDescriptor; +import org.wildfly.subsystem.resource.SubsystemResourceDefinitionRegistrar; +import org.wildfly.subsystem.resource.operation.ResourceOperationRuntimeHandler; + +@MetaInfServices(Extension.class) +public class BCEExtension extends SubsystemExtension { + + public BCEExtension() { + super(SubsystemConfiguration.of(BCESubsystemRegistrar.NAME, BCESubsystemModel.CURRENT, + BCESubsystemRegistrar::new), SubsystemPersistence.of(BCESubsystemSchema.CURRENT)); + } + + /** + * Model for the 'bce' subsystem. + */ + public enum BCESubsystemModel implements SubsystemModel { + VERSION_1_0_0(1, 0, 0), + ; + + static final BCESubsystemModel CURRENT = VERSION_1_0_0; + + private final ModelVersion version; + + BCESubsystemModel(int major, int minor, int micro) { + this.version = ModelVersion.create(major, minor, micro); + } + + @Override + public ModelVersion getVersion() { + return this.version; + } + } + + /** + * Schema for the 'bce' subsystem. + */ + public enum BCESubsystemSchema implements PersistentSubsystemSchema { + + VERSION_1_0(1, 0, Stability.DEFAULT), + ; + + static final BCESubsystemSchema CURRENT = VERSION_1_0; + + private final VersionedNamespace namespace; + + BCESubsystemSchema(int major, int minor, Stability stability) { + this.namespace = SubsystemSchema.createSubsystemURN(BCESubsystemRegistrar.NAME, stability, new IntVersion(major, minor)); + } + + @Override + public VersionedNamespace getNamespace() { + return this.namespace; + } + + @Override + public Stability getStability() { + return Stability.DEFAULT; + } + + @Override + public PersistentResourceXMLDescription getXMLDescription() { + PersistentResourceXMLDescription.Factory factory = PersistentResourceXMLDescription.factory(this); + return factory.builder(BCESubsystemRegistrar.PATH).build(); + } + } + + /** + * Registrar for the 'bce' subsystem root resource. + */ + private static final class BCESubsystemRegistrar implements SubsystemResourceDefinitionRegistrar { + + static final String NAME = "bce"; + static final PathElement PATH = SubsystemResourceDefinitionRegistrar.pathElement(NAME); + static final ParentResourceDescriptionResolver RESOLVER = new SubsystemResourceDescriptionResolver(NAME, BCESubsystemRegistrar.class); + + @Override + public ManagementResourceRegistration register(SubsystemRegistration parent, ManagementResourceRegistrationContext context) { + ManagementResourceRegistration registration = parent.registerSubsystemModel(ResourceDefinition.builder(ResourceRegistration.of(PATH), RESOLVER).build()); + ResourceDescriptor descriptor = ResourceDescriptor.builder(RESOLVER) + .withAddOperationRestartFlag(OperationEntry.Flag.RESTART_ALL_SERVICES) + .withRemoveOperationRestartFlag(OperationEntry.Flag.RESTART_ALL_SERVICES) + .withRuntimeHandler(new ResourceOperationRuntimeHandler() { + @Override + public void addRuntime(OperationContext context, ModelNode model) { + if (context.isBooting()) { + context.addStep(new AbstractDeploymentChainStep() { + @Override + protected void execute(DeploymentProcessorTarget processorTarget) { + processorTarget.addDeploymentProcessor(NAME, Phase.INSTALL, Phase.INSTALL_WELD_DEPLOYMENT, new BCEDeploymentUnitProcessor()); + + } + }, OperationContext.Stage.RUNTIME); + } else { + context.reloadRequired(); + } + } + + @Override + public void removeRuntime(OperationContext context, ModelNode model) throws OperationFailedException { + context.reloadRequired(); + } + }) + .build(); + ManagementResourceRegistrar.of(descriptor).register(registration); + return registration; + } + } + + private static final class BCEDeploymentUnitProcessor implements DeploymentUnitProcessor { + + @Override + public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException { + final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit(); + try { + final WeldCapability weldCapability = deploymentUnit.getAttachment(Attachments.CAPABILITY_SERVICE_SUPPORT) + .getCapabilityRuntimeAPI(Capabilities.WELD_CAPABILITY_NAME, WeldCapability.class); + weldCapability.registerBuildCompatibleExtension(RegisteredExtension.class, deploymentUnit); + } catch (CapabilityServiceSupport.NoSuchCapabilityException e) { + throw new RuntimeException(e); + } + } + } + + +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/DummyBean.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/DummyBean.java new file mode 100644 index 000000000000..623ab11b6040 --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/DummyBean.java @@ -0,0 +1,12 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.weld.extensions.buildcompatible.subsystem; + +import jakarta.enterprise.context.Dependent; + +@Dependent +public class DummyBean { +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredBean.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredBean.java new file mode 100644 index 000000000000..b9b59db56cda --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredBean.java @@ -0,0 +1,10 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.weld.extensions.buildcompatible.subsystem; + +// no bean defining annotation, processed via RegisteredExtension +public class RegisteredBean { +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredExtension.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredExtension.java new file mode 100644 index 000000000000..17b6e6d6ad33 --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/RegisteredExtension.java @@ -0,0 +1,18 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.weld.extensions.buildcompatible.subsystem; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; +import jakarta.enterprise.inject.build.compatible.spi.Discovery; +import jakarta.enterprise.inject.build.compatible.spi.ScannedClasses; + +public class RegisteredExtension implements BuildCompatibleExtension { + + @Discovery + public void discovery(ScannedClasses sc) { + sc.add(RegisteredBean.class.getName()); + } +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/SubsystemBceRegistrationTest.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/SubsystemBceRegistrationTest.java new file mode 100644 index 000000000000..a711b0d69736 --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/SubsystemBceRegistrationTest.java @@ -0,0 +1,86 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.weld.extensions.buildcompatible.subsystem; + +import jakarta.inject.Inject; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.as.arquillian.api.ServerSetup; +import org.jboss.as.arquillian.api.ServerSetupTask; +import org.jboss.as.arquillian.container.ManagementClient; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.as.test.module.util.TestModule; +import org.jboss.as.test.shared.ServerReload; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.net.URL; + +@RunWith(Arquillian.class) +@ServerSetup(SubsystemBceRegistrationTest.SetupTask.class) +public class SubsystemBceRegistrationTest { + + @Deployment + public static WebArchive getDeployment() throws Exception { + return ShrinkWrap.create(WebArchive.class) + .addClasses(SubsystemBceRegistrationTest.class, DummyBean.class, TestModule.class, RegisteredBean.class) + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Inject + DummyBean dummyBean; + + @Inject + RegisteredBean registeredBean; + + @Test + public void testBceRegisteredAndExecuted() { + // check plain WAR deployment + Assert.assertNotNull(dummyBean); + + // verify BCE was executed; if so, RegisteredBean would now be resolvable + Assert.assertNotNull(registeredBean); + } + + public static class SetupTask implements ServerSetupTask { + private static final String MODULE_NAME = "build-compatible-extension"; + private static TestModule testModule; + + @Override + public void setup(ManagementClient managementClient, String containerId) throws Exception { + URL url = BCEExtension.class.getResource(MODULE_NAME + "-module.xml"); + File moduleXmlFile = new File(url.toURI()); + testModule = new TestModule("test." + MODULE_NAME, moduleXmlFile); + testModule.addResource("bce-extension.jar") + .addClasses(BCEExtension.class, RegisteredExtension.class, RegisteredBean.class) + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml") + .addAsServiceProvider(org.jboss.as.controller.Extension.class, BCEExtension.class); + testModule.create(); + + managementClient.getControllerClient().execute(Util.createAddOperation(PathAddress.pathAddress("extension", "test." + MODULE_NAME))); + managementClient.getControllerClient().execute(Util.createAddOperation(PathAddress.pathAddress("subsystem", "bce"))); + + ServerReload.executeReloadAndWaitForCompletion(managementClient); + } + + @Override + public void tearDown(ManagementClient managementClient, String containerId) throws Exception { + + managementClient.getControllerClient().execute(Util.createRemoveOperation(PathAddress.pathAddress("subsystem", "bce"))); + managementClient.getControllerClient().execute(Util.createRemoveOperation(PathAddress.pathAddress("extension", "test." + MODULE_NAME))); + + testModule.remove(); + + ServerReload.executeReloadAndWaitForCompletion(managementClient); + } + } +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/build-compatible-extension-module.xml b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/build-compatible-extension-module.xml new file mode 100644 index 000000000000..ed32ee059842 --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/weld/extensions/buildcompatible/subsystem/build-compatible-extension-module.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/integration/basic/src/test/modules/test/build-compatible-extension/main/module.xml b/testsuite/integration/basic/src/test/modules/test/build-compatible-extension/main/module.xml new file mode 100644 index 000000000000..3822eb68ecfe --- /dev/null +++ b/testsuite/integration/basic/src/test/modules/test/build-compatible-extension/main/module.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/weld/common/src/main/java/org/jboss/as/weld/WeldCapability.java b/weld/common/src/main/java/org/jboss/as/weld/WeldCapability.java index b40831d7ab35..1464cbe1800c 100644 --- a/weld/common/src/main/java/org/jboss/as/weld/WeldCapability.java +++ b/weld/common/src/main/java/org/jboss/as/weld/WeldCapability.java @@ -6,6 +6,8 @@ package org.jboss.as.weld; import java.util.function.Supplier; + +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.inject.spi.Extension; @@ -26,15 +28,28 @@ public interface WeldCapability { * Registers a CDI Portable Extension for the {@link DeploymentUnit} passed as argument to * this method. *

- * The extension is registered if only if the DeploymentUnit is part of a Weld Deployment. Specifically, + * The extension is registered if and only if the DeploymentUnit is part of a Weld Deployment. Specifically, * if a call to {@link #isPartOfWeldDeployment(DeploymentUnit)} using the DeploymentUnit argument - * returns {@code true}. Otherwise this method will return immediately. + * returns {@code true}. Otherwise, this method will return immediately. * * @param extension An instance of the CDI portable extension to add. * @param unit The deployment unit where the extension will be registered. */ void registerExtensionInstance(final Extension extension, final DeploymentUnit unit); + /** + * Registers a CDI Build Compatible Extension for the {@link DeploymentUnit} passed as argument to + * this method. + *

+ * The extension is registered if and only if the DeploymentUnit is part of a Weld Deployment. Specifically, + * if a call to {@link #isPartOfWeldDeployment(DeploymentUnit)} using the DeploymentUnit argument + * returns {@code true}. Otherwise, this method will return immediately. + * + * @param extension An instance of the CDI portable extension to add. + * @param unit The deployment unit where the extension will be registered. + */ + void registerBuildCompatibleExtension(final Class extension, final DeploymentUnit unit); + /** * Adds the Bean Manager service associated to the {@link DeploymentUnit} to ServiceBuilder passed as argument. *

diff --git a/weld/common/src/main/java/org/jboss/as/weld/deployment/WeldPortableExtensions.java b/weld/common/src/main/java/org/jboss/as/weld/deployment/WeldPortableExtensions.java index 4174c91c1086..e7be9fffcf38 100644 --- a/weld/common/src/main/java/org/jboss/as/weld/deployment/WeldPortableExtensions.java +++ b/weld/common/src/main/java/org/jboss/as/weld/deployment/WeldPortableExtensions.java @@ -5,11 +5,15 @@ package org.jboss.as.weld.deployment; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; +import java.util.function.Function; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; import jakarta.enterprise.inject.spi.Extension; import org.jboss.as.server.deployment.AttachmentKey; @@ -18,14 +22,16 @@ import org.jboss.as.weld.logging.WeldLogger; import org.jboss.weld.bootstrap.spi.Metadata; import org.jboss.weld.bootstrap.spi.helpers.MetadataImpl; +import org.jboss.weld.exceptions.IllegalArgumentException; /** - * Container class that is attached to the top level deployment that holds all portable extension metadata. + * Container class that is attached to the top level deployment that holds all portable and build compatible extensions + * metadata. *

- * A portable extension may be available to multiple deployment class loaders, however for each PE we + * A CDI extension may be available to multiple deployment class loaders, however for each PE we * only want to register a single instance. *

- * This container provides a mechanism for making sure that only a single PE of a given type is registered. + * This container provides a mechanism for making sure that only a single PE/BCE of a given type is registered. * * @author Stuart Douglas * @@ -52,6 +58,7 @@ public static WeldPortableExtensions getPortableExtensions(final DeploymentUnit } private final Map, Metadata> extensions = new HashMap<>(); + private final Collection> buildCompatibleExtensions = new ArrayList<>(); public synchronized void tryRegisterExtension(final Class extensionClass, final DeploymentUnit deploymentUnit) throws DeploymentUnitProcessingException { if (!Extension.class.isAssignableFrom(extensionClass)) { @@ -72,8 +79,36 @@ public synchronized void registerExtensionInstance(final Extension extension, fi extensions.put(extension.getClass(), new MetadataImpl<>(extension, deploymentUnit.getName())); } + public synchronized void registerBuildCompatibleExtension(final Class extension) { + buildCompatibleExtensions.add(extension); + } + + /** + * If there was at least one build compatible extension discovered or registered, this method will add a portable + * extension allowing their execution. It is a no-op if there are no build compatible extensions. + * + * @param extensionCreator a function that can create an instance of the {{@code LiteExtensionTranslator}} from given collection of found BCEs + * @throws IllegalArgumentException if the deployment unit parameter equals null + */ + public synchronized void registerLiteExtensionTranslatorIfNeeded(Function>, + Extension> extensionCreator, DeploymentUnit deploymentUnit) throws IllegalArgumentException { + if (deploymentUnit == null) { + throw WeldLogger.ROOT_LOGGER.incorrectBceTranslatorSetup(); + } + + // only register if we found any BCE be it via discovery or manual registration + if (!buildCompatibleExtensions.isEmpty()) { + registerExtensionInstance(extensionCreator.apply(getBuildCompatibleExtensions()), deploymentUnit); + } + } + public Collection> getExtensions() { return new HashSet<>(extensions.values()); } + public List> getBuildCompatibleExtensions() { + return new ArrayList<>(buildCompatibleExtensions); + } + + } diff --git a/weld/common/src/main/java/org/jboss/as/weld/logging/WeldLogger.java b/weld/common/src/main/java/org/jboss/as/weld/logging/WeldLogger.java index e5e8a254bbb5..cedff39b688c 100644 --- a/weld/common/src/main/java/org/jboss/as/weld/logging/WeldLogger.java +++ b/weld/common/src/main/java/org/jboss/as/weld/logging/WeldLogger.java @@ -267,4 +267,7 @@ public interface WeldLogger extends BasicLogger { @Message(id = 63, value = "Original %s does not have a module") IllegalArgumentException originalClassDoesNotHaveAModule(Class originalClass); + + @Message(id = 64, value = "Incorrect setup for Weld's LiteExtensionTranslator initialization; a deployment unit has to be specified") + IllegalArgumentException incorrectBceTranslatorSetup(); } diff --git a/weld/subsystem/src/main/java/org/jboss/as/weld/WeldCapabilityImpl.java b/weld/subsystem/src/main/java/org/jboss/as/weld/WeldCapabilityImpl.java index 9e96f6568d81..f598c5d94897 100644 --- a/weld/subsystem/src/main/java/org/jboss/as/weld/WeldCapabilityImpl.java +++ b/weld/subsystem/src/main/java/org/jboss/as/weld/WeldCapabilityImpl.java @@ -6,6 +6,7 @@ import java.util.function.Supplier; +import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension; import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.inject.spi.Extension; @@ -33,6 +34,14 @@ public void registerExtensionInstance(final Extension extension, final Deploymen } } + @Override + public void registerBuildCompatibleExtension(Class extension, DeploymentUnit unit) { + if (isPartOfWeldDeployment(unit)) { + WeldPortableExtensions extensions = WeldPortableExtensions.getPortableExtensions(unit); + extensions.registerBuildCompatibleExtension(extension); + } + } + @Override public Supplier addBeanManagerService(final DeploymentUnit unit, final ServiceBuilder serviceBuilder) { if (isPartOfWeldDeployment(unit)) { diff --git a/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldDeploymentProcessor.java b/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldDeploymentProcessor.java index 8660dd84d4f1..051b1d176034 100644 --- a/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldDeploymentProcessor.java +++ b/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldDeploymentProcessor.java @@ -70,6 +70,7 @@ import org.jboss.weld.config.ConfigurationKey; import org.jboss.weld.configuration.spi.ExternalConfiguration; import org.jboss.weld.configuration.spi.helpers.ExternalConfigurationBuilder; +import org.jboss.weld.lite.extension.translator.LiteExtensionTranslator; import org.jboss.weld.manager.api.ExecutorServices; import org.jboss.weld.security.spi.SecurityServices; import org.jboss.weld.transaction.spi.TransactionServices; @@ -213,8 +214,11 @@ public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitPro additional.getServices().add(entry.getKey(), Reflections.cast(entry.getValue())); } } - - final Collection> extensions = WeldPortableExtensions.getPortableExtensions(deploymentUnit).getExtensions(); + WeldPortableExtensions portableExtensions = WeldPortableExtensions.getPortableExtensions(deploymentUnit); + // register LiteExtensionTranslator as the last extension so that we have all info on registered BCEs + // NOTE: I chose to register it under the dep. unit of the top level deployment, using its CL, not sure if this is correct + portableExtensions.registerLiteExtensionTranslatorIfNeeded(classes -> new LiteExtensionTranslator(classes, module.getClassLoader()), deploymentUnit); + final Collection> extensions = portableExtensions.getExtensions(); final WeldDeployment deployment = new WeldDeployment(beanDeploymentArchives, extensions, module, subDeploymentLoaders, deploymentUnit, rootBeanDeploymentModule, eeModuleDescriptors); diff --git a/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldPortableExtensionProcessor.java b/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldPortableExtensionProcessor.java index 37f455758e46..ea68bbe25f40 100644 --- a/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldPortableExtensionProcessor.java +++ b/weld/subsystem/src/main/java/org/jboss/as/weld/deployment/processors/WeldPortableExtensionProcessor.java @@ -28,7 +28,6 @@ import org.jboss.as.weld.logging.WeldLogger; import org.jboss.modules.Module; import org.jboss.vfs.VFSUtils; -import org.jboss.weld.lite.extension.translator.LiteExtensionTranslator; import org.wildfly.security.manager.WildFlySecurityManager; /** @@ -74,14 +73,9 @@ private void loadAttachments(Module module, DeploymentUnit deploymentUnit, WeldP // load class and register for portable extensions Collection> loadedPortableExtensions = loadExtensions(module, portableExtensionServices, Object.class); registerPortableExtensions(deploymentUnit, extensions, loadedPortableExtensions); - // load class and register for portable extensions - // if there is at least one, add a portable extension processing them - List> loadedBuildCompatExtensions = - loadExtensions(module, buildCompatibleExtensionServices, BuildCompatibleExtension.class); - if (!loadedBuildCompatExtensions.isEmpty()) { - Extension extension = new LiteExtensionTranslator(loadedBuildCompatExtensions, module.getClassLoader()); - // NOTE: I chose to register it under the same dep. unit as other extensions, not sure if this is correct - extensions.registerExtensionInstance(extension, deploymentUnit); + // load class and register for discovered build compatible extensions + for (Class extensionClass : loadExtensions(module, buildCompatibleExtensionServices, BuildCompatibleExtension.class)) { + extensions.registerBuildCompatibleExtension(extensionClass); } } catch (IOException e) { throw new DeploymentUnitProcessingException(e);