Integrating Spring & T5.0.5
Please note that this method was inspired from the solution presented by [SergeEby] [TapestrySpringIntegrationAlternative1] in t5.0.2. – [JunTsai]
See also:
add spring module class
package corner.orm.tapestry.spring; import org.apache.tapestry.ioc.ObjectLocator; import org.apache.tapestry.ioc.ObjectProvider; import org.apache.tapestry.ioc.OrderedConfiguration; /** * spring 1.x/2.x + Tapestry5.0.5 * @author jun.tsai * @version $Revision: 2830 $ * @since 3.0 */ public class SpringModule { //contribution master object provider public static void contributeMasterObjectProvider( OrderedConfiguration<ObjectProvider> configuration, ObjectLocator locator) { configuration.add("spring", locator .autobuild(SpringObjectProvider.class)); } }
add spring annotation class
@Target( { PARAMETER, FIELD }) @Retention(RUNTIME) @Documented public @interface Spring { public String value(); }
Create the SpringObjectProvider class
The class listing is presented below:
package corner.orm.tapestry.spring; import org.apache.tapestry.ioc.AnnotationProvider; import org.apache.tapestry.ioc.ObjectLocator; import org.apache.tapestry.ioc.ObjectProvider; import org.apache.tapestry.ioc.annotations.InjectService; import org.apache.tapestry.ioc.services.TypeCoercer; /** * @author jcai * @version $Revision: 2828 $ * @since 3.0 */ public class SpringObjectProvider implements ObjectProvider { private TypeCoercer _typeCoercer; public SpringObjectProvider(@InjectService("TypeCoercer") TypeCoercer typeCoercer) { _typeCoercer = typeCoercer; } /** * @see org.apache.tapestry.ioc.ObjectProvider#provide(java.lang.Class, * org.apache.tapestry.ioc.AnnotationProvider, * org.apache.tapestry.ioc.ObjectLocator) */ public <T> T provide(Class<T> objectType, AnnotationProvider annotationProvider, ObjectLocator locator) { Spring annotation = annotationProvider.getAnnotation(Spring.class); if (annotation == null) return null; String value = annotation.value(); Object obj = getSpringContext().getBean(value); T coerced = _typeCoercer.coerce(obj, objectType); return coerced; } private ApplicationContext getSpringContext(){ // get application context } }
add module define in your MANIFEST.MF file
Tapestry-Module-Classes: corner.orm.tapestry.spring.SpringModule
Inject Spring beans
We are done! it's now time to inject some Spring beans. For illustration purpose, I am updating an example from Tapestry 5 integration test source code:
First, here is sample applicationContext-hibernate.xml config file. Only the relevant parts are presented (I am using Spring/Hibernate stack)
<?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-2.0.xsd"> <!-- Hibernate SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="${hibernate.config}"/> <property name="hibernateProperties"> <value> hibernate.dialect=${hibernate.dialect} hibernate.show_sql=${hibernate.show_sql} hibernate.query.substitutions=true 'Y', false 'N' </value> </property> </bean> ... <!-- Transaction manager for a single Hibernate SessionFactory (alternativeto JTA) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <bean id="toDoDatabase" class="org.apache.tapestry.integration.app1.services.ToDoDatabaseHibernateImpl"> <property name="sessionFactory" ref="sessionFactory"/> </bean> </beans>
As you can see, the toDoDatabase is now mapped to the ToDoDatabaseHibernateImpl class.
And then, the ToDoList class:
package org.apache.tapestry.integration.app1.pages; import java.util.List; import org.apache.tapestry.PrimaryKeyEncoder; import org.apache.tapestry.annotations.Component; import org.apache.tapestry.annotations.Inject; import org.apache.tapestry.corelib.components.Form; import org.apache.tapestry.integration.app1.data.ToDoItem; import org.apache.tapestry.integration.app1.services.ToDoDatabase; import org.apache.tapestry.util.DefaultPrimaryKeyEncoder; public class ToDoList { @Inject @Spring("toDoDatabase") private ToDoDatabase _database; private ToDoItem _item; private DefaultPrimaryKeyEncoder<Long, ToDoItem> _encoder; @Component private Form _form; public List<ToDoItem> getItems() { return _encoder.getValues(); } public ToDoItem getItem() { return _item; } public void setItem(ToDoItem item) { _item = item; } public ToDoDatabase getDatabase() { return _database; } public PrimaryKeyEncoder getEncoder() { return _encoder; } void onPrepare() { List<ToDoItem> items = _database.findAll(); _encoder = new DefaultPrimaryKeyEncoder<Long, ToDoItem>(); for (ToDoItem item : items) { _encoder.add(item.getId(), item); } } void onSuccess() { int order = 0; for (ToDoItem item : _encoder.getValues()) { item.setOrder(order++); _database.update(item); } } void onSelectedFromAddNew() { if (_form.isValid()) { ToDoItem item = new ToDoItem(); item.setTitle("<New To Do>"); item.setOrder(_encoder.getValues().size()); _database.add(item); } } void onActionFromReset() { _database.reset(); } }
Note that the only change to this class the the @Inject annotation
Congrats! you are now using injected Spring beans in T5.0.5