-
-
Save antoinesd/3097661ca99fa61900fb to your computer and use it in GitHub Desktop.
package org.cdispec.converter; | |
import static java.lang.annotation.ElementType.FIELD; | |
import static java.lang.annotation.ElementType.METHOD; | |
import static java.lang.annotation.ElementType.PARAMETER; | |
import static java.lang.annotation.ElementType.TYPE; | |
import static java.lang.annotation.RetentionPolicy.RUNTIME; | |
import java.lang.annotation.Documented; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.Target; | |
import javax.enterprise.util.Nonbinding; | |
import javax.inject.Qualifier; | |
/** | |
* @author Antoine Sabot-Durand | |
*/ | |
@Qualifier | |
@Target({TYPE, METHOD, PARAMETER, FIELD}) | |
@Retention(RUNTIME) | |
@Documented | |
public @interface Convert { | |
@Nonbinding | |
String value() default ""; | |
} |
package org.cdispec.converter; | |
import java.lang.annotation.Annotation; | |
import java.lang.reflect.Type; | |
import java.util.HashSet; | |
import java.util.Set; | |
import javax.enterprise.event.Observes; | |
import javax.enterprise.inject.spi.BeanAttributes; | |
import javax.enterprise.inject.spi.Extension; | |
import javax.enterprise.inject.spi.InjectionPoint; | |
import javax.enterprise.inject.spi.ProcessBeanAttributes; | |
import javax.enterprise.inject.spi.ProcessInjectionPoint; | |
/** | |
* @author Antoine Sabot-Durand | |
*/ | |
public class ConverterExtension implements Extension { | |
private static class ConverterBeanAttribute implements BeanAttributes<Object> { | |
private BeanAttributes<Object> delegate; | |
private Set<Type> types; | |
public ConverterBeanAttribute(BeanAttributes<Object> delegate, Set<Type> types) { | |
this.delegate = delegate; | |
this.types = types; | |
} | |
@Override | |
public Set<Type> getTypes() { | |
return types; | |
} | |
@Override | |
public Set<Annotation> getQualifiers() { | |
return delegate.getQualifiers(); | |
} | |
@Override | |
public Class<? extends Annotation> getScope() { | |
return delegate.getScope(); | |
} | |
@Override | |
public String getName() { | |
return delegate.getName(); | |
} | |
@Override | |
public Set<Class<? extends Annotation>> getStereotypes() { | |
return delegate.getStereotypes(); | |
} | |
@Override | |
public boolean isAlternative() { | |
return delegate.isAlternative(); | |
} | |
} | |
private Set<Type> types = new HashSet<>(); | |
public void retrieveTypes(@Observes ProcessInjectionPoint<?,?> pip) { | |
InjectionPoint ip=pip.getInjectionPoint(); | |
if(ip.getAnnotated().isAnnotationPresent(Convert.class)) | |
types.add(ip.getType()); | |
} | |
public void addTypeToConverter(@Observes ProcessBeanAttributes<Object> pba) { | |
if(pba.getAnnotated().isAnnotationPresent(Convert.class)) | |
pba.setBeanAttributes(new ConverterBeanAttribute(pba.getBeanAttributes(),types)); | |
} | |
} |
package org.cdispec.converter; | |
import javax.enterprise.inject.Produces; | |
import javax.enterprise.inject.spi.InjectionPoint; | |
/** | |
* @author Antoine Sabot-Durand | |
*/ | |
public class ConverterProducer { | |
@Produces | |
@Convert | |
public Object produceConverter(InjectionPoint ip) { | |
String toConvert = ip.getAnnotated().getAnnotation(Convert.class).value(); | |
Class<?> toType = (Class<?>) ip.getAnnotated().getBaseType(); | |
System.out.println("I have to convert "+ toConvert+ " to type: " +toType.toString()); | |
if(toType.equals(Integer.class)) | |
return new Integer(toConvert); | |
else if (toType.equals(StringBuffer.class)) | |
return new StringBuffer(toConvert); | |
else | |
return null; | |
} | |
} |
package org.cdispec.converter; | |
import junit.framework.Assert; | |
import org.jboss.arquillian.container.test.api.Deployment; | |
import org.jboss.arquillian.junit.Arquillian; | |
import org.jboss.shrinkwrap.api.Archive; | |
import org.jboss.shrinkwrap.api.ShrinkWrap; | |
import org.jboss.shrinkwrap.api.asset.EmptyAsset; | |
import org.jboss.shrinkwrap.api.spec.WebArchive; | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import java.io.FileNotFoundException; | |
import javax.enterprise.inject.spi.Extension; | |
import javax.inject.Inject; | |
/** | |
* @author Antoine Sabot-Durand | |
*/ | |
@RunWith(Arquillian.class) | |
public class ConvertProducerTest { | |
@Deployment | |
public static Archive<?> createTestArchive() throws FileNotFoundException { | |
WebArchive ret = ShrinkWrap | |
.create(WebArchive.class, "test.war") | |
.addPackage("org.cdispec.converter") | |
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") | |
.addAsServiceProvider(Extension.class, ConverterExtension.class); | |
return ret; | |
} | |
@Inject | |
@Convert("126") | |
Integer converted; | |
@Inject | |
@Convert("Me/Hungry") | |
StringBuffer converted2; | |
@Test | |
public void shoulHaveInjectedConvertedInteger() { | |
Assert.assertEquals(new Integer(126), converted); | |
} | |
@Test | |
public void shoulHaveInjectedConvertedStringBuffer() { | |
Assert.assertEquals("Me/Hungry", converted2.toString()); | |
} | |
} |
edit Just saw that this gist is rather old and we might have discussed this already in the final code.
This is imo perfectly non -portable code. Please read spec section 12.4.3. Bean discovery
„For every type in the set of discovered types (as defined in Section 12.4.1, “Type discovery”), the container must:
• if the class is a managed bean, session bean, or other Java EE component class supporting injection, fire an event of type ProcessInjectionPoint for each injection point in the class, as defined in Section 11.5.7, “ProcessInjectionPoint event”, and THEN
• if the class is a managed bean, session bean, or other Java EE component class supporting injection, fire an event of type ProcessInjectionTarget, as defined in Section 11.5.8, “ProcessInjectionTarget event”, and then
• determine which alternatives, interceptors and decorators are enabled, according to the rules defined in Section 5.1.2, “Enabled and disabled beans”, Section 9.4, “Interceptor enablement and ordering” and Section 8.2, “Decorator enablement and ordering”, and THEN
• if the class is an enabled bean, interceptor or decorator, fire an event of type ProcessBeanAttributes, as defined in Section 11.5.9, “ProcessBeanAttributes event”, and THEN
…
„So the CDI spec clearly specifies that the whole loop is ‚for every type in the set of discovered types, THEN THEN THEN“
OWB impls it exactly as it is specified.
This code works for CDI 1.1 and 1.2. It was tested with Weld 2.2.6 and should work with OWB 1.5.x. I could port it to CDI 1.0 using Deltaspike if you need.
The extension build the list of types for each
InjectionPoint
qualified with@Convert
qualifier, it thens change Bean Attributes of the produce to add all the types discovered.