0

I have the following @ApplicationScoped bean:

@ApplicationScoped
public class ServiceProducer {

    private static final Logger logger = LoggerFactory.getLogger(ServiceProducer.class);

    @Default
    @Produces
    @PersistenceContext(unitName = "nemo")
    private EntityManager nemoEntityManager;

    private CacheManager cacheManager;

    @PostConstruct
    void init() {
        try {
            cacheManager = Caching.getCachingProvider().getCacheManager(
                    Objects.requireNonNull(Thread.currentThread().getContextClassLoader().getResource("/ehcache.xml")).toURI(),
                    Thread.currentThread().getContextClassLoader());
        } catch (URISyntaxException e) {
            logger.error(e.getMessage());
        }

    }


    @Produces
    public CacheManager produceCacheManager() {
        return cacheManager;
    }

The above class is contained in a common / shared module of my web applications. This is good for production, however I need an alternative for integration test, which are done with Cucumber with wildspike integration.

By configuring beans.xml, unfortunately I cannot disable the bean above, I tried with configuring beans.xml in this way:

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
    http://xmlns.jcp.org/xml/ns/javaee
    http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" bean-discovery-mode="all">

    <scan>
        <exclude name="it.myapp.ecommerce.commons.resource.ServiceProducer"></exclude>
    </scan>
    

however nothing changes. Is it due because the class belongs from a dependency ?

Fabrizio Stellato
  • 1,727
  • 21
  • 52
  • 1
    If I am not mistaken, in order for the `` filter to work, it must be in the beans.xml of the bean archive that defines the class. However, alternatives+`@Priority` are probably appropriate for your case. – Nikos Paraskevopoulos Dec 07 '20 at 20:25
  • Can you post some snippets? It's still unclear to me on how to use @alternative annotation of a resource provider bean like the one I posted – Fabrizio Stellato Dec 07 '20 at 21:34
  • Just to be clear, I already have the alternative class for producing logger and entity manager, however the issue is that I'm not able to use just it. When starting cucumber, I have ambiguous injection due to serviceproducer class – Fabrizio Stellato Dec 07 '20 at 21:42
  • Have you annotated the producer *method* as alternative? – Nikos Paraskevopoulos Dec 08 '20 at 01:03
  • @NikosParaskevopoulos Yes I did, then I configured beans.xml with alternative, but I had no improvements, even by excluding resorces/test/META-INF/beans.xml of common module won't work – Fabrizio Stellato Dec 09 '20 at 09:44

1 Answers1

3

You basically have two options.

Firstly, and this is the usual go-to recommended option, it's the @Alternative plus @Priority combination on the secondary bean that you declare and only add in test environment. That way, it will be picked up for testing but not in production. Note that it is imperative that you only add the alternative in the test environment else it would be picked up at all times. You can, for instance, declare this bean directly under test project (or its sources) so that the main (production) JAR doesn't contain it. Furthermore, you don't need to alter beans.xml to achieve the above. Alternatives can be enabled either via @Priority or via beans.xml; the former is global, the latter is per-bean-archive.

Second option is a CDI extension that will observe ProcessAnnotatedType<ServiceProducer> event and will veto() the proper class. That means the given class won't be picked up as bean. This can be done conditionally based on some parameter or whatever else you have at hand. Given you do the above, you then need to somehow add the new test implementation of ServiceProducer. You can again do that by declaring it in test sources (no need for alternative here) but you can also use the very same extension to register a synthetic bean in AfterBeanDiscovery via BeanConfigurator SPI.

While CDI extension are pretty powerful, I'd recommend going with the first option that's way simpler and more understandable once you read up a bit on how alternatives and their enablement works.

Siliarus
  • 6,393
  • 1
  • 14
  • 30