SpringELResolverSupport konfiguriert ELResolver mit Spring
Die Überschrift sagt eigentlich schon alles: der ELResolver wird selbst durch Spring erzeugt und konfiguriert.
Manchmal ist es nützlich oder sogar notwendig, dass ein ELResolver durch Spring konfiguriert wird. Wenn man den Resolver allerdings direkt in die faces-config.xml einträgt, dann geht das nicht.
Stattdessen wird ein Helper eingetragen, der auf die eigentlichen ELResolver delegiert…
Der Quellcode sieht so aus:
package org.springframework.web.jsf; import java.beans.FeatureDescriptor; import java.util.Iterator; import java.util.Map; import javax.el.ELContext; import javax.el.ELResolver; import javax.faces.context.FacesContext; import org.springframework.context.ApplicationContext; /** * adds all ELResolvers defined in spring's root context. * @author Stefan Rinke */ public class SpringELResolverSupport extends ELResolver { Map<ELResolver,ELResolver> resolvers = null; @SuppressWarnings("unchecked") private void initResolvers(ELContext ctx) { FacesContext context = (FacesContext) ctx.getContext(FacesContext.class); if( context != null ) { ApplicationContext appCtx = FacesContextUtils.getRequiredWebApplicationContext(context); resolvers = appCtx.getBeansOfType(ELResolver.class); } } @Override public Class<?> getCommonPropertyType(ELContext ctx, Object base) { if( resolvers == null ) initResolvers(ctx); return Object.class; } @Override public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext arg0, Object arg1) { return null; } @Override public Class<?> getType(ELContext ctx, Object base, Object prop) { if( resolvers == null ) initResolvers(ctx); for (ELResolver resolver : resolvers.keySet()) { Class<?> clz = resolver.getType(ctx, base, prop); if( ctx.isPropertyResolved() ) return clz; } return null; } @Override public Object getValue(ELContext ctx, Object base, Object prop) { if( resolvers == null ) initResolvers(ctx); for (ELResolver resolver : resolvers.keySet()) { Object value = resolver.getValue(ctx, base, prop); if( ctx.isPropertyResolved() ) return value; } return null; } @Override public boolean isReadOnly(ELContext ctx, Object base, Object prop) { if( resolvers == null ) initResolvers(ctx); for (ELResolver resolver : resolvers.keySet()) { boolean readOnly = resolver.isReadOnly(ctx, base, prop); if( ctx.isPropertyResolved() ) return readOnly; } return false; } @Override public void setValue(ELContext ctx, Object base, Object prop, Object value) { if( resolvers == null ) initResolvers(ctx); for (ELResolver resolver : resolvers.keySet()) { resolver.setValue(ctx, base, prop, value); if( ctx.isPropertyResolved() ) break; } } }
Was passiert ist einfach zu sagen: Die SpringELResolverSupport-Klasse lädt aus dem ApplicationContext von Spring alle ELResolver (mit getBeansOfType(ELResolver.class)) und delegiert alle Calls der Reihe nach an die gefundenen Resolver. So kann ein Resolver selbst mit Spring erzeugt und konfiguriert werden.
Offen bleibt die Frage nach der Reihenfolge. Da getBeansOfType die Reihenfolge offen läßt, werden die Resolver beliebig nacheinander aufgerufen. Das kann unter Umständen ein Problem erzeugen, wenn man auf eine ganz bestimmte Reihenfolge angewiesen ist.