Question

I have a Producers class annotated with @Singleton, containing a method annotated with @Produces.

I want to write unit test using an alternative of this method, but can't manage to do it. here's a summary of my code :

package fr.easycompany.easywrite.tools.injection;

@Singleton
public class Producers {
    @Produces @Named(PREFERENCES_FILE_NAMED)
    public String producePreferenceFileName(){
        return "preferences.xml";
    }
}

And my Alternative :

package fr.easycompany.easywrite.tools.injection; 

@Singleton
@Alternative
public class ProducersAlternative {
    @Produces @Named(PREFERENCES_FILE_NAMED)
    public String producePreferenceFileName(){
        return "preferences_test.xml";
    }
}

I also created a beans.xml in src/test/resources/META-INF with the following content

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:weld="http://jboss.org/schema/weld/beans" 
       xsi:schemaLocation="
          http://java.sun.com/xml/ns/javaee http://docs.jboss.org/cdi/beans_1_0.xsd
          http://jboss.org/schema/weld/beans http://jboss.org/schema/weld/beans_1_1.xsd">
    <alternatives>
        <class>fr.easycompany.easywrite.tools.injection.ProducersAlternative</class>
        </alternatives>
</beans>

At the execution, it's always Producers#producePreferenceFileName() which is called. Why is it not ProducersAlternative's method ? Is it impossible to have an alternative of a singleton injected class ?

Was it helpful?

Solution

I don't think that this has anything to do with Singletons. The annotation @Alternative just is not meant to be used on Producer classes, but on the alternative implementation of a bean. You could use a alternative stereotype and annotate your alternative producer method instead to make this work. This is needed, because methods that have @Alternative annotation can't be enabled in beams.xml - but stereotypes can (see also this discussion on JBoss forum). To do so, you have to create a stereotype like this:

@RequestScoped
@Stereotype
@Retention(RetentionPolicy.RUNTIME)
@Alternative
@Target({
    ElementType.TYPE, ElementType.METHOD
})
public @interface Staging {}

You have to enable this alternative stereotype in your beans.xml (instead declaring your alternative producer class there) like this:

<alternatives>
  <stereotype>full.qualified.path.to.Staging</stereotype>
</alternatives>

You can then annotate your alternative producer method (best you delete the @Alternative annotation on your producer class and in the beans.xml):

@Singleton
public class ProducersAlternative {
  @Produces @Named(PREFERENCES_FILE_NAMED) @Staging
  public String producePreferenceFileName(){
      return "preferences_test.xml";
  }
}

Hope this helps :-)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top