You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Apache Wiki <wi...@apache.org> on 2009/12/10 11:55:47 UTC

[Tapestry Wiki] Update of "HowToRunTapestry5Websphere" by ChristianKoeberl

Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Tapestry Wiki" for change notification.

The "HowToRunTapestry5Websphere" page has been changed by ChristianKoeberl.
The comment on this change is: added new page for Tapestry on Websphere.
http://wiki.apache.org/tapestry/HowToRunTapestry5Websphere

--------------------------------------------------

New page:
= Tapestry on Websphere =

Running Tapestry on Websphere is not so easy (actually running any modern web framework)! I'm talking about the "real" Websphere - not the Websphere Community Edition (CE).

The main problem with Websphere is that it does not support the standards defined in the [[http://java.sun.com/products/servlet/|Java Servlet Specification]]. Therefore some workarounds have to be applied to run Tapestry.

== Fix Packs, Filter Compatibility ==
Pleas read (and follow) [[http://tapestry.apache.org/tapestry5/websphere.html|Tapestry 5 Deployment Notes: WebSphere]].

== Filter initializing - Multiple Registries ==

Websphere calls the init-method on Servlet filters every time a client hits the matching URL and any of the init-methods haven't finished yet (according to Servlet Spec the init-method must only be called once). The Tapestry filter initializes the IoC registry in "init" - so, if many clients (or system management agents) hit your page on redeploy, you'll have a bunch of Tapestry IoC registries running.

You will notice this by finding something like this in your logs:
{{{
[WebContainer : 6] ERROR () org.apache.tapestry5.ioc.internal.SerializationSupport - Setting a new service proxy provider when there's already an existing provider. This may indicate that you have multiple IoC Registries.
}}}

When you have this problem there are two ways out:
 1. avoid clients from sending requests to your app before it has finished initializing (e.g. by showing a "site down" page on your Apache)
 2. or change Tapestry filter to a listener and a filter. The listener is only called once on startup - so everything's ok.

Here is the code for option 2:

!TapestryListener.java
{{{
package org.apache.tapestry5.mine;


import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tapestry5.internal.ServletContextSymbolProvider;
import org.apache.tapestry5.internal.TapestryAppInitializer;
import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.def.ModuleDef;
import org.apache.tapestry5.ioc.services.SymbolProvider;
import org.apache.tapestry5.services.HttpServletRequestHandler;
import org.apache.tapestry5.services.ServletApplicationInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The TapestryListener is responsible for initializing Tapestry.
 * <p/>
 * The application is configured via context-level init parameters.
 * <p/>
 * <dl>
 * <dt>tapestry.app-package</dt>
 * <dd>The application package (used to search for pages, components, etc.)</dd>
 * <dt>tapestry.application-name</dt>
 * <dd>The name of the application (used for </dd>
 * </dl>
 */
public class TapestryListener implements ServletContextListener
{
    private final Logger logger = LoggerFactory.getLogger(TapestryListener.class);

    private ServletContext context;

    private Registry registry;

    private HttpServletRequestHandler handler;

    /**
     * Key under which that Tapestry IoC {@link org.apache.tapestry5.ioc.Registry} is stored in the ServletContext. This
     * allows other code, beyond Tapestry, to obtain the Registry and, from it, any Tapestry services. Such code should
     * be careful about invoking {@link org.apache.tapestry5.ioc.Registry#cleanupThread()} appopriately.
     */
    public static final String REGISTRY_CONTEXT_NAME = "org.apache.tapestry5.application-registry";

    /**
     * Initializes the application using the {@link TapestryAppInitializer}. The application name is the capitalization of
     * the context parameter "org.apache.tapestry5.application-name".
     */
    public void contextInitialized(ServletContextEvent sce)
    {
        context = sce.getServletContext();

        String appName = sce.getServletContext().getInitParameter("org.apache.tapestry5.application-name");
        if(appName == null)
        	appName = "app";

        SymbolProvider provider = new ServletContextSymbolProvider(context);

        TapestryAppInitializer appInitializer = new TapestryAppInitializer(logger, provider, appName, "servlet");

        appInitializer.addModules(provideExtraModuleDefs(context));

        registry = appInitializer.createRegistry();

        context.setAttribute(REGISTRY_CONTEXT_NAME, registry);

        ServletApplicationInitializer ai = registry.getService("ServletApplicationInitializer",
                                                               ServletApplicationInitializer.class);

        ai.initializeApplication(context);

        registry.performRegistryStartup();

        handler = registry.getService("HttpServletRequestHandler", HttpServletRequestHandler.class);

        init(registry);

        appInitializer.announceStartup();
    }

    protected final ServletContext getServletContext()
    {
        return context;
    }

    /**
     * Invoked from {@link #init(FilterConfig)} after the Registry has been created, to allow any additional
     * initialization to occur. This implementation does nothing, and my be overriden in subclasses.
     *
     * @param registry from which services may be extracted
     */
    protected void init(Registry registry)
    {
    	// empty for override
    }

    /**
     * Overridden in subclasses to provide additional module definitions beyond those normally located. This
     * implementation returns an empty array.
     */
    protected ModuleDef[] provideExtraModuleDefs(ServletContext context)
    {
        return new ModuleDef[0];
    }

    public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        try
        {
            boolean handled = handler.service((HttpServletRequest) request, (HttpServletResponse) response);

            if (!handled) chain.doFilter(request, response);
        }
        finally
        {
            registry.cleanupThread();
        }
    }

    /**
     * Shuts down and discards the registry.  Invokes {@link #destroy(org.apache.tapestry5.ioc.Registry)} to allow
     * subclasses to peform any shutdown logic, then shuts down the registry, and removes it from the ServletContext.
     */
    public void contextDestroyed(ServletContextEvent sce)
    {
        destroy(registry);

        registry.shutdown();

        getServletContext().removeAttribute(REGISTRY_CONTEXT_NAME);

        registry = null;
        context = null;
        handler = null;
    }

    /**
     * Invoked from {@link #destroy()} to allow subclasses to add additional shutdown logic to the filter. The Registry
     * will be shutdown after this call. This implementation does nothing, and may be overridden in subclasses.
     *
     * @param registry
     */
    protected void destroy(Registry registry)
    {
    	// empty for override
    }
}
}}}

!TapestryFilter.java
{{{
package org.apache.tapestry5.mine;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.services.HttpServletRequestHandler;

/**
 * The TapestryFilter is responsible for intercepting all requests into the web application. It identifies the requests
 * that are relevant to Tapestry, and lets the servlet container handle the rest.
 */
public class TapestryFilter implements Filter
{
    private HttpServletRequestHandler handler;

    private Registry registry;

    /**
     * Initializes the filter 
     */
    public final void init(FilterConfig filterConfig) throws ServletException
    {
    	registry = (Registry) filterConfig.getServletContext().getAttribute(TapestryListener.REGISTRY_CONTEXT_NAME);

    	if(registry == null)
    	{
    		throw new ServletException("No Tapestry registry found. Please check that TapestryListener is added as <listener>");
    	}

        handler = registry.getService("HttpServletRequestHandler", HttpServletRequestHandler.class);
    }

    public final void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        try
        {
            boolean handled = handler.service((HttpServletRequest) request, (HttpServletResponse) response);

            if (!handled) chain.doFilter(request, response);
        }
        finally
        {
            registry.cleanupThread();
        }
    }

    public final void destroy()
    {
        registry = null;
        handler = null;
    }
}
}}}

web.xml
{{{
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
        PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

	<display-name>My Tapestry 5 Test Application</display-name>

	<context-param>
		<param-name>tapestry.app-package</param-name>
		<param-value>fill in my-app-package</param-value>
	</context-param>

	<filter>
		<filter-name>app</filter-name>
		<filter-class>org.apache.tapestry5.mine.TapestryFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>app</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

	<listener>
		<listener-class>org.apache.tapestry5.mine.TapestryListener</listener-class>
	</listener>

</web-app>
}}}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tapestry.apache.org
For additional commands, e-mail: dev-help@tapestry.apache.org