Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WELD-2794 Change how we determine BM for synth beans in BCE that aren't related to any bean archive #3017

Merged
merged 2 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,8 @@ public BeanDeployment getOrCreateBeanDeployment(Class<?> clazz) {
return DeploymentStructures.getOrCreateBeanDeployment(deployment, deploymentManager, bdaMapping, contexts, clazz);
}

public BeanDeployment getBeanDeploymentIfExists(Class<?> clazz) {
return DeploymentStructures.getBeanDeploymentIfExists(deployment, bdaMapping, clazz);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public void addBean(Bean<?> bean) {
public <T> WeldBeanConfigurator<T> addBean() {
// null is only going to occur if the invocation is outside of OM in which case it will fail in the
// subsequent method inside checkWithinObserverNotification()
return addBean(getReceiver() != null ? getReceiver().getClass() : null);
return addBean(getReceiver() != null ? getReceiver().getClass() : null, null);
}

/**
Expand All @@ -115,12 +115,14 @@ public <T> WeldBeanConfigurator<T> addBean() {
* This method should not be used anywhere else.
*
* @param receiverClass class of the Build Compatible extension performing synth. bean registration
* @param fallbackClass fallback receiver class for BCEs coming from non-CDI archives; can be null
* @param <T> bean type
* @return instance of {@link WeldBeanConfigurator}
*/
public <T> WeldBeanConfigurator<T> addBean(Class<?> receiverClass) {
public <T> WeldBeanConfigurator<T> addBean(Class<?> receiverClass, Class<?> fallbackClass) {
checkWithinObserverNotification();
BeanConfiguratorImpl<T> configurator = new BeanConfiguratorImpl<>(receiverClass, getBeanDeploymentFinder());
BeanConfiguratorImpl<T> configurator = new BeanConfiguratorImpl<>(receiverClass, fallbackClass,
getBeanDeploymentFinder());
// note that here we deliberately keep getReceiver() since the logging is related to registering portable extension
additionalBeans.add(BeanRegistration.of(configurator, getReceiver()));
return configurator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension;
import jakarta.enterprise.inject.spi.AnnotatedType;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanAttributes;
Expand All @@ -42,6 +43,7 @@
import org.jboss.weld.bean.BeanIdentifiers;
import org.jboss.weld.bean.StringBeanIdentifier;
import org.jboss.weld.bean.WeldBean;
import org.jboss.weld.bootstrap.BeanDeployment;
import org.jboss.weld.bootstrap.BeanDeploymentFinder;
import org.jboss.weld.bootstrap.event.WeldBeanConfigurator;
import org.jboss.weld.contexts.CreationalContextImpl;
Expand Down Expand Up @@ -83,10 +85,18 @@ public class BeanConfiguratorImpl<T> implements WeldBeanConfigurator<T>, Configu
* @param defaultBeanClass
* @param beanDeploymentFinder
*/
public BeanConfiguratorImpl(Class<?> defaultBeanClass, BeanDeploymentFinder beanDeploymentFinder) {
public BeanConfiguratorImpl(Class<?> defaultBeanClass, Class<?> fallbackClass, BeanDeploymentFinder beanDeploymentFinder) {
this.beanClass = defaultBeanClass;
this.injectionPoints = new HashSet<>();
this.beanManager = beanDeploymentFinder.getOrCreateBeanDeployment(beanClass).getBeanManager();
BeanDeployment beanDeployment = beanDeploymentFinder.getBeanDeploymentIfExists(beanClass);
if (beanDeployment == null && fallbackClass != null && BuildCompatibleExtension.class.isAssignableFrom(beanClass)) {
// case of synth beans coming from BCE with no backing archive
// use a fallback class, typically LiteExtensionTranslator.class
beanDeployment = beanDeploymentFinder.getOrCreateBeanDeployment(fallbackClass);
} else {
beanDeployment = beanDeploymentFinder.getOrCreateBeanDeployment(beanClass);
}
this.beanManager = beanDeployment.getBeanManager();
this.attributes = new BeanAttributesConfiguratorImpl<>(beanManager);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,15 @@ public static BeanDeployment getOrCreateBeanDeployment(Deployment deployment, Be
}
}

public static BeanDeployment getBeanDeploymentIfExists(Deployment deployment, BeanDeploymentArchiveMapping bdaMapping,
Class<?> clazz) {
BeanDeploymentArchive beanDeploymentArchive = deployment.loadBeanDeploymentArchive(clazz);
if (beanDeploymentArchive == null) {
throw UtilLogger.LOG.unableToFindBeanDeploymentArchive(clazz);
} else {
// can be null
return bdaMapping.getBeanDeployment(beanDeploymentArchive);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.jboss.weld.tests.accessibility.bce;

import static org.junit.Assert.assertTrue;

import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension;

import jakarta.inject.Inject;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.BeanDiscoveryMode;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.jboss.shrinkwrap.impl.BeansXml;
import org.jboss.weld.test.util.Utils;
import org.jboss.weld.tests.accessibility.bce.lib.MyBeanCreator;
import org.jboss.weld.tests.accessibility.bce.lib.MyBce;
import org.jboss.weld.tests.accessibility.bce.lib.SomeType;
import org.jboss.weld.tests.category.Integration;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

/**
* Tests a scenario in which an application (WAR) has a library (/lib) which isn't a bean archive but has registered BCE.
* While such BCE creates synth bean, its {@code Instance} should be able to access beans from the application (WAR)
*/
@RunWith(Arquillian.class)
@Category(Integration.class)
public class BceInLibTest {

@Deployment
public static WebArchive getDeployment() {
WebArchive war = ShrinkWrap
.create(WebArchive.class, Utils.getDeploymentNameAsHash(BceInLibTest.class, Utils.ARCHIVE_TYPE.WAR))
.addClasses(MyBean.class)
.addAsWebInfResource(new BeansXml(BeanDiscoveryMode.ANNOTATED), "beans.xml");
// archive with extension and no beans.xml == not a bean archive
JavaArchive lib = ShrinkWrap.create(JavaArchive.class)
.addClasses(MyBce.class, MyBeanCreator.class, SomeType.class)
.addAsServiceProvider(BuildCompatibleExtension.class, MyBce.class);
return war.addAsLibrary(lib);
}

@Inject
Instance<Object> instance;

@Test
public void testVisibility() {
// assert dummy bean is available
assertTrue(instance.select(MyBean.class).isResolvable());
// assert we can select type added through BCE from here
assertTrue(instance.select(SomeType.class).isResolvable());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.jboss.weld.tests.accessibility.bce;

import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class MyBean {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.jboss.weld.tests.accessibility.bce.lib;

import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension;
import jakarta.enterprise.inject.build.compatible.spi.Synthesis;
import jakarta.enterprise.inject.build.compatible.spi.SyntheticComponents;

public class MyBce implements BuildCompatibleExtension {


@Synthesis
public void registerSynthBean(SyntheticComponents syntheticComponents) {
syntheticComponents.addBean(SomeType.class)
.type(SomeType.class)
.createWith(MyBeanCreator.class)
.scope(Dependent.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.jboss.weld.tests.accessibility.bce.lib;

import static org.junit.Assert.assertTrue;

import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.build.compatible.spi.Parameters;
import jakarta.enterprise.inject.build.compatible.spi.SyntheticBeanCreator;
import org.jboss.weld.tests.accessibility.bce.MyBean;

public class MyBeanCreator implements SyntheticBeanCreator<SomeType> {
@Override
public SomeType create(Instance<Object> lookup, Parameters params) {
// assert that Instance provided here (BCE in non bean archive lib) can "see" MyBean
assertTrue(lookup.select(MyBean.class).isResolvable());
return new SomeType();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.jboss.weld.tests.accessibility.bce.lib;

public class SomeType {
}
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ public void synthesis(@Priority(Integer.MAX_VALUE) @Observes jakarta.enterprise.
if (abd instanceof AfterBeanDiscoveryImpl) {
// specify the receiver class to be the BCE extension, linking the bean to it
// in EE env this affects the BM used for dynamic resolution inside bean creation method
configurator = ((AfterBeanDiscoveryImpl) abd).addBean(syntheticBean.extensionClass);
configurator = ((AfterBeanDiscoveryImpl) abd).addBean(syntheticBean.extensionClass,
LiteExtensionTranslator.class);
} else {
configurator = abd.addBean();
}
Expand Down
Loading