Versions Compared

Key

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

...

Customized WW/XW ObjectFactory

TODO: Document

...

Session backed Bean Factory

The idea is to simply create a retrieve-or-create bean factory:

Code Block
titleSessionBackedBeanFactory.java
borderStylesolid

package net.itneering.core.spring.session;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

import com.opensymphony.xwork.ActionContext;

import java.util.Map;

/**
 * SessionBackedBeanFactory tries to lookup beans by name in XWork session. If not found,
 * it tries to instantiate new bean and attaches it to said session.
 *
 * @author <a href="mailto:gielen@it-neering.net">Rene Gielen</a>
 */

public abstract class SessionBackedBeanFactory implements BeanFactoryAware, SessionProxy {

    BeanFactory beanFactory = null;

    /**
     * Find a component by name in session scoped storage implementation. If not found, try to instantiate new one by
     * {@link org.springframework.beans.factory.BeanFactory#getBean(String)}. Then found component will be attached
     * to session store implementation.
     *
     * @param componentName
     * @return The requested component, if found.
     */
    public Object getSessionComponent( String componentName ) {
        Object result = getSession().get(componentName);
        if ( result == null ) {
            result = beanFactory.getBean(componentName);
            storeComponent(componentName, result);
        }
        return result;
    }

    public void storeComponent(String componentName, Object component ) {
        getSession().put(componentName, component);
    }

    /**
     * Actual implementation of the session scoped storage Map.
     * Lookup {@link com.opensymphony.xwork.ActionContext#getSession()}.
     *
     * @return The Map for keeping session objects.
     */
    public Map getSession() {
        return ActionContext.getContext().getSession();
    }

    /**
     * Callback that supplies the owning factory to a bean instance.
     * <p>Invoked after population of normal bean properties but before an init
     * callback like InitializingBean's afterPropertiesSet or a custom init-method.
     *
     * @param beanFactory owning BeanFactory (may not be null).
     *                    The bean can immediately call methods on the factory.
     *
     * @throws org.springframework.beans.BeansException
     *          in case of initialization errors
     * @see org.springframework.beans.factory.BeanInitializationException
     */
    public void setBeanFactory( BeanFactory beanFactory ) throws BeansException {
        this.beanFactory = beanFactory;
    }
}

Example applicationContext setup:

Code Block
titleapplicationContext.xml
langxml
borderStylesolid

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans default-autowire="byName">
    <bean id="sessionBeanProxy" class="net.itneering.core.spring.session.SessionBackedBeanFactory" singleton="true"/>
    <bean id="securityContextComponent" class="net.itneering.security.component.DefaultSecurityContextComponent" singleton="false" />
</beans>

Example action use:

Code Block
titleSessionBackedBeanFactory.java
borderStylesolid

package net.itneering.xwork.action;

import com.opensymphony.xwork.ActionSupport;
import net.itneering.core.spring.session.SessionBackedBeanFactory;
import net.itneering.security.component.DefaultSecurityContextComponent;

/**
 * Simple sessionBeanProxy aware action.
 *
 * @author <a href="mailto:gielen@it-neering.net">Rene Gielen</a>
 * @version $Revision: 1.1 $
 */

public class SecurityAwareAction extends ActionSupport implements PrincipalAware {

    private static final Logger log = Logger.getLogger(SecurityAwareAction.class);

    protected SessionBackedBeanFactory sessionBeanProxy;

    /**
     * For Spring wiring usage.
     *
     * @param sessionBeanProxy The sessionBeanProxyto use.
     */
    public void setSessionBeanProxy( SessionBackedBeanFactory sessionBeanProxy ) {
        this.sessionBeanProxy = sessionBeanProxy;
    }

    /**
     * Getter for actions security context.
     *
     * @return The securityContextComponent set by IoC.
     */
    public SecurityContextComponent getSecurityContextComponent() {
        return sessionBeanProxy!= null ? sessionBeanProxy.getSessionComponent("securityContextComponent") : null;
    }

    /**
     * Get the current User Principal for this session.
     *
     * @return The User Principal.
     */
    public UserEntity getPrincipal() {
        try {
            return getSecurityContextComponent().getPrincipal();
        } catch ( NullPointerException e ) {
            return null;
        }
    }

    /**
     * Indicate whether we have a logged in User.
     *
     * @return <tt>true</tt> if logged in.
     */
    public boolean isLoggedIn() {
        return getPrincipal() != null;
    }

}

Auto proxied Session backed Component Factory

Does anyone have an implementation of this? (Eric Molitor)
The intention was a bit different for this one, so I tried to clarify headings. Nice idea, though ... (Rene Gielen).
The theory here is to create a custom Pointcut class that utilizes the ComponentConfiguration retrieved from the DefaultComponentManager (which loads the Component list from components.xml). The getClassFilter() matches anything that implements one of the Components in the ComponentConfiguration. The Pointcut is then registered as an advisor for all beans (AutoProxy via Springs DefaultAdvisorAutoProxyCreator). The Advice implementation looks at which Component is implmented and fetches the apporiate value out of the Session and calls the Components setter method.
TODO: Document, create example