Asymmetry between producer and event observer with @Nonbinding qualifier
starksm64 Aug 21, 2012 11:45 AMSo I have a little test that has a producer generate a string based on a @Nonbinding value of a qualifier to set unique values for fields. The qualifier cannot be used to differentiate between events because of the @Nonbinding value however. Is there a way to customize the event selection that provides the same dynamic selection of who should receive the event?
Here is the test code:
package test.com.si.weld.ex1; import javax.enterprise.util.Nonbinding; import javax.inject.Qualifier; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; @Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface TestSymbol { @Nonbinding String value(); } package test.com.si.weld.symbol; import test.com.si.weld.ex1.TestSymbol; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; /** * @author Scott stark * @version $Revision:$ */ @ApplicationScoped public class SymbolConsumer { @Inject @TestSymbol("key1") private String value1; @Inject @TestSymbol("key2") private String value2; public void key1Event(@Observes @TestSymbol("key1") String value1) { this.value1 = value1; System.out.printf("key1Event, %s\n", value1); } public void key2Event(@Observes @TestSymbol("key2") String value2) { this.value2 = value2; System.out.printf("key2Event, %s\n", value2); } @Override public String toString() { return "SymbolConsumer{" + "value1='" + value1 + '\'' + ", value2='" + value2 + '\'' + '}'; } } package test.com.si.weld.symbol; import test.com.si.weld.ex1.TestSymbol; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Event; import javax.enterprise.inject.Produces; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.InjectionPoint; import javax.inject.Inject; import java.lang.annotation.Annotation; import java.util.Properties; import java.util.Set; /** * @author Scott Stark * @version $Revision:$ */ @ApplicationScoped public class SymbolProducer { private Properties symbols = new Properties(); @Inject @TestSymbol("key1") private Event<String> key1Event; @Inject @TestSymbol("key2") private Event<String> key2Event; public static TestSymbol getTestSymbol(Set<Annotation> qualifiers) { TestSymbol symbol = null; for(Annotation a : qualifiers) { if(TestSymbol.class.isAssignableFrom(a.getClass())) { symbol = TestSymbol.class.cast(a); break; } } return symbol; } public SymbolProducer() { symbols.setProperty("key1", "value1"); symbols.setProperty("key2", "value2"); } @TestSymbol("") @Produces public String getSymbol(InjectionPoint ip, BeanManager beanManager) { String key = getTestSymbol(ip.getQualifiers()).value(); String symbol = symbols.getProperty(key); System.out.printf("getSymbol(%s) = %s\n", ip, symbol); return symbol; } public void sendKey1Value(String value) { key1Event.fire(value); } public void sendKey2Value(String value) { key2Event.fire(value); } } package test.com.si.weld.symbol; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.EmptyAsset; import org.jboss.shrinkwrap.api.spec.JavaArchive; import org.junit.Test; import org.junit.runner.RunWith; import test.com.si.weld.ex1.TestSymbol; import javax.inject.Inject; /** * @author Scott Stark * @version $Revision:$ */ @RunWith(Arquillian.class) public class TestNonBinding { @Deployment public static JavaArchive createDeployment() { JavaArchive archive = ShrinkWrap.create(JavaArchive.class) .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); archive.addPackages(true, "test/com/si/weld/symbol"); archive.addClass(TestNonBinding.class); archive.addClass(TestSymbol.class); return archive; } // Arquillian enables @Inject directly in the test case class itself! @Inject SymbolConsumer consumer; @Inject SymbolProducer producer; @Test public void testSymbols() { System.out.printf("consumer = %s\n", consumer); producer.sendKey1Value("value1.1"); System.out.printf("consumer = %s\n", consumer); } }
Output when the TestNonBinding.testSymbols is run:
34 [main] INFO org.jboss.weld.Version - WELD-000900 1.1.9 (Final) consumer = getSymbol([field] @TestSymbol @Inject private test.com.si.weld.symbol.SymbolConsumer.value1) = value1 getSymbol([field] @TestSymbol @Inject private test.com.si.weld.symbol.SymbolConsumer.value2) = value2 SymbolConsumer{value1='value1', value2='value2'} key1Event, value1.1 key2Event, value1.1 consumer = SymbolConsumer{value1='value1.1', value2='value1.1'}
So both the key1Event and key2Event observer methods are called when an event with a TestSymbol("key1") qualifier is sent out because the value of the TestSymbol qualifier is not used due to the NonBinding meta-annotation. It would be good to uniformally be able to map such a qualifier on both producers and events.