Overriding PopulationStrategy per ActionBean

How to use non-default PopulationStrategy only on particular ActionBean(s)

PopulationStrategy is configurable globally, but sometimes it's convenient if we could use different population strategy for a particular action bean. This entry shows you how to achieve it by using a custom population strategy implementation.

Create the custom population strategy and the annotation

The custom population strategy:

SelectivePopulationStrategy
 
public class SelectivePopulationStrategy implements PopulationStrategy 
{ 
private static final Log LOG = Log.getInstance(SelectivePopulationStrategy.class); 

private Configuration config; 
private PopulationStrategy defaultDelegate; 
private Map<Class<? extends PopulationStrategy>, PopulationStrategy> delegates = 
new HashMap<Class<? extends PopulationStrategy>, PopulationStrategy>(); 
private Map<Class<? extends ActionBean>, PopulationStrategy> actionBeanStrategies = 
new HashMap<Class<? extends ActionBean>, PopulationStrategy>(); 

protected PopulationStrategy getDelegate(InputTagSupport tag) 
throws StripesJspException 
{ 
ActionBean actionBean = tag.getActionBean(); 
if (actionBean == null) 
return defaultDelegate; 

// check cache 
Class<? extends ActionBean> beanType = actionBean.getClass(); 
PopulationStrategy delegate = actionBeanStrategies.get(beanType); 
if (delegate != null) 
return delegate; 

CustomPopulationStrategy annotation = 
beanType.getAnnotation(CustomPopulationStrategy.class); 
if (annotation == null) 
{ 
delegate = defaultDelegate; 
} 
else 
{ 
Class<? extends PopulationStrategy> type = annotation.value();
delegate = delegates.get(type); 
if (delegate == null) 
{ 
try 
{ 
delegate = type.newInstance(); 
delegate.init(config); 
delegates.put(type, delegate); 
} 
catch (Exception e) 
{ 
delegate = defaultDelegate; 
LOG.info("Could not instantiate population strategy" 
+ " of name [" + type + "]", e); 
} 
} 
} 

// cache and return 
actionBeanStrategies.put(beanType, delegate); 
return delegate; 
} 

public Object getValue(InputTagSupport tag) throws StripesJspException 
{ 
PopulationStrategy strategy = getDelegate(tag); 
Object value = (strategy).getValue(tag); 
return value; 
} 

public void init(Configuration configuration) throws Exception
{ 
this.config = configuration; 
defaultDelegate = new DefaultPopulationStrategy(); 
defaultDelegate.init(config); 
} 
} 

The annotation:

CusomPopulationStrategy
 
@Retention(RetentionPolicy.RUNTIME) 
public @interface CustomPopulationStrategy 
{ 
Class<? extends PopulationStrategy> value() 
default DefaultPopulationStrategy.class; 
} 

Annotate your ActionBean

Drop the SelectivePopulationStrategy into Stripes' extensions package and annotate your action bean.
Assuming you want to use BeanFirstPopulationStrategy on your ExampleActionBean, it would look as follows.

 
@CustomPopulationStrategy(BeanFirstPopulationStrategy.class) 
public class ExampleActionBean ... 
{ 
... 
} 

The other (unannotated) action beans will use the DefaultPopulationStrategy.