Last active
August 29, 2015 14:09
-
-
Save antoinesd/3097661ca99fa61900fb to your computer and use it in GitHub Desktop.
Implementing type conversion with CDI 1.1+
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 ""; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.