Versions Compared

Key

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

...

XWork/WebWork specific solutions

Preface

TODO: DocumentWebWork is based on XWork, and XWork is not tied to the web layer. So when dealing with session scoped stuff, WW users might want to use XWorks session abstraction features to keep their application independent from web context. This is why we will discuss some XW/WW specific solutions below.

Custom TargetSource, the WebWork way

...

Example applicationContext setup :(note that the session scoped bean has to be setup with singleton="false"):

Code Block
title
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
titleSessionBackedBeanFactorySecurityAwareAction.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;
    }

}
...
}

For well known session scoped components, you might get more convenience by subclassing SessionBackedBeanFactory:

Code Block
titleSecurityAwareSessionBeanProxy.java
borderStylesolid

package net.itneering.security.component;

import net.itneering.core.spring.session.SessionBackedBeanFactory;

/**
 * SecurityAwareSessionBeanProxy.
 *
 * @author <a href="mailto:gielen@it-neering.net">Rene Gielen</a>
 */

public class SecurityAwareSessionBeanProxy extends SessionBackedBeanFactory {

    String securityContextComponentName = "securityContextComponent";

    /**
     * Make component name configurable by spring setup
     */
    public void setSecurityContextComponentName( String securityContextComponentName ) {
        this.securityContextComponentName = securityContextComponentName;
    }

    public SecurityContextComponent getSecurityContextComponent() {
        return (SecurityContextComponent) getSessionComponent(securityContextComponentName);
    }

}

Again example applicationContext setup:

Code Block
titleapplicationContext2.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="mySecurityContextComponent" class="net.itneering.security.component.DefaultSecurityContextComponent" singleton="false" />
    <bean id="sessionBeanProxy" class="net.itneering.security.component.SecurityAwareSessionBeanProxy" singleton="true">
        <property name="securityContextComponentName" value="mySecurityContextComponent" />
    </bean>
</beans>

Example action use:

Code Block
titleSecurityAwareAction2.java
borderStylesolid

package net.itneering.xwork.action;

import com.opensymphony.xwork.ActionSupport;
import net.itneering.security.component.SecurityAwareSessionBeanProxy;
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 SecurityAwareSessionBeanProxy sessionBeanProxy;

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

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

As said, the solution is very simple. You will get no ties to web layer, and the configuration is really simple, there is no need for proxy definitions in applicationContext.xml etc.
The main disadvantage is that you will not be able to wire session scoped beans directly into your actions, you will have to use the indirection via the session backed bean factory. And, as always when dealing with XWork session abstraction, you have to take care for a action context to be setup.

Auto proxied Session backed Component Factory

...