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

  • No labels