Skip to content

Commit

Permalink
WFLY-19573 Expand WeldCapability to include build compatible extensions.
Browse files Browse the repository at this point in the history
Introduce separate WeldLogger entry for incorrect LiteExtensionTranslator setup.
Change the CL and DU to that of a top level deployment when registering LiteExtensionTranslator.
  • Loading branch information
manovotn committed Sep 5, 2024
1 parent 4e2e3c5 commit 4c73b51
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 16 deletions.
19 changes: 17 additions & 2 deletions weld/common/src/main/java/org/jboss/as/weld/WeldCapability.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -26,15 +28,28 @@ public interface WeldCapability {
* Registers a CDI Portable Extension for the {@link DeploymentUnit} passed as argument to
* this method.
* <p>
* 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.
* <p>
* 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<? extends BuildCompatibleExtension> extension, final DeploymentUnit unit);

/**
* Adds the Bean Manager service associated to the {@link DeploymentUnit} to ServiceBuilder passed as argument.
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
* <p/>
* 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.
* <p/>
* 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
*
Expand All @@ -52,6 +58,7 @@ public static WeldPortableExtensions getPortableExtensions(final DeploymentUnit
}

private final Map<Class<?>, Metadata<Extension>> extensions = new HashMap<>();
private final Collection<Class<? extends BuildCompatibleExtension>> buildCompatibleExtensions = new ArrayList<>();

public synchronized void tryRegisterExtension(final Class<?> extensionClass, final DeploymentUnit deploymentUnit) throws DeploymentUnitProcessingException {
if (!Extension.class.isAssignableFrom(extensionClass)) {
Expand All @@ -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<? extends BuildCompatibleExtension> 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<List<Class<? extends BuildCompatibleExtension>>,
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<Metadata<Extension>> getExtensions() {
return new HashSet<>(extensions.values());
}

public List<Class<? extends BuildCompatibleExtension>> getBuildCompatibleExtensions() {
return new ArrayList<>(buildCompatibleExtensions);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -33,6 +34,14 @@ public void registerExtensionInstance(final Extension extension, final Deploymen
}
}

@Override
public void registerBuildCompatibleExtension(Class<? extends BuildCompatibleExtension> extension, DeploymentUnit unit) {
if (isPartOfWeldDeployment(unit)) {
WeldPortableExtensions extensions = WeldPortableExtensions.getPortableExtensions(unit);
extensions.registerBuildCompatibleExtension(extension);
}
}

@Override
public Supplier<BeanManager> addBeanManagerService(final DeploymentUnit unit, final ServiceBuilder<?> serviceBuilder) {
if (isPartOfWeldDeployment(unit)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -213,8 +214,11 @@ public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitPro
additional.getServices().add(entry.getKey(), Reflections.cast(entry.getValue()));
}
}

final Collection<Metadata<Extension>> 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<Metadata<Extension>> extensions = portableExtensions.getExtensions();

final WeldDeployment deployment = new WeldDeployment(beanDeploymentArchives, extensions, module, subDeploymentLoaders, deploymentUnit, rootBeanDeploymentModule, eeModuleDescriptors);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -74,14 +73,9 @@ private void loadAttachments(Module module, DeploymentUnit deploymentUnit, WeldP
// load class and register for portable extensions
Collection<Class<?>> 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<Class<? extends BuildCompatibleExtension>> 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<? extends BuildCompatibleExtension> extensionClass : loadExtensions(module, buildCompatibleExtensionServices, BuildCompatibleExtension.class)) {
extensions.registerBuildCompatibleExtension(extensionClass);
}
} catch (IOException e) {
throw new DeploymentUnitProcessingException(e);
Expand Down

0 comments on commit 4c73b51

Please sign in to comment.