Skip to main content

Syntax Validation for Java Fragment TBB

This little post explains how to perform "Content Validation" of a Java Fragment TBB as part of the Tridion Java Mediator I am currently working on. If you want more information about the "Yet Another Java Mediator" for Tridion templating, have a look at my previous post.

Content validation for TBBs, or in Tridion terms, a Template Content Handler, is a piece of code that runs when a TBB is read (open) or written (saved) and it serves two purposes:
  • perform any validation of the TBB content;
  • replace any references to other Tridion items (either by TCM URI or WebDAV URL, or some kind of reference) with some kind of substitution;
I have not implemented any replacement logic yet (it is to come in the near future when I'll write the logic to upload JARs and execute classes from it). So far my goal was to perform a compile of the TBB Java source fragment at the moment of saving the TBB, and in case of errors, show the errors in the GUI and prevent saving. This is the same behaviour the C# Fragment TBBs have in OOTB Tridion.

In .NET things are simple -- all I had to do was create a class that extends abstract Tridion.ContentManager.Templating.AbstractTemplateContentHandler and implement method PerformValidateContent. From this method I called the Java Fragment compile logic (written in Java, over JNI proxy, as described in my previous post).

C#:
public class JavaFragmentContentHandler : AbstractTemplateContentHandler {

public override void PerformValidateContent() {
    JavaTemplateHandler handler = new JavaTemplateHandler();
    handler.compile(base.Content);
}

Java:
public class JavaTemplateHandler {

public void compile(String javaFragmentSource) {
    String javaSource = String.format(JAVA_FRAGMENT_SKELETON_SOURCE, javaFragmentSource);
    SourceStringCompiler compiler = new SourceStringCompiler(CLASSES_DIR);
    compiler.compile(JAVA_FRAGMENT_SKELETON_CLASS_NAME, javaSource);
}

On the Java side, I am simply intercepting the messages coming from the Compiler API and, in case of an error, throw an exception with the compiler message formatted a bit. I do some formatting on the line numbers only, so that the line number reported is actually relative to the Java Fragment that is shown in Tridion and not the line number relative to the entire compilation unit. The thrown exception is propagated all the way back into .NET and eventually ends up being displayed in the CME.

I hit a few roadblocks, of course:
  • Content handlers need to be registered in the GAC. This is unfortunately inconsistent with the mechanism of registering mediators, where you can specify the actual assembly path. As a Java head, I really dislike the GAC -- it is the root of all evil. This meant I had to sign all my referenced DLLs (including Tom.Java, jni4net). This meant a lot of trouble with the JAR loading mechanism from jni4net etc). In the end I opted for reflection, just to keep the 'referenced' DLLs out of GAC and unsigned;
  • 32bit vs 64bit trouble -- some parts of Tridion CM run as 32bit applications and some as 64bit. This poses a huge problem to jni4net Bridge, which has to use the appropriate 32 vs 64 bit Java Development Kit based on the calling .NET CLR it runs it;
Finally, everything worked and the validation looks something like that:
Notice the variable "a" declared without a type and the Date class not being resolvable.

A detail error message looks like this, if expanded:
So far I have the entire Java Fragment TBB done, including validation/compilation. Next, I I'll focus on the JSP/JSTL TBBs that I intend to use as replacement of Dreamweaver TBBs.


Comments

Popular posts from this blog

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...

REL Standard Tag Library

The RSTL is a library of REL tags providing standard functionality such as iterating collections, conditionals, imports, assignments, XML XSLT transformations, formatting dates, etc. RSTL distributable is available on my Google Code page under  REL Standard Tag Library . Always use the latest JAR . This post describes each RSTL tag in the library explaining its functionality, attributes and providing examples. For understanding the way expressions are evaluated, please read my post about the  Expression Language used by REL Standard Tag Library . <c:choose> / <c:when> / <c:otherwise> Syntax:     <c:choose>         <c:when test="expr1">             Do something         </c:when>         <c:when test="expr2">             Do something else         </c:when...

Publish Binaries to Mapped Structure Groups

Today's TBB of the Week comes from the high demand in the field to publish binary assets to different mapped Structure Groups. By default SDL Tridion offers two ways of publishing binaries: All binaries publish to a folder defined in your Publication properties; All binaries rendered by a given template publish to a folder corresponding to a given Structure Group; In my view, both cases are terrible, over-simplified and not representing a real use-case. Nobody in the field wants all binaries in one folder and nobody separates binary locations by template. Instead, everybody wants a mapping mechanism that takes a binary and publishes it to a given folder, defined by a Structure Group, and this mapping is done using some kind of metadata. More often than not, the metadata is the TCM Folder location of the Multimedia Component. I have seen this implemented numerous times. So the solution to publish binaries to a given location implies finding a mapping from a TCM Folder to a...