Differences between revisions 12 and 13
Revision 12 as of 2007-06-30 13:21:39
Size: 6704
Editor: NickWestgate
Comment:
Revision 13 as of 2009-09-20 23:20:13
Size: 6704
Editor: localhost
Comment: converted to 1.6 markup
No differences found!

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

Tapestry5SpringIntegrationAlternative2 (last edited 2009-09-20 23:20:13 by localhost)