Dear Wiki user, You have subscribed to a wiki page or wiki category on "Jakarta-tapestry Wiki" for change notification.
The following page has been changed by DavidPeterson: http://wiki.apache.org/jakarta-tapestry/Tapestry4Spring The comment on the change is: Simplified text, improved the english and made some fixes ------------------------------------------------------------------------------ - = Combining Tapestry 4.0, Hivemind 1.1 and Spring = + = 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. - Many people have asked how to combine the above solution, I was also curious about that and spent one-and-a-half-days figuring out the best way to do that. Reasons behind that are: - 1. Tapestry is a good framework for web UI. - 2. Spring is a good container framework. Spring is also a good example of software project development. - 3. Hivemind, for me, is not mature enough (and proved that when I found bug while I did this project). Hivemind has a good future, but I doubt it will 100% replace Spring. Both of them have their own advantages. - For the release version, I like combination of Tapestry+Spring+Hibernate, but they are all growing very fast and I really like to try milestone versions of Tapestry4+Spring+Hibernate30+(Hivemind11). I'll omit Hibernate in my explanation since the hard part is between Tapestry and Spring. Once Spring is correctly configured, Hibernate solution is very pluggable. + (''Basic knowledge of Java, Tapestry, and Spring assumed.'') - Magic reference for Tapestry and Spring combination is in Spring Reference. We still can use that solution, but we will lose the pretty combination offered by Tapestry+Hivemind. Another disadvantage is the solution extended BaseEngine, and BaseEngine extension is deprecated in Tapestry 4. + == 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. - ''Basic knowledge of Java, Tapestry, and Spring assumed.'' - == Hivemind Configuration == - '''You can skip this step''' (Hivemind Configuration) by downloading tapestry-spring.jar from http://sourceforge.net/projects/diaphragma and placing it on your classpath. Then skip down to Spring Configuration and you should be able to reference Spring beans from Tapestry 4. ''Or, keep reading below if you're interested in how it works...'' - Hivemind is related intimately with Tapestry, HLS (the author of both) has provide a way to easily work with Hivemind from within Tapestry. Like Spring, Hivemind uses special XML metadata. Hivemind also has its own metadata, and so does Tapestry. If we want to contribute to the whole Hivemind registry, the easiest way is by creating hivemodule.xml in your WEB-INF directory. Here is what you need in this project: + Continue reading, if you're interested in how it works... + + + Tapestry uses Hivemind, behind the scenes, for dependency-injection. Hivemind's XML configuration is similar to Spring. The easiest way to contribute to the whole Hivemind registry is by creating hivemodule.xml in your WEB-INF directory. + + Here is what you need in this project to provide a new implementation of the DefaultSpringBeanFactoryHolder: + {{{ <?xml version="1.0"?> - <module id="testing" version="1.0.0"> + <module id="diaphragma.tapspr" version="1.0.0"> + <implementation - <implementation service-id="hivemind.lib.DefaultSpringBeanFactoryHolder"> + service-id="hivemind.lib.DefaultSpringBeanFactoryHolder"> - <invoke-factory> + <invoke-factory> - <construct autowire-services="false" + <construct autowire-services="false" - class="id.co.nincec.dymension.TestingSpringBeanFactoryHolderImpl"> + class="diaphragma.tapspr.XSpringBeanFactoryHolderImpl"> - <event-listener + <event-listener - service-id="hivemind.ShutdownCoordinator" /> + service-id="hivemind.ShutdownCoordinator" /> - <set-object property="context" + <set-object property="context" - value="service:tapestry.globals.WebContext" /> + value="service:tapestry.globals.WebContext" /> - </construct> + </construct> - </invoke-factory> + </invoke-factory> - </implementation> + </implementation> - <module> + </module> }}} - Here, we define a service to override a default service in Hivemind. We need to override it since we will be working in a web application only and we don't want any dependancy with class org.apache.tapestry.engine.BaseEngine (like I say, the class will be deprecated in Tapestry4) - - Next job is to create TestingSpringBeanFactoryHolderImpl.java. It look like this: + Next job is to create XSpringBeanFactoryHolderImpl.java. It look like this: {{{ + package diaphragma.tapspr; - /** - * - */ - package id.co.nincec.dymension; + import java.io.PrintStream; + import org.apache.hivemind.events.RegistryShutdownListener; import org.apache.hivemind.lib.impl.SpringBeanFactoryHolderImpl; import org.apache.tapestry.web.WebContext; import org.springframework.beans.factory.BeanFactory; + import org.springframework.context.ConfigurableApplicationContext; - /** - * @author enefem - * - */ - public class TestingSpringBeanFactoryHolderImpl extends - SpringBeanFactoryHolderImpl implements RegistryShutdownListener { + public class XSpringBeanFactoryHolderImpl extends SpringBeanFactoryHolderImpl + implements RegistryShutdownListener + { - private WebContext context; + private WebContext context; - public void setContext(WebContext context) { - this.context = context; - } + public XSpringBeanFactoryHolderImpl() + { + } - public WebContext getContext() { - return context; - } + public void setContext(WebContext webcontext) + { + context = webcontext; + } + public WebContext getContext() + { + return context; + } - public BeanFactory getBeanFactory() { - if (super.getBeanFactory() == null) { - super.setBeanFactory(TestingWebApplicationContextUtils - .getWebApplicationContext(getContext())); - } - return super.getBeanFactory(); - } + public BeanFactory getBeanFactory() + { + if(super.getBeanFactory() == null) + super.setBeanFactory(XWebApplicationContextUtils.getWebApplicationContext(getContext())); + return super.getBeanFactory(); + } + - public void registryDidShutdown() { + public void registryDidShutdown() + { - ((ConfigurableApplicationContext) super.getBeanFactory()).close(); + ((ConfigurableApplicationContext)super.getBeanFactory()).close(); - } + } } }}} As we can see, this class extends the default SpringBeanFactoryHolder. The important thing is what you see in getBeanFactory() method, there you define where our BeanFactory located. In this example, I use WebApplicationContextUtils.getRequiredWebApplicationContext() method. There is another method which doesn't throw exception WebApplicationContextUtils.getWebApplicationContext(). - Next, we implement TestingWebApplicationContextUtils.java + Next, we implement XWebApplicationContextUtils.java {{{ + package diaphragma.tapspr; - /** - * - */ - package id.co.nincec.dymension; import org.apache.tapestry.web.WebContext; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; + public class XWebApplicationContextUtils extends WebApplicationContextUtils + { - /** - * @author enefem - * - */ - public class TestingWebApplicationContextUtils extends - WebApplicationContextUtils { + public XWebApplicationContextUtils() + { + } - public static WebApplicationContext getWebApplicationContext(WebContext wc) { - Object attr = wc - .getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); - if (attr == null) { - return null; - } - if (attr instanceof RuntimeException) { - throw (RuntimeException) attr; - } - if (attr instanceof Error) { - throw (Error) attr; - } - if (!(attr instanceof WebApplicationContext)) { - throw new IllegalStateException( - "Root context attribute is not of type WebApplicationContext: " - + attr); - } - return (WebApplicationContext) attr; - } - public static WebApplicationContext getRequiredWebApplicationContext( + public static WebApplicationContext getWebApplicationContext(WebContext webcontext) - WebContext wc) throws IllegalStateException { - WebApplicationContext wac = getWebApplicationContext(wc); - if (wac == null) { - throw new IllegalStateException( - "No WebApplicationContext found: no ContextLoaderListener registered?"); - } - return wac; - } + { + Object obj = webcontext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); + if(obj == null) + return null; + if(obj instanceof RuntimeException) + throw (RuntimeException)obj; + if(obj instanceof Error) + throw (Error)obj; + if(!(obj instanceof WebApplicationContext)) + throw new IllegalStateException((new StringBuilder()).append("Root context attribute is not of type WebApplicationContext: ").append(obj).toString()); + else + return (WebApplicationContext)obj; + } + public static WebApplicationContext getRequiredWebApplicationContext(WebContext webcontext) + throws IllegalStateException + { + WebApplicationContext webapplicationcontext = getWebApplicationContext(webcontext); + if(webapplicationcontext == null) + throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?"); + else + return webapplicationcontext; + } } + }}} - == Spring Configuration == + == Step 2: Spring Configuration == Spring in servlet mode need two things, it needs the XML file for bean configuration and also a filter in web.xml. In web.xml, you will have to add this: {{{ <context-param> @@ -157, +152 @@ "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> - <bean id="person" class="id.co.nincec.dymension.page.Person"> + <bean id="person" class="com.example.model.Person"> <property name="name"> <value>Nanda Firdausi</value> </property> @@ -167, +162 @@ It defines one object with one property. - == See it works!! == + == Step 3: Access Spring property from Tapestry page specification == Now time to see whether our bean can be accessed from a Tapestry page. First, let us create the page specification (Home.page). @@ -179, +174 @@ "http://jakarta.apache.org/tapestry/dtd/Tapestry_3_1.dtd"> <page-specification class="org.apache.tapestry.html.BasePage"> + <inject property="person" object="spring:person" /> - <inject property="inuyasha" - object="spring:person" /> </page-specification> }}} - See, how easy it is to access Spring-managed beans from within a Tapestry page!! And so natural!! The page template is trivial, one super-simple-example is like this (Home.html). {{{ - <span jwcid="@Insert" value="ognl:inuyasha" /> + <span jwcid="@Insert" value="ognl:person.name" /> }}} - And we are finish!!! - I wait for comments, suggestions, and any other things related to this simple tutorial. + Please make comments, suggestions, and any other things related to this tutorial. ---- ''This information was originally written in an email to the Tapestry User's List on March 7, 2005 by Nanda Firdausi'' --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
