Skip to main content

Enabling JSTL Support in JSP Templating

In my recent efforts on writing a Java Mediator for SDLTridion templating, I have now reached the point where I can write Template Building Blocks in JSP. Next is to enable JSTL support in the JSP TBB. That means to be able to use the Java Standard Tag Library (JSTL) and Expression Language (EL) in my JSP TBBs.

This functionality allows the following in a JSP TBB:
  • declare a taglib in my JSP with a given prefix. The interesting part is the uri attribute -- which comes from the TLD (Tag Library Definition) file. For JSTL, the .tld files are contained in the JAR itself, under path META-INF/. Each uri identifies a unique .tld file. This way, the J2EE engine knows which .tld to load, and therefore, which implementation classes, tags and method signatures are available within that TLD;
  • use EL to read variables from the package. Yes, it is cool! In the example below, expression ${UserName} reads the item with name UserName from the package and outputs its value;
Running the TBB above in Template Builder yields the following:

So How Did I Do It?

First, I had to add the two JARs containing the JSTL implementation (standard.jar and jstl.jar) to the jni4net classpath. This gives instant access to the JSTL tags -- due to the fact that their TLDs are within the JAR itself, I don't have to bother with placing the TLDs in the classpath.

Next, for reading items from the package using EL, I had to extend a bit the PageContext.findAttribute() method. In EL, the expression ${variable} will end up in the pageContext.findAttribute(variable). This method is responsible with testing the existence of variable in each scope (e.g. page, request, session, application). In my fake implementation, I don't have session or application scopes; instead, I added a custom scope PACKAGE_SCOPE that is in fact backed up by the _package object I am passing into the PageContext (check out my previous post about a detailed explanation of this).

Therefore, in my FakePageContext.java class, I implemented the findAttribute method like this:

public Object findAttribute(String name) {
    Object result = getAttribute(name);
    if (result == null) {
        result = getAttribute(name, REQUEST_SCOPE);
    }
    if (result == null) {
        result = getAttribute(name, PACKAGE_SCOPE);
    }
    return result;
}

public Object getAttribute(String name, int scope) {
    switch (scope) {
        case PAGE_SCOPE:
            return attributes.get(name);

        case REQUEST_SCOPE:
            return request.getAttribute(name);

        case PACKAGE_SCOPE:
            return _package == null ? null : _package.GetValue(name);

        default:
            throw new IllegalArgumentException("Invalid scope");
    }
}

Next Steps

  • EL expression on bean-like syntax (something similar to the Get eXtension) in order to allow some kind of EL like this ${component.fields.paragraph[0].bodytext};
  • ability to set/modify items in the package: e.g. <c:set var="MyTitle" value="some value" scope="package"/>;


Comments

Popular posts from this blog

Scaling Policies

This post is part of a bigger topic Autoscaling Publishers in AWS . In a previous post we talked about the Auto Scaling Groups , but we didn't go into details on the Scaling Policies. This is the purpose of this blog post. As defined earlier, the Scaling Policies define the rules according to which the group size is increased or decreased. These rules are based on instance metrics (e.g. CPU), CloudWatch custom metrics, or even CloudWatch alarms and their states and values. We defined a Scaling Policy with Steps, called 'increase_group_size', which is triggered first by the CloudWatch Alarm 'Publish_Alarm' defined earlier. Also depending on the size of the monitored CloudWatch custom metric 'Waiting for Publish', the Scaling Policy with Steps can add a difference number of instances to the group. The scaling policy sets the number of instances in group to 1 if there are between 1000 and 2000 items Waiting for Publish in the queue. It also sets the

Running sp_updatestats on AWS RDS database

Part of the maintenance tasks that I perform on a MSSQL Content Manager database is to run stored procedure sp_updatestats . exec sp_updatestats However, that is not supported on an AWS RDS instance. The error message below indicates that only the sa  account can perform this: Msg 15247 , Level 16 , State 1 , Procedure sp_updatestats, Line 15 [Batch Start Line 0 ] User does not have permission to perform this action. Instead there are several posts that suggest using UPDATE STATISTICS instead: https://dba.stackexchange.com/questions/145982/sp-updatestats-vs-update-statistics I stumbled upon the following post from 2008 (!!!), https://social.msdn.microsoft.com/Forums/sqlserver/en-US/186e3db0-fe37-4c31-b017-8e7c24d19697/spupdatestats-fails-to-run-with-permission-error-under-dbopriveleged-user , which describes a way to wrap the call to sp_updatestats and execute it under a different user: create procedure dbo.sp_updstats with execute as 'dbo' as

Toolkit - Dynamic Content Queries

This post if part of a series about the  File System Toolkit  - a custom content delivery API for SDL Tridion. This post presents the Dynamic Content Query capability. The requirements for the Toolkit API are that it should be able to provide CustomMeta queries, pagination, and sorting -- all on the file system, without the use third party tools (database, search engines, indexers, etc). Therefore I had to implement a simple database engine and indexer -- which is described in more detail in post Writing My Own Database Engine . The querying logic does not make use of cache. This means the query logic is executed every time. When models are requested, the models are however retrieved using the ModelFactory and those are cached. Query Class This is the main class for dynamic content queries. It is the entry point into the execution logic of a query. The class takes as parameter a Criterion (presented below) which triggers the execution of query in all sub-criteria of a Criterio