WARNING!!! Configuration with initialization parameters is deprecated! If you still want to use it, please refer to 2.1 version of this page.
With Tiles it is possible to use expression languages not only in JSP pages, but also in XML definition files.
Currently supported languages are EL (as in javax.el), i.e. the language used in JSP code, MVEL and OGNL.
To enable the use of expression languages, you are encouraged to use the Pure Java configuration by overriding the createAttributeEvaluatorFactory method of BasicTilesContainerFactory. For example:
@Override protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory, LocaleResolver resolver) { ELAttributeEvaluator evaluator = new ELAttributeEvaluator(); // the rest of the initialization... BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory( new DirectAttributeEvaluator()); attributeEvaluatorFactory.registerAttributeEvaluator("EL", evaluator); return attributeEvaluatorFactory; }
The EL language is supported since Tiles 2.1. If you are using Servlet 2.5 or above, you can leverage your container EL support.
@Override protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory, LocaleResolver resolver) { //... Initialization of the factory. ELAttributeEvaluator evaluator = new ELAttributeEvaluator(); evaluator.setApplicationContext(applicationContext); JspExpressionFactoryFactory efFactory = new JspExpressionFactoryFactory(); efFactory.setApplicationContext(applicationContext); evaluator.setExpressionFactory(efFactory.getExpressionFactory()); ELResolver elResolver = new CompositeELResolver() { { add(new TilesContextELResolver()); add(new TilesContextBeanELResolver()); add(new ArrayELResolver(false)); add(new ListELResolver(false)); add(new MapELResolver(false)); add(new ResourceBundleELResolver()); add(new BeanELResolver(false)); } }; evaluator.setResolver(elResolver); // End of the attribute evaluator factory initialization. }
If you are using Servlets 2.4/JSP 2.0, you still can use Tiles EL support but:
@Override protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory, LocaleResolver resolver) { BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory( createELEvaluator(applicationContext)); return attributeEvaluatorFactory; } /** * Creates the EL evaluator. * * @param applicationContext The Tiles application context. * @return The EL evaluator. */ private ELAttributeEvaluator createELEvaluator( TilesApplicationContext applicationContext) { ELAttributeEvaluator evaluator = new ELAttributeEvaluator(); evaluator.setApplicationContext(applicationContext); // This is the important piece! evaluator.setExpressionFactory(new ExpressionFactoryImpl()); // End of the important piece! ELResolver elResolver = new CompositeELResolver() { { add(new TilesContextELResolver()); add(new TilesContextBeanELResolver()); add(new ArrayELResolver(false)); add(new ListELResolver(false)); add(new MapELResolver(false)); add(new ResourceBundleELResolver()); add(new BeanELResolver(false)); } }; evaluator.setResolver(elResolver); return evaluator; }
Let's use this example:
<definition name="test.composite.el.definition" templateExpression="${layout}" preparer="org.apache.tiles.test.preparer.RequestSettingViewPreparer"> <put-attribute name="title" value="This is a configured composite definition."/> <put-attribute name="header" value="/header.jsp"/> <put-attribute name="body" expression="${requestScope.body}"/> </definition>
Before rendering the definition:
To use MVEL support you need to register an instance of MVELAttributeEvaluator along with other supporting objects.
@Override protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory, LocaleResolver resolver) { TilesRequestContextHolder requestHolder = new TilesRequestContextHolder(); VariableResolverFactory variableResolverFactory = new TilesContextVariableResolverFactory( requestHolder); variableResolverFactory .setNextFactory(new TilesContextBeanVariableResolverFactory( requestHolder)); MVELAttributeEvaluator evaluator = new MVELAttributeEvaluator(requestHolder, variableResolverFactory); BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory( new DirectAttributeEvaluator()); attributeEvaluatorFactory.registerAttributeEvaluator("MVEL", evaluator); return attributeEvaluatorFactory; }
Let's use this example:
<definition name="test.composite.mvel.definition" templateExpression="MVEL:layout" preparer="org.apache.tiles.test.preparer.RequestSettingViewPreparer"> <put-attribute name="title" value="This is a configured composite definition."/> <put-attribute name="header" value="/header.jsp"/> <put-attribute name="body" expression="MVEL:requestScope.body"/> </definition>
Before rendering the definition:
To use OGNL support you need to register an instance of OGNLAttributeEvaluator along with other supporting objects.
@Override protected AttributeEvaluatorFactory createAttributeEvaluatorFactory( TilesApplicationContext applicationContext, TilesRequestContextFactory contextFactory, LocaleResolver resolver) { try { PropertyAccessor objectPropertyAccessor = OgnlRuntime.getPropertyAccessor(Object.class); PropertyAccessor mapPropertyAccessor = OgnlRuntime.getPropertyAccessor(Map.class); PropertyAccessor applicationContextPropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>( new TilesApplicationContextNestedObjectExtractor(), objectPropertyAccessor); PropertyAccessor requestScopePropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>( new RequestScopeNestedObjectExtractor(), mapPropertyAccessor); PropertyAccessor sessionScopePropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>( new SessionScopeNestedObjectExtractor(), mapPropertyAccessor); PropertyAccessor applicationScopePropertyAccessor = new NestedObjectDelegatePropertyAccessor<TilesRequestContext>( new ApplicationScopeNestedObjectExtractor(), mapPropertyAccessor); PropertyAccessorDelegateFactory<TilesRequestContext> factory = new TilesContextPropertyAccessorDelegateFactory( objectPropertyAccessor, applicationContextPropertyAccessor, requestScopePropertyAccessor, sessionScopePropertyAccessor, applicationScopePropertyAccessor); PropertyAccessor tilesRequestAccessor = new DelegatePropertyAccessor<TilesRequestContext>(factory); OgnlRuntime.setPropertyAccessor(TilesRequestContext.class, tilesRequestAccessor); } catch (OgnlException e) { throw new TilesTestRuntimeException("Cannot initialize OGNL evaluator", e); } BasicAttributeEvaluatorFactory attributeEvaluatorFactory = new BasicAttributeEvaluatorFactory( new DirectAttributeEvaluator()); attributeEvaluatorFactory.registerAttributeEvaluator("MVEL", new OGNLAttributeEvaluator()); return attributeEvaluatorFactory; }
Let's use this example:
<definition name="test.composite.mvel.definition" templateExpression="OGNL:layout" preparer="org.apache.tiles.test.preparer.RequestSettingViewPreparer"> <put-attribute name="title" value="This is a configured composite definition."/> <put-attribute name="header" value="/header.jsp"/> <put-attribute name="body" expression="OGNL:requestScope.body"/> </definition>
Before rendering the definition: