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?

Reply via email to