Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

A quite "clean" solution for web applications in general can be found at JA-SIG. The solution is well documented and can be found here. Below you will find a WebWork adoption of this solution.

XWork/WebWork specific solutions

Preface

TODO: Document

Custom TargetSource, the WebWork way

Here is a modified version of the TargetSource solution pointed out above that integrates with the existing WebWork session so doesn't require an additional filter or listener. Usage is pretty much the same, create an interface for your object and make sure that you always use that interface and not the underlying implementation or autowiring will fail. You can find more information on how to make this work by looking at the WebWorkTargetSource Shopping Cart Example.

Code Block
titleWebWorkTargetSource.java
borderStylesolid
package org.tuxbot.webwork.spring;

/* Portions Copyright 2005 The JA-SIG Collaborative.  All rights reserved.
 *  See license distributed with this file and
 *  available online at http://www.uportal.org/license.html
 */

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.target.AbstractPrototypeBasedTargetSource;
import org.springframework.beans.factory.DisposableBean;
import com.opensymphony.xwork.ActionContext;

import java.util.Map;

/**
 * This target source is to be used in collaberation with WebWork.
 * The target source binds the target bean to the Session retrieved from
 * WebWork. By default the bean is bound to the session
 * using the name of the target bean as part of the key. This can be overridden by setting
 * the <code>sessionKey</code> property to a not null value.
 *
 * @author Eric Dalquist <a href="mailto:edalquist@unicon.net">edalquist@unicon.net</a>
 * @author Eric Molitor <a href="mailto:eric@tuxbot.com">eric@tuxbot.com</a>
 * @version 1.0
 */
public class WebWorkTargetSource extends AbstractPrototypeBasedTargetSource implements DisposableBean {
    private final static Log LOG = LogFactory.getLog(WebWorkTargetSource.class);

    private transient Object noSessionInstance = null;
    private String sessionKey = null;
    private String compiledSessionKey = null;

    public WebWorkTargetSource() {
        this.updateBeanKey();
    }

    /**
     * @return Returns the sessionKey.
     */
    public String getSessionKey() {
        return this.sessionKey;
    }
    /**
     * @param sessionKey The sessionKey to set.
     */
    public void setSessionKey(String sessionKey) {
        this.sessionKey = sessionKey;
        this.updateBeanKey();
    }
    /**
     * @see org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource#setTargetBeanName(java.lang.String)
     */
    public void setTargetBeanName(String targetBeanName) {
        super.setTargetBeanName(targetBeanName);
        this.updateBeanKey();
    }

    /**
     * @see org.springframework.aop.TargetSource#getTarget()
     */
    public Object getTarget() throws Exception {
        final Map session = ActionContext.getContext().getSession();

        if (session == null) {
            LOG.warn("No Session found for thread '" + Thread.currentThread().getName() + "'");

            if (this.noSessionInstance == null) {
                this.noSessionInstance = this.newPrototypeInstance();

                if (LOG.isDebugEnabled()) {
                    LOG.debug("Created instance of '" + this.getTargetBeanName() + "', not bound to any webWorkSession.");
                }
            }
            else {
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Found instance of '" + this.getTargetBeanName() + "', not bound to any webWorkSession.");
                }
            }

            return this.noSessionInstance;
        }
        else {
            String beanKey = this.compiledSessionKey;

            Object instance = session.get(beanKey);
            if (instance == null) {
                instance = this.newPrototypeInstance();
                session.put(beanKey, instance);

                if (LOG.isDebugEnabled()) {
                    LOG.debug("Created instance of '" + this.getTargetBeanName() + "', bound to webWorkSession for '" + Thread.currentThread().getName() + "' using key '" + beanKey + "'.");
                }
            }
            else if (LOG.isDebugEnabled()) {
                LOG.debug("Found instance of '" + this.getTargetBeanName() + "', bound to webWorkSession for '" + Thread.currentThread().getName() + "' using key '" + beanKey + "'.");
            }

            return instance;
        }
    }

    /**
     * @see org.springframework.beans.factory.DisposableBean#destroy()
     */
    public void destroy() throws Exception {
        if (this.noSessionInstance != null && this.noSessionInstance instanceof DisposableBean) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Destroying sessionless bean instance '" + this.noSessionInstance + "'");
            }

            ((DisposableBean)this.noSessionInstance).destroy();
        }
    }

    /**
     * Generates the key to store the bean in the session with.
     */
    private void updateBeanKey() {
        if (this.sessionKey == null) {
            final StringBuffer buff = new StringBuffer();

            buff.append(this.getClass().getName());
            buff.append("_");
            buff.append(this.getTargetBeanName());

            this.compiledSessionKey = buff.toString();
        }
        else {
            this.compiledSessionKey = this.sessionKey;
        }
    }
}

XWork/WebWork specific solutions

Preface

...

Customized ApplicationContext Implementation

...