jAlbum is built with Java and equipped with Groovy and BeanShell, a very powerful Java-like scripting language. Scripting gives you the ability to add any imaginable features to generated albums. Within special <% scriptlets %> you can construct just about any expression you like that is also valid Java. Scriptlets can be embedded into the template files of jAlbum skins (index.htt and slide.htt) or inside style sheet files of skins.

Jalbum versions 12.3 onwards can execute any kind of scripting language that runs on the Java Virtual Machine. Just drop the relevant .jar file inside jAlbum's "ext" folder to add support for it. Once installed, jAlbum's system console now contains an entry for that language and you can script in that language by just using the right file extension for your scripts.

Note: Any scripting (Groovy, BeanShell, JavaScript etc.) incurs a startup time for the evaluation and execution of the code within, but jAlbum tags, such as <ja:if> construct, don't as they are executed by compiled Java code, and that is faster than interpreted script code.

Important note: If a skin calls getVars() in init.bsh, that triggers the generation of all of the variables for the object, include things like the thumbnail dimensions. If the skin later does something that will alter those variables, as, for example, adding a filter to the engine, which might change those dimensions, the reported values will now be incorrect. The skin should, therefore, avoid using getVars() until all other actions that might change the object's variables have been done. If this can't be avoided, it is possible to cause the core to regenerate the variables for an object by executing obj.setVars(null).

Naturally, within BeanShell/Groovy <% scriptlets %> you enter comments as //This is a comment. You cannot use the jAlbum comment tag <%--This is a comment--%>.

Void and null variable values

Some variables only exist in certain circumstances. The nextPage variable is one such variable. It doesn't exist for the last page of a slide show. If you need to refer to such a variable in a script, you must ensure that it exists first, otherwise a scripting error will occur. Here are two ways to ensure that you don't refer to a nonexisting variable:

<ja:if exists="nextPage">
    <% // here it's safe to refer to nextPage %>
    if (nextPage != void) {
        // here it's safe to refer to nextPage
   Map exists = binding.variables;
   if (exists.variableName) {
       // here it's safe to refer to nextPage

As seen by the example, one uses the "void/exists" keywords within a script to test if a variable exists (is declared). This is one of the few examples where BeanShell scripting differs from Java. Java is a compiled language, BeanShell is interpreted when executed. In Java, a reference to a nonexistent variable will cause the compiler to halt. In BeanShell such references can happen in run-time, hence the need for the "void" keyword. "Void" should not be confused with "null". Null means that a variable exists, but has no value. Java programmers know the importance of doing null tests before refering/dereferencing an object that might be null. The same applies to variables that may be void.

First test for void, then null and finally do any other validation or comparison.


Here are some examples. Copy and paste them into a skin to have them executed during album creation.

Ordinary calculations: <%= 5*(3+2) %> --> 25

Access variables too: <%= thumbWidth*2 %>

Warn for large images and use variables in strings easily:
  if (fileSize > 1500000)
    out.print("Original file is large: " + fileSize + " bytes.");

Produce fast Google-like numbered links to other index pages:
  if(!exists.totalIndexes) return; //in init.groovy add 'Map exists = binding.variables;' as above
 // if (totalIndexes == void) return;  // BeanShell totalIndexes only exist if several index pages
  for (i=1; i<=totalIndexes; i++) {
    if (i == indexNum) out.print(" <b>" + i + "</b>");  // Emphasize current index page
    else {
      out.print("<a href=\"" + engine.getIndexPageName() + (i==1?"":i)
       + engine.getPageExtension() + "\">" + " " + i + "</a>");
       //Groovy print statement is println, the 'out.' is not required but including it will speed up interpretation

Scripting can be performed in four syntaxes:

Ordinary scriptlet: <% ... %>
Value of this scriptlet is outputted to the page: <%= ... %>
Old syntax for the above: <eval> ... </eval>
Function definition scriptlet (only evaluated once): <%! ... %>

Use scripting to construct advanced skins containing cool dynamic image borders etc. You have access to the full power and class hierarchy of java + there are also a number of practical "implicit objects" to assist you. To access Java classes use the ‘import’ keyword, for example to access se.datadosen.util classes:

import se.datadosen.util.*

This "opens a java package namespace" so that you can, for example, access the IO class that lies within se.datadosen.util. For example IO.someMethodHere(). For BeanShell you could use the longer se.datadosen.util.IO.someMethodHere() instead of importing thel package.


Not all scriptable actions may be valid, for example Audio clips can not be attached by a user to folders, audio, video and web locations. Yet it is possible by scripting to attach an audio clip to such an object. The result of scripting such 'unexpected' actions may or may not work; the API may also change in the future to prevent unexpected use of the API.