Spring context portable extension
trossmy Feb 18, 2010 1:50 PMI have created a portable extension that injects all the beans of the spring context into the cdi context like this:
package weld.example.portable.extension.spring; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.RequestScoped; import javax.enterprise.context.SessionScoped; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AfterBeanDiscovery; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.ProcessProducer; import javax.enterprise.inject.spi.Producer; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Scope; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * User: rossmyt * Date: 18.02.2010 * Time: 09:22:28 */ public class SpringContextExtension implements Extension { private ApplicationContext applicationContext; private List<Bean> beans= new java.util.ArrayList<Bean>(); void processAnnotatedType(@Observes ProcessAnnotatedType pat) { boolean isSpring = pat.getAnnotatedType().isAnnotationPresent(SpringContext.class); if (isSpring) { SpringContext springContext = pat.getAnnotatedType().getAnnotation(SpringContext.class); String configFile = springContext.configFile(); applicationContext = new ClassPathXmlApplicationContext(configFile); String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (final String beanDefinitionName : beanDefinitionNames) { final Object bean = applicationContext.getBean(beanDefinitionName); final Class type = applicationContext.getType(beanDefinitionName); Scope scope = bean.getClass().getAnnotation(Scope.class); Class cdiScope= ApplicationScoped.class; if (scope!=null) { String scopeName = scope.value(); if (scopeName.equals("request")) { cdiScope= RequestScoped.class; } else if (scopeName.equals("session")) { cdiScope= SessionScoped.class; } } final Class scp=cdiScope; final Set<Type> types = new HashSet<Type>() { { add(type); add(Object.class); } }; Bean<?> cdiBean = new Bean<Object>() { @Override public Set<Type> getTypes() { return types; } @Override public Set<Annotation> getQualifiers() { return Collections.emptySet(); } @SuppressWarnings({"unchecked"}) @Override public Class<? extends Annotation> getScope() { return scp; } @Override public String getName() { return beanDefinitionName; } @Override public Set<Class<? extends Annotation>> getStereotypes() { return Collections.emptySet(); } @Override public Class<?> getBeanClass() { return type; } @Override public boolean isAlternative() { return false; } @Override public boolean isNullable() { return false; } @Override public Set<InjectionPoint> getInjectionPoints() { return Collections.emptySet(); } @Override public Object create(CreationalContext<Object> objectCreationalContext) { return bean; } @Override public void destroy(Object instance, CreationalContext<Object> objectCreationalContext) { objectCreationalContext.release(); } }; beans.add(cdiBean); } } } void afterBeanDiscovery(@Observes AfterBeanDiscovery abd) { for (Bean bean:beans) { abd.addBean(bean); } System.out.println("Added spring context!"); } }
with the SpringContext @interface
package weld.example.portable.extension.spring; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; /** * User: rossmyt * Date: 18.02.2010 * Time: 09:27:36 */ @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public @interface SpringContext { public String configFile () default "application.xml"; }
The Spring context is injected in this bean
package weld.example; import java.io.Serializable; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.context.SessionScoped; import javax.enterprise.inject.Produces; import javax.inject.Named; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import weld.example.portable.extension.spring.SpringContext; /** * User: rossmyt * Date: 17.02.2010 * Time: 16:41:35 */ @Named(value = "init") @ApplicationScoped @SpringContext public class Init implements Serializable { @Produces @ApplicationScoped @PersistenceContext(unitName = "foo") EntityManager em; }
I test it with the following spring config file application.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="springTest" class="weld.example.SpringTest"> <property name="doesItWork" value="yes"/> </bean> </beans>
and
package weld.example; import java.io.Serializable; /** * User: rossmyt * Date: 18.02.2010 * Time: 11:53:57 */ public class SpringTest implements Serializable { private String doesItWork; public String getDoesItWork() { return doesItWork; } public void setDoesItWork(String doesItWork) { this.doesItWork = doesItWork; } }
So far so good. If I test with a jsf page
<h1>#{springTest.doesItWork}</h1>
everything works as expected.
But if I inject the springTest bean into another bean like this
@Inject SpringTest springTest;
a new Instance of SpringTest is created, with springTest.getDoesItWork returning null.
On the other hand, if I inject the beanManager like this
@Inject BeanManager beanManager;
then beanManager.getBeans(springTest
) returns a Set containing the expected springTest bean with springTest.getDoesItWork() returning 'yes'
So, what is it that I don't understand correctly?