Hi all, We're looking into moving our apps from a 'traditional' servlet container with spring into a Java EE web profile server like glassfish 3.1. Motivations for doing this is to utilize cdi(jsr 299, 330), ejb3 and more. Not just for the tapestry app, but also the other applications in our portfoleo which share common core business logic.
For reference on previous discussions: http://tapestry.1045711.n5.nabble.com/Java-based-spring-configuration-td3394086.html http://tapestry.1045711.n5.nabble.com/Discussion-td2421783i20.html Now, I've tried running the tapestry quickstart app in glassfish 3.1 (with the eclipse connector for publishing). This works ok - although I cannot make live class reloading work. :( Glassfish uses Weld, so the CDIModule is basically an objectprovider for injecting Weld managed beans. (As you probably know CDI/Weld can also be used outside jee as alternative to tapestry-ioc, spring, etc) *CDIModule class* *public class CDIModule { * * public static void bind(ServiceBinder binder) {* * binder.bind(ObjectProvider.class, CDIObjectProvider.class).withId("CDIObjectProvider"); * * } * * public static BeanManager buildBeanManager(Logger log) { * * try {* * BeanManager beanManager = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");* * return beanManager; * * } catch (NamingException e) {* * log.error("Could not lookup jndi resource: java:comp/BeanManager", e);* * }* * return null;* * } * * public static void contributeMasterObjectProvider(* * @InjectService("CDIObjectProvider") ObjectProvider cdiProvider,* * OrderedConfiguration<ObjectProvider> configuration) { * *// configuration.add("cdiProvider", cdiProvider, "after:Service,after:AnnotationBasedContributions,after:Alias,after:Autobuild"); * * configuration.add("cdiProvider", cdiProvider, "after:*"); * * } * *}* * * The beanmanager is expected to be found in jndi. If the beans.xml is present it will be available at this point. The BeanManager is also exposed as a service and injectable for other services or components. I've tested by adding the *@SubModule(CDIModule.class) *to my quickstart appmodule. * * *CDIObjectProvider class* *public class CDIObjectProvider implements ObjectProvider { * * private BeanManager beanManager;* * private Logger log;* * * * @SuppressWarnings({ "unchecked", "rawtypes" })* * private Set allowedScopes = CollectionFactory.newSet(* * ApplicationScoped.class,* * Singleton.class);* * * * public CDIObjectProvider(* * Logger log,* * @InjectService("BeanManager") BeanManager manager) {* * this.beanManager = manager;* * this.log = log;* * }* * @SuppressWarnings("unchecked")* * public <T> T provide(Class<T> objectType,* * AnnotationProvider annotationProvider, ObjectLocator locator) {* * Set<Bean<?>> beans = beanManager.getBeans(objectType);* * if(beans!=null && beans.size()>0) {* * Bean<T> bean = (Bean<T>) beans.iterator().next(); * * if(hasValidScope(bean)) {* * CreationalContext<T> ctx = beanManager.createCreationalContext(bean);* * T o = (T) beanManager.getReference(bean, objectType, ctx); * * log.info("Found and returning: "+objectType.getCanonicalName());* * return o; * * }* * }* * return null;* * } * * protected <T> boolean hasValidScope(Bean<T> bean) {* * return bean!=null && allowedScopes.contains(bean.getScope());* * }* *}* I've limited the scope to singleton/applicationscoped. Perhaps also Default could be accepted though. Until now I've only tested this with pojo's and not ejb's - but for that it's working as expected. I can inject CDI beans into pages and components using* org.apache.tapestry5.ioc.annotations.Inject* I'm no expert to tapestry internals - so there could be other considerations that needs to be addressed. In fact in seemed just a little to easy to implement - so I must have missed something. - Or perhaps it's just that easy to do in Tapestry :) Thoughts, comments?