Dear Wiki user, You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for change notification.
The following page has been changed by henrikvendelbo: http://wiki.apache.org/tapestry/Tapestry4Spring ------------------------------------------------------------------------------ = Combining Tapestry 4 and Spring = - How can you reference Spring beans from Tapestry 4? In earlier versions of Tapestry, the most common method was to extend the BaseEngine class. However, in Tapestry 4 the BaseEngine class is deprecated, and we now need to extend SpringBeanFactoryHolder. + How can you reference Spring beans from Tapestry 4? In earlier versions of Tapestry, the most common method was to extend the BaseEngine class. However, in Tapestry 4 the BaseEngine class is deprecated, and we now need to use or extend SpringBeanFactoryHolder. - Add an entry in your hivemodule.xml: + In the following varying methods are described of setting up Spring support in Tapestry. + + (''Basic knowledge of Java, Tapestry, and Spring assumed.'') + + == Step 1: Hivemind Configuration == + + Note: You can skip this step by downloading tapestry-spring.jar from http://sourceforge.net/projects/diaphragma and placing it on your classpath. + + If you already take care of Spring elsewhere, you can avoid implementing your own SpringBeanFactoryHolder implementation class, just add an entry in your hivemodule.xml: {{{ <implementation service-id="hivemind.lib.DefaultSpringBeanFactoryHolder"> <invoke-factory> @@ -15, +23 @@ </invoke-factory> </implementation> }}} - Consult [http://jakarta.apache.org/hivemind/hivemind-lib/SpringLookupFactory.html] for more information. - == Injecting Spring Beans == - - You may inject beans managed by Spring into pages and components just like you inject anything else as described by [http://tapestry.apache.org/tapestry4/UsersGuide/injection.html]. You can describe the injection in the .page/.jwc file or using an @InjectObject annotation. Just use the 'spring:' prefix like: - {{{ - @InjectObject("spring:name.from.applicationContext.xml") - }}} - - You may also wire Spring managed beans in HiveMind services such as IEngine services. - {{{ - <service-point id="MyService" interface="org.apache.tapestry.engine.IEngineService"> - <invoke-factory> - <construct class="engine.MyService"> - <set-object property="springBean" value="spring:name.of.spring.bean"/> - </construct> - </invoke-factory> - </service-point> - }}} - - (''Basic knowledge of Java, Tapestry, and Spring assumed.'') - - == Spring, Tapestry and Hibernate == - - In order to use lazy loading and for most Spring Hibernate templates, you need access to a Hibernate Session. The traditionnal Spring solution is to use the "OpenSessionInView" pattern where a Hibernate session is open for the whole request. - However, OpenSessionInView has to be configured in the web.xml which is not very friendly when you setup some particular Tapestry URLs. - - A better solution is to integrate the session opening/closing in Hivemind by using the WebRequestServicerFilter interface. Also, for Tapestry assets, it is not necessary to create a session. This code is based on the Spring OpenSessionInViewFilter. - - This requires to implement a class and wire it into Tapestry. - Here is the code for the class: - - {{{ - package actualis.web.tapestry.framework; - - import java.io.IOException; - - import org.apache.commons.logging.Log; - import org.apache.commons.logging.LogFactory; - import org.apache.hivemind.lib.SpringBeanFactoryHolder; - import org.apache.tapestry.Tapestry; - import org.apache.tapestry.services.ServiceConstants; - import org.apache.tapestry.services.WebRequestServicer; - import org.apache.tapestry.services.WebRequestServicerFilter; - import org.apache.tapestry.web.WebRequest; - import org.apache.tapestry.web.WebResponse; - import org.hibernate.FlushMode; - import org.hibernate.Session; - import org.hibernate.SessionFactory; - import org.springframework.dao.DataAccessResourceFailureException; - import org.springframework.orm.hibernate3.SessionFactoryUtils; - import org.springframework.orm.hibernate3.SessionHolder; - import org.springframework.transaction.support.TransactionSynchronizationManager; - - public class HibernateRequestFilter implements WebRequestServicerFilter { - - private static Log logger = LogFactory.getLog(HibernateRequestFilter.class); - - public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory"; - - private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME; - - private SpringBeanFactoryHolder _beanFactoryHolder; - - /** - * Set the bean name of the SessionFactory to fetch from Spring's root - * application context. Default is "sessionFactory". - * - * @see #DEFAULT_SESSION_FACTORY_BEAN_NAME - */ - public void setSessionFactoryBeanName(String sessionFactoryBeanName) { - this.sessionFactoryBeanName = sessionFactoryBeanName; - } - - /** - * Return the bean name of the SessionFactory to fetch from Spring's root - * application context. - */ - protected String getSessionFactoryBeanName() { - return sessionFactoryBeanName; - } - - public void service(WebRequest request, WebResponse response, - WebRequestServicer servicer) throws IOException { - String svcValue = request.getParameterValue(ServiceConstants.SERVICE); - if (Tapestry.ASSET_SERVICE.equals(svcValue)) { - servicer.service(request, response); - return; - } - logger.debug("entering into Hibernate Request Filter " + " service:" + svcValue - + " context:" + request.getContextPath() + " activation:" - + request.getActivationPath() + " path:" + request.getPathInfo()); - SessionFactory sessionFactory = lookupSessionFactory(request); - Session session = null; - - // single session mode - - logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter"); - session = getSession(sessionFactory); - TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder( - session)); - - try { - servicer.service(request, response); - } - - finally { - // single session mode - TransactionSynchronizationManager.unbindResource(sessionFactory); - logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter"); - try { - closeSession(session, sessionFactory); - } catch (RuntimeException ex) { - logger.error("Unexpected exception on closing Hibernate Session", ex); - } - } - - } - - /** For injection. */ - public final void setBeanFactoryHolder(SpringBeanFactoryHolder beanFactoryHolder) { - _beanFactoryHolder = beanFactoryHolder; - } - - protected SessionFactory lookupSessionFactory(WebRequest request) { - if (logger.isDebugEnabled()) { - logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() - + "' for OpenSessionInViewFilter"); - } - return (SessionFactory) _beanFactoryHolder.getBeanFactory().getBean( - getSessionFactoryBeanName(), SessionFactory.class); - } - - protected Session getSession(SessionFactory sessionFactory) - throws DataAccessResourceFailureException { - return openSession(sessionFactory); - } - - protected Session openSession(SessionFactory sessionFactory) - throws DataAccessResourceFailureException { - Session session = SessionFactoryUtils.getSession(sessionFactory, true); - // session.setFlushMode(FlushMode.NEVER); - session.setFlushMode(FlushMode.COMMIT); - return session; - } - - protected void closeSession(Session session, SessionFactory sessionFactory) { - session.close(); - // SessionFactoryUtils.releaseSession(session, sessionFactory); - } - - } - - }}} - - - The wiring into tapestry is the following: - {{{ - <service-point id="HibernateServicerFilter" - interface="org.apache.tapestry.services.WebRequestServicerFilter"> - <invoke-factory> - <construct class="actualis.web.tapestry.framework.HibernateRequestFilter"> - <set-object property="beanFactoryHolder" value="service:hivemind.lib.DefaultSpringBeanFactoryHolder"/> - </construct> - </invoke-factory> - </service-point> - - <contribution configuration-id="tapestry.request.WebRequestServicerPipeline"> - <filter name="HibernateServicerFilter" - object="service:HibernateServicerFilter"/> - </contribution> - }}} - - == Step 1: Hivemind Configuration == - - Note: You can skip this step by downloading tapestry-spring.jar from http://sourceforge.net/projects/diaphragma and placing it on your classpath. Continue reading, if you're interested in how it works... @@ -442, +275 @@ public abstract DAOFactory getDao(); }}} + == Injecting Spring Beans == + + You may inject beans managed by Spring into pages and components just like you inject anything else as described by [http://tapestry.apache.org/tapestry4/UsersGuide/injection.html]. You can describe the injection in the .page/.jwc file or using an @InjectObject annotation. Just use the 'spring:' prefix like: + {{{ + @InjectObject("spring:name.from.applicationContext.xml") + }}} + + You may also wire Spring managed beans in HiveMind services such as IEngine services. + {{{ + <service-point id="MyService" interface="org.apache.tapestry.engine.IEngineService"> + <invoke-factory> + <construct class="engine.MyService"> + <set-object property="springBean" value="spring:name.of.spring.bean"/> + </construct> + </invoke-factory> + </service-point> + }}} + + + == Spring, Tapestry and Hibernate == + + In order to use lazy loading and for most Spring Hibernate templates, you need access to a Hibernate Session. The traditionnal Spring solution is to use the "OpenSessionInView" pattern where a Hibernate session is open for the whole request. + However, OpenSessionInView has to be configured in the web.xml which is not very friendly when you setup some particular Tapestry URLs. + + A better solution is to integrate the session opening/closing in Hivemind by using the WebRequestServicerFilter interface. Also, for Tapestry assets, it is not necessary to create a session. This code is based on the Spring OpenSessionInViewFilter. + + This requires to implement a class and wire it into Tapestry. + Here is the code for the class: + + {{{ + package actualis.web.tapestry.framework; + + import java.io.IOException; + + import org.apache.commons.logging.Log; + import org.apache.commons.logging.LogFactory; + import org.apache.hivemind.lib.SpringBeanFactoryHolder; + import org.apache.tapestry.Tapestry; + import org.apache.tapestry.services.ServiceConstants; + import org.apache.tapestry.services.WebRequestServicer; + import org.apache.tapestry.services.WebRequestServicerFilter; + import org.apache.tapestry.web.WebRequest; + import org.apache.tapestry.web.WebResponse; + import org.hibernate.FlushMode; + import org.hibernate.Session; + import org.hibernate.SessionFactory; + import org.springframework.dao.DataAccessResourceFailureException; + import org.springframework.orm.hibernate3.SessionFactoryUtils; + import org.springframework.orm.hibernate3.SessionHolder; + import org.springframework.transaction.support.TransactionSynchronizationManager; + + public class HibernateRequestFilter implements WebRequestServicerFilter { + + private static Log logger = LogFactory.getLog(HibernateRequestFilter.class); + + public static final String DEFAULT_SESSION_FACTORY_BEAN_NAME = "sessionFactory"; + + private String sessionFactoryBeanName = DEFAULT_SESSION_FACTORY_BEAN_NAME; + + private SpringBeanFactoryHolder _beanFactoryHolder; + + /** + * Set the bean name of the SessionFactory to fetch from Spring's root + * application context. Default is "sessionFactory". + * + * @see #DEFAULT_SESSION_FACTORY_BEAN_NAME + */ + public void setSessionFactoryBeanName(String sessionFactoryBeanName) { + this.sessionFactoryBeanName = sessionFactoryBeanName; + } + + /** + * Return the bean name of the SessionFactory to fetch from Spring's root + * application context. + */ + protected String getSessionFactoryBeanName() { + return sessionFactoryBeanName; + } + + public void service(WebRequest request, WebResponse response, + WebRequestServicer servicer) throws IOException { + String svcValue = request.getParameterValue(ServiceConstants.SERVICE); + if (Tapestry.ASSET_SERVICE.equals(svcValue)) { + servicer.service(request, response); + return; + } + logger.debug("entering into Hibernate Request Filter " + " service:" + svcValue + + " context:" + request.getContextPath() + " activation:" + + request.getActivationPath() + " path:" + request.getPathInfo()); + SessionFactory sessionFactory = lookupSessionFactory(request); + Session session = null; + + // single session mode + + logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter"); + session = getSession(sessionFactory); + TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder( + session)); + + try { + servicer.service(request, response); + } + + finally { + // single session mode + TransactionSynchronizationManager.unbindResource(sessionFactory); + logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter"); + try { + closeSession(session, sessionFactory); + } catch (RuntimeException ex) { + logger.error("Unexpected exception on closing Hibernate Session", ex); + } + } + + } + + /** For injection. */ + public final void setBeanFactoryHolder(SpringBeanFactoryHolder beanFactoryHolder) { + _beanFactoryHolder = beanFactoryHolder; + } + + protected SessionFactory lookupSessionFactory(WebRequest request) { + if (logger.isDebugEnabled()) { + logger.debug("Using SessionFactory '" + getSessionFactoryBeanName() + + "' for OpenSessionInViewFilter"); + } + return (SessionFactory) _beanFactoryHolder.getBeanFactory().getBean( + getSessionFactoryBeanName(), SessionFactory.class); + } + + protected Session getSession(SessionFactory sessionFactory) + throws DataAccessResourceFailureException { + return openSession(sessionFactory); + } + + protected Session openSession(SessionFactory sessionFactory) + throws DataAccessResourceFailureException { + Session session = SessionFactoryUtils.getSession(sessionFactory, true); + // session.setFlushMode(FlushMode.NEVER); + session.setFlushMode(FlushMode.COMMIT); + return session; + } + + protected void closeSession(Session session, SessionFactory sessionFactory) { + session.close(); + // SessionFactoryUtils.releaseSession(session, sessionFactory); + } + + } + + }}} + + + The wiring into tapestry is the following: + {{{ + <service-point id="HibernateServicerFilter" + interface="org.apache.tapestry.services.WebRequestServicerFilter"> + <invoke-factory> + <construct class="actualis.web.tapestry.framework.HibernateRequestFilter"> + <set-object property="beanFactoryHolder" value="service:hivemind.lib.DefaultSpringBeanFactoryHolder"/> + </construct> + </invoke-factory> + </service-point> + + <contribution configuration-id="tapestry.request.WebRequestServicerPipeline"> + <filter name="HibernateServicerFilter" + object="service:HibernateServicerFilter"/> + </contribution> + }}} + --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
