JSTP is basically a subset of JSP, and a build time translator of it.

The nice thing about JSP is everybody knows it, and all modern IDE support it. The bad thing is it's heavy weight, you can only use it in a servlet container, inside a HTTP request/response cycle. That severely limits its availability as a template solution in many other situations.

JSTP discards things in JSP that depend on Servlet. The remaining part is pure template solution. A JSTP page looks very much like a JSP page; it is translated into a simple java class at build time, and used at runtime as a simple class without any dependencies.

Note However JSTP was not set out to "fix" JSP. I wanted a simple, intuitive, lightweight, statically typed template language. There were some already, unfortunately they don't have IDE supports at the level that JSP is supported in modern IDE, like find usages, refactoring, code completion etc. In my work environment we perform constant refactoring, without IDE support it's pretty tedious. I guess it's not yet easy for IDEs to understand a new language, the solution left is to adopt a subset of JSP syntax so that IDEs can be fooled to treat JSTP as if it's JSP.

Hello World

Download jstp-1.0.0.jar, save it in your 'classpath', or into Ant lib directory. Create a JSTP file HelloWorld.jstp:

    Hello World!  
Translate it by command line
    java net.sf.jstp.JstpTranslator HelloWorld.jstp 
or by Ant task
    <taskdef name="jstp" classname="net.sf.jstp.JstpAntTask"/>
    <jstp><fileset dir="." includes="**/*.jstp"/></jstp> 
either way a file is created
    public class HelloWorld                                     
        public void render( out)            
            out.print("Hello World!\r\n");                      


Bottom line, just start writing JSTP pages like JSP and don't worry about it, you'll be fine mostly. Don't forget to configure your IDE to treat .jstp files as JSP files.

Following JSP-like tags are supported

    <%-- comment    --%>
    <%!  declaration  %>
    <%   scriptlet    %>
    <%=  expression   %>
    <%@  directive    %> 

They look and behave like JSP counterparts, except that only 'page' directive is supported, any other directive like <%@include% ...> is a translation error. 'page' directive has different attributes than those in JSP.

Everything else is treated as template text, including other special elements in JSP, like <jsp:useBean/>, taglibs, ${EL} etc. Implicit JSP variables like 'session', 'request' don't make sense in JSTP and are not supported.


The package of the generate java class can either be specified in page directive

    <%@ page package="" %>  
or automatically deduced by Ant task from directory structure. If neither is available, the class is in the 'default package'.


Imports are treated the same way in JSP, and your IDE should have taken care of it by adding imports automatically in page directive.

    <%@ page import="java.util.Date,

Parameter Passing

You can declare some instance variables for parameter passing. For example, in Bar.jstp, 'name' is one of its parameter

        public String name;                    
    Hello <%= name %> 
which is translated in as
    public class Bar                                        
        public String name;                                 
        public void render( out)         
            out.print("Hello ");                            

The caller naturally pass a 'name' parameter by

    Bar bar = new Bar();                          = "John";                               

You can surely declare and use getter/setters if you like.

Super Class

The 'extends' attribute of 'page' directive is supported just as in JSP.

In JSP the super class doesn't make much sense and nobody really uses the 'extends' attribute, however in JSTP you may find it very useful in your type hierarchy. For example, you have XXXTemplate as abstract interface

    public class XXXTemplate                                     
        public String name;                                      
        abstract public void render( out);    
and Bar.jstp is one of its implementation
    <%@ page extends="XXXTemplate" %>          
    Hello <%= name %> 
which results in
    public class Bar extends XXXTemplate                    
        public void render( out)         
            out.print("Hello ");                            
You can use it like
    XXXTemplate t = new Bar();                    = "John";                                  


If you need to include another JSTP in one JSTP, remember it's just a normal java class, and you invoke it in the same way:

    blah blah   
    <% new Bar().render(out); //including Bar.jstp %>  

Rendering Method

By default the rendering method signature is

    public void render( out) 
template texts are rendered by
and expressions are converted to String by

You can change those to anything you like in page directive:

    <%@ page                                                      
        render-method="public void genMessage(StringBuffer buf)"  
        text-wrapper ="buf.append"                                
        expr-wrapper ="Util.escape"                               
    Hello <%= name %>   
The result render method will look like
    public void genMessage(StringBuffer buf)      
        buf.append("Hello ");                     

Whitespace Gobbling

In JSP all whitespaces in template text are reserved. In JSTP some whitespaces are gobbled, and JSTP source pages look much nicer. You can turn the feature off by

    <%@page ws-gobbling="false" %> 
to follow JSP's convention if you must.

If ws-gobbling='true' which is default, you don't have to worry about how exactly it works, just format the JSTP source by common sense; if some whitespaces are gobbled against your intention, you can simply repeat the gobbled whitespaces at the same place. For example in

    <% out.flush(); %>       
The newline after the %> is gobbled, so the output will be
If you don't want that newline to be gobbled, just add a newline
    <% out.flush(); %>       

The exact gobbling policy is

  • if on the same line there are only blanks(space or tab) before a JSTP start tag, those blanks are gobbled.
  • if a JSTP end tag is immediately followed by a newline, or with only blanks between, the newline and the blanks are gobbled.

(the rules don't apply to <%=%> tag)

(same idea by Christoph on Velocity whitespace gobbling)

For example, (. represents space or tab, represents newline)

the two spaces before <%, the 3 spaces and one newline after %>, are not considered as template text; they are apparently only there to format the source, not the output.

'page' Directive Attributes

As a summary, following are attributes of page directive

packagethe package name of the generated java class. none

(however see autopackage option of Ant Task)
extendsthe super class name of the generated java class none""
render-methodthe signature of render method"public void render( out)" "public void genMessage(StringBuffer buf)"
text-wrapperhow to render template texts"out.print""buf.append"
expr-wrapperhow to convert expression to String "String.valueOf" "Util.escape"
ws-gobblingwhitespace gobbling "true"
importcomma seperated import list none "java.util.Date, java.util.List"

command line translation

To translate a jstp by command line

    java net.sf.jstp.JstpTranslator jstpFile [javaFile] 

The feature is minimal; Ant task is recommended in development.

Ant Task

You must first define the jstp task in Ant,

    <taskdef name="jstp" classname="net.sf.jstp.JstpAntTask"/> 

Specify jstp files to be translated in a <fileset> child:

        <fileset ... />

The task has some options, for example:

    <jstp destdir="tmp" encoding="UTF-8" autopackage="true" overwrite="false" verbose="false" failonerror="true">
        <fileset dir="demo" includes="**/*.jstp"/>
The only one really useful to you is probably 'destdir'.

JSTP Ant Task Options

destdir the destination directory for generated java files. if not specified, java files will be generated in the same directories of source jstp files.
encoding the encoding of jstp and java files. if not specified default platform encoding is assumed.
autopackage 'true' by default. automatically determine package by directory structure. for example, if inputs are
    <fileset dir="demo" includes="**/*.jstp"/> 
the package of demo/doo/foo/Bar.jstp will be "", unless Bar.jstp explicitly defines its package in <%@page package='..' %>
overwrite re-generate java file even if it's newer than the jstp file. by default the option is 'false'.
verbose 'false' by default
failonerror 'true' by default

temp counter
My Datanet
My Datanet