Tapestry4Spring

来源:互联网 发布:软件开发技术路线 编辑:程序博客网 时间:2024/05/04 20:04

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.

(Basic knowledge of Java, Tapestry, and Spring assumed.)

Step 1: Hivemind Configuration

Note: You can skip this step by downloading tapestry-spring.jar from [WWW] http://sourceforge.net/projects/diaphragma and placing it on your classpath.

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="diaphragma.tapspr" version="1.0.0">    <implementation        service-id="hivemind.lib.DefaultSpringBeanFactoryHolder">        <invoke-factory>            <construct autowire-services="false"                class="diaphragma.tapspr.XSpringBeanFactoryHolderImpl">                <event-listener                    service-id="hivemind.ShutdownCoordinator" />                <set-object property="context"                    value="service:tapestry.globals.WebContext" />            </construct>        </invoke-factory>    </implementation></module>

Next job is to create XSpringBeanFactoryHolderImpl.java. It look like this:

package diaphragma.tapspr;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;public class XSpringBeanFactoryHolderImpl extends SpringBeanFactoryHolderImpl    implements RegistryShutdownListener{    private WebContext context;    public XSpringBeanFactoryHolderImpl()    {    }    public void setContext(WebContext webcontext)    {        context = webcontext;    }    public WebContext getContext()    {        return context;    }    public BeanFactory getBeanFactory()    {        if(super.getBeanFactory() == null)            super.setBeanFactory(XWebApplicationContextUtils.getWebApplicationContext(getContext()));        return super.getBeanFactory();    }    public void registryDidShutdown()    {        ((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 XWebApplicationContextUtils.java

package diaphragma.tapspr;import org.apache.tapestry.web.WebContext;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.context.support.WebApplicationContextUtils;public class XWebApplicationContextUtils extends WebApplicationContextUtils{    public XWebApplicationContextUtils()    {    }    public static WebApplicationContext getWebApplicationContext(WebContext webcontext)    {        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;    }}

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>        <param-name>contextConfigLocation</param-name>        <param-value>/WEB-INF/applicationContext.xml</param-value></context-param><listener>        <listener-class>                org.springframework.web.context.ContextLoaderListener        </listener-class></listener>

And now let us try a simple XML file (place it under WEB-INF/ as applicationContext.xml).

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"         "http://www.springframework.org/dtd/spring-beans.dtd"><beans>        <bean id="person" class="com.example.model.Person">        <property name="name">                <value>Nanda Firdausi</value>        </property>        </bean></beans>

It defines one object with one property.

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).

<?xml version="1.0" encoding="UTF-8"?>        <!DOCTYPE page-specification PUBLIC        "-//Apache Software Foundation//Tapestry Specification 4.0//EN"        "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">        <page-specification class="org.apache.tapestry.html.BasePage">        <inject property="person" object="spring:person" /></page-specification>

The page template is trivial, one super-simple-example is like this (Home.html).

<span jwcid="@Insert" value="ognl:person.name" /> 

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

last edited 2005-10-28 20:39:17 by NandaFirdausi

原创粉丝点击