I want to extend and register my own function as detailed here:
http://static.springsource.org/spring/docs/3.0.x/reference/expressions.html see section: 6.5.11 Functions.
However, I wish to use this expression from a spring xml file and not in code as presented in the page.
How do I get a reference to the "StandardEvaluationContext" object used by spring while parsing my xml file? without having that spring can't find my registered function.
Thanks,
Yair
So, the solution I found is:
public class DBCustomExpressionRegistration implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
if (beanFactory instanceof ConfigurableBeanFactory) {
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
cbf.setBeanExpressionResolver(new StandardBeanExpressionResolver(){
@Override
protected void customizeEvaluationContext(
StandardEvaluationContext evalContext) {
evalContext.addMethodResolver(new InfraReflectiveMethodResolver());
}
});
}
}
public String getDbConfig(String param){
Configuration configuration = ConfigurationFactory.getConfiguration();
@SuppressWarnings("unchecked")
Iterator<String> keys = configuration.getKeys();
while(keys.hasNext()){
String key = keys.next();
String value = configuration.getString(key);
String tempKey = "database.*."+param;
if (key.matches(tempKey)){
return value;
}
}
throw new IllegalArgumentException("could find pattern for: database.<string>" + param);
}
private class InfraReflectiveMethodResolver extends ReflectiveMethodResolver {
@Override
public MethodExecutor resolve(EvaluationContext context, Object targetObject, String name, List<TypeDescriptor> argumentTypes) throws AccessException {
if ("getDbConfig".equals(name)){
return new DBMethodExecutor();
}
return super.resolve(context, targetObject, name, argumentTypes);
}
}
private class DBMethodExecutor implements MethodExecutor {
@Override
public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException {
try {
return new TypedValue(getDbConfig((String)arguments[0]), new TypeDescriptor(new MethodParameter(DBCustomExpressionRegistration.class.getDeclaredMethod("getDbConfig",new Class[] { String.class }), -1)));
}
catch (Exception ex) {
throw new AccessException("Problem invoking method: getDbConfig" , ex);
}
}
}
}
you use from the spring file like this:
<bean id="dbCustomExpressionRegistration" class="com.db.util.DBCustomExpressionRegistration"/>
in a bean that needs to use the getDbConfig function:
<property name="user" value="#{getDbConfig('username')}" />