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.