JSP Tool

The HTTP JSP Bundle of the ProSyst mBS supports deployment of JSP components. The translation phase of a JSP page requires too much resources and is unsuitable for runtime execution on an embedded device. That's why the JSP Tool was created. It translates JSP pages into Java files, ready for packaging and registration into the HTTP JSP Bundle. The JSP Tool supports JavaServer Pages™ Specification version 1.1.

Contents:


Basic Principles

The JSP Tool processes JSP files, generates Java source files and finally launches a compiler to issue bytecode, ready for registration into the JSP container of the HTTP JSP Bundle. The generated source files represent servlet classes, which on request to the JSP resource, generate an appropriate output. The generated classes extend com.prosyst.mbs.services.http.jsp.JspServletBase, which in its turn implements javax.servlet.jsp.HttpJspPage.


Deviations from the JSP Specification

According to JSP specification, using the <jsp:useBean> action in your JSPs can result in including the java.beans package in the generated implementation class, which will also require loading the java.awt package. This can lead to a great memory allocation at runtime or can prevent from having JSP support on some limited Java virtual machines, not providing the java.beans package.

The JSP Tool and the HTTP JSP Bundle offer a solution for this issue by using an internal API for JavaBeans management instead of java.beans. If you are using the java.beans package in the JSP page or servlet, apart from the programming code generated by the JSP Tool, you'll have to replace it with com.prosyst.util.beans which has the same functionality. To create a bean instance, use com.prosyst.util.beans.BeanUtils.instantiate() instead of java.beans.Beans.instantiate().


Starting the JSP Tool

The JSP Tool starting script is jsptool and is situated in the bin/tools/framework/jsp directory. As the JSP Tool has console user interface, you should start it in a command prompt window from the tool's home directory. The tool accepts a number of parameters - generation options and JSP file and directory locations. If you invoke the jsptool script without parameters, all available options will be listed.

For example: To compile the JSP files of the JSP Demo, you may use a command line like this:

jsptool ../../../../demo/framework/jsp/demo/jsp

All JSP files in the given directory and its subdirectories will be translated. Use the -tlcp option, to set the additional classpath, if the JSP file(s) import external (outside lib/frameworklib.jar) class(es) or the class(es) defined in the system classpath.

The output of the tool is by default placed in an output subdirectory of the tool's home directory - bin/tools/framework/jsp/output.

Tip: You can change the output directory with a JSP Tool option.


Generated Files

After the JSP Tool successfully completes its operation, for each JSP page it generates:

All generated files are named after the original JSP page if it is a valid Java identifier. Otherwise, the name is constructed by replacing the invalid characters with their hexadecimal equivalents.

If there are two or more JSP files with the same name in different directories and they are translated together, then the output name for these files will be <filename>, <filename>_1,<filename>_2,...,<filename>_n for the Java, class and resource files.

Note: The JSP Tool does not require confirmation for file overwriting. If files with names, coinciding with the generated ones, already exist, they will be overwritten without a prompt.


JSP Tool Options

The JSP Tool features a number of options. They allow the user to manage tool's output in different ways - to change the output directory and package of generated Java classes, to pass options to the Java compiler, etc.

jsptool [<options>] <jsp files>


General Options

Define an Output Directory

By default, the output directory of the JSP Tool is called output and is a subdirectory of the tool's home directory. The -out option allows you to change this directory.

-out <dir>

The given directory path can be absolute or relative to the tool's home directory (bin/tools/framework/jsp). If you provide a path to a not existing directory, it will be created and the output files will be placed there.

For example:

-out ../../../../demo/framework/jsp

Define a Package for the Servlet Classes

By default JSP servlet classes are not placed within a Java package. To specify a package for the generated servlet classes, use the -package option.

-package <package>

For example:

-package demo.jsp

Print Debug Information

Use the -debug option to print debug information in the standard output. You cay combine different debug levels with one or more of the p, t and c parameters:

-debug [p][t][c]

where:

For example: Debug the specified JSP with the Parser and Translator combined debug level.

-debug pt ../../demo/jsp

Set Classpath to Tag Handlers and JavaBeans

If your JSP pages use a custom tag library, a bean or an external class library, the JSP Tool requires that you specify a classpath to the location of the tag handler(s) managing them, to the bean or the used class library, respectively. Use the following command line:

-tlcp <classpath>

Your classpath can include directories, as well as ZIP and JAR archives. Classpath entries must be separated by semicolons.


Compilation Options

Specify a Java Compiler

The JSP Tool allows you to determine a Java compiler to use for compiling the generated servlet. The default compiler is "javac". To specify the compiler use the following option:

-compiler <compiler>

The option value must be a path to the Java compiler executable.

For example:

-compiler D:/Java/jdk1.2.2/bin/javac.exe

Specify Java Compiler Options

As a part of the JSP translation process, the call to the Java compiler is included in the JSP Tool work. As it can't be separated from the tool's runtime. you can pass parameters to the Java compiler with the -opt JSP Tool option.

-opt <options>

where <options> is any option the Java compiler recognizes (can be the default one or the one, specified with the -compiler JSP Tool option). If you are passing multiple parameters, they must be enclosed within quotes.

For example:

-opt "-g:none -target 1.1"

Translate JSPs to Java Files without Compilation

The JSP Tool allows you to translate JSP files to Java files, skipping their compilation. Use the following option:

-nocompiler

For example:

-nocompiler ../../../demo/jsp


Bundle Options

Generate a Bundle Activator

To register one or more JSP servlets in the HTTP JSP Bundle, a developer must create a bundle, which registers the servlet and its resources into the OSGi HTTP Service. The user can request the JSP Tool to generate automatically a bundle activator class and to specify what aliases it should register on bundle activation. Use the following option:

-register <alias>

The alias value must begin and not end with a slash ("/"). When you generate a bundle activator automatically, all servlets, generated from JSP pages, are registered separately, as subaliases of the specified alias.

The bundle activator is created with default name BundleActivatorImpl.

For example: If we have two JSP pages - demo.jsp and example.jsp, whose Java implementations should be in a demo.jsp package, and pass the following option to the JSP Tool:

-register /mydemo

we'll have as a result a BundleActivatorImpl.java file and a corresponding class file, which registers two servlets - /mydemo/Demo and /mydemo/Example with instances of the servlet classes the tool has generated from the JSP pages. The HTTP context object is set to this, as the created bundle activator also implements the org.osgi.service.http.HttpContext interface.

Generate a Bundle Manifest File

As JSP resources and generated class files have to be packed in a bundle JAR, which must contain a manifest file to be installed and used on an OSGi framework. The JSP Tool provides an option to automatically generate a manifest file with a specified name reflecting the requirements for registering JSP pages and resources.

-mf <manifest file name>

The generated manifest file contains a number of manifest headers, such as Bundle-Category, Bundle-Vendor, Bundle-Activator, Manifest-Version, etc.

The bundle activator is by default declared as <package_name>.BundleActivatorImpl, where <package_name> is the package specified with the -package JSP Tool option (if any).

In addition, the manifest is created to import the packages, required when registering a JSP-based servlet in the HTTP JSP Bundle.

Package Exporter Description
com.prosyst.mbs.services.http.jsp Java Server Pages
API Bundle
Contains the JSP servlet extension, used by the HTTP JSP Bundle.
javax.servlet OSGi Library Bundle Host the components of the Java Servlet API 2.2.
javax.servlet.http
javax.servlet.jsp Java Server Pages
API Bundle
Contains the classes and interfaces of the JavaServer Pages technology.
org.osgi.framework System Bundle Contains the OSGi Framework API, necessary for developing and using bundles.
org.osgi.service.http OSGi Library Bundle Contains the OSGi HTTP Service, implemented by the HTTP JSP Bundle, for servlet and resource registration.
If custom tags are used
javax.servlet.jsp.tagext Java Server Pages
API Bundle
Contains the API for tag extension, defined by the JSP Specification.
If JavaBeans are used
com.prosyst.util.beans Java Server Pages
API Bundle
Contains the ProSyst API for JavaBeans management.

If generated Java files import packages other than java.* prefixed ones, they are also added to the Import-Package header.

An example generated manifest:


  Manifest-Version: 1.0
  Bundle-Vendor: ProSyst
  Bundle-Name: JSP Deployment Bundle
  Import-Package: org.osgi.framework, org.osgi.service.http, 
  com.prosyst.mbs.services.http.jsp; specification-version=1.1, javax.servlet.http, 
  javax.servlet.jsp, com.prosyst.mbs.services.http.jsp, javax.servlet
  Bundle-Category: jsp
  Bundle-Activator: BundleActivatorImpl
  Bundle-Description: This bundle registers JSP pages and resources with root alias(es) demo
Listing 1: Example manifest.


Options for Optimized Resource Allocation

The JSP specification defines a classic way to compile JSPs, where static content is written as String objects into the output. This approach allocates much temporary memory and CPU time in order to transfer chars into bytes by using the JSP author-selected character encoding.

Best Performance

With -bestperf option you can translate a JSP file into a Java class, optimized for quick output of static content.

-bestperf <jsp files>

As a result, the JSP Tool converts JSP's static content into bytes by using the character encoding of the page directive and writes them in a resource file with the .res extension.

When the first client request comes, the bytes from the resource file are loaded into memory, where they remain until the page is destroyed. On a next request, the JSP implementation reads these bytes directly from memory without the need of transforming them and creating unnecessary String objects.

This translation is called “best performance”, as it skips the char-to-byte conversion at runtime, so it is the fastest method to send data to the client.

JSP implementation classes generated with this method extend com.prosyst.mbs.services.http.jsp.JspBestPerformanceBase.

Developers should apply this option on JSP pages that are often requested or which have highly mixed dynamic and static content.

For example:

-bestperf ../../demo/jsp ../../demo2/jsp

Least Memory

With the -leastmem option, you can generate a JSP implementation, optimized for small memory allocation.

-leastmem <jsp files>

As a result, the JSP Tool converts JSP's static content in bytes and places it in a .res file. The JSP implementation class reads the resource file at each request, without keeping it in the memory. This slows down the response but saves memory.

JSP implementation classes generated with this method extend com.prosyst.mbs.services.http.jsp.JspLeastMemoryBase.

The "least memory" method should be used on JSP pages that have large static content and are rarely requested.

For example:

-leastmem ../../demo/jsp

Classic String Mode

The -classicstrings option generates JSP implementation classes in the classic out.print(String) style with static content as inside the Java files. By default the Java files are generated with this option.

-classicstrings <jsp files>

For example:

-classicstrings ../../demo/jsp

Tag Pooling

Use the -tagpool option to enable tag handler pooling in the HTTP JSP Bundle. This allows you to pool and reuse custom JSP tag handler objects, which significantly boosts the performance of JSP pages using custom tag libraries.

-tagpool <JSP files>

For example:

-tagpool ../../demo/jsp


Compression Options

Compress Static Content

Use the -compress option to generate JSP implementation classes with compressed static content.

-compress [k][w][c][l<num>][a]

where:

Note: The LZ compression will be ignored in case you are not using -bestperf option.

You can combine different compression levels.

For example:

-compress wl30 ../../demo/jsp

Define Compressed Content Types

Use the -compressTypes option to specify content (MIME) types, to which compression will be applied.

-compressTypes <content types>

The default content types are "text/html", "text/htm" and "text/xml". The content types, provided with the -compressTypes option override the default ones. If the content types are more than one, separate them with space(s) and enclose the entire value in quotes.

For example:

-compressTypes "text/html text/plain"


Options for Java Code Optimization

When compiling JSP pages with intensive custom tag usage, generated output can become very large. Even after using the –bestperf option to remove the template text from the implementation class, the class can be still very large. Actually, the problem is not in the class file size but in concentrating all content in a single method – _jspService(). JVMs running on embedded devices can have great difficulties in loading "fat" method bodies. To solve this issue, the JSP Tool offers two code optimization options: -codeoptbasic and –codeoptfull. What’s common to both of them is that the repeated code, handling a custom tag, is united in a single method.

For example, if a custom tag with attributes “name” and “value” is encountered 3 times in a JSP, the code initializing the tag, setting its attributes and invoking tag handler methods will appear 3 times in the resulting implementation class. Instead, by using the tool's code optimization options the implementation class will have a single method responsible for the tag operations, which is called 3 times.

Basic Optimization

Use the -codeoptbasic option to optimize generated implementation class with static methods for custom tags without bodies.

For example, you can apply the option to a <lib:say message="hello"/> tag but not to a <lib:say>hello</lib:say> one.

Let's suppose that a JSP page contains the following two tags:

<lib:say message="hello" to="John"/>
<lib:say message="bye" to="Mary"/>
Listing 2.1: Using a bodyless custom tag in a JSP page.

As a result, the JSP Tool will generate one method for both tags similar to the following:

         . . .  
public static int _jspLibSay0(java.lang.String message, java.lang.String to,
Object parent, PageContext pageContext)
throws JspException { com.prosyst.tags.LibSay _jspSay =
(com.prosyst.tags.LibSay) _jspGetTag(com.prosyst.tags.LibSay.class,
pageContext,
parent); _jspSay.setMessage(message); _jspSay.setTo(to); try { _jspSay.doStartTag(); return _jspSay.doEndTag(); } finally { if (_jspSay != null) { _jspSay.release(); _jspReleaseTag(_jspSay ); } } }
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException { . . . if ( _jspLibSay0("hello", "John", parent, pageContext)
== javax.servlet.jsp.tagext.Tag.SKIP_PAGE) return; if ( _jspLibSay0("bye", "Mary", parent, pageContext)
== javax.servlet.jsp.tagext.Tag.SKIP_PAGE) return; . . . }
Listing 2.2: Java code, generated for a custom tag without body.

Note: This optimization should be used, when it is not possible to apply Full Code Optimization.

Full Optimization

Use the -codeoptfull option to significantly compact generated code by having specific handling methods for custom tags with and without body.

-codeoptfull<methodSize>[kb]

where <methodSize> stands for the size in KB of method bodies in the generated Java source file. The default is 4KB.

For example:

-codeoptfull8
or
-codeoptfull8kb

An implementation class, generated with the -codeoptfull option, contains two types of custom tag methods - for the tag itself, and for the tag's body. According to tag content size in the JSP page and the specified method size, there can be more than one method of either type, dedicated to a single custom tag. Bodyless tags are represented by static methods in the implementation class (as shown for Basic Optimization).

For example if we have the following tag in a JSP page:

<lib:say to="John">
  hello
</lib:say>
Listing 3.1: Using a custom tag with a body in a JSP page.

then the JSP Tool will generate Java code similar to this one:

         . . .
  public int _jspLibSay3(String to, Object parent, 
                         PageContext pageContext, JspWriter out, 
                         JspMagicWriter _jspWriter, int bodyIndex) 
             throws JspException, IOException {
    com.prosyst.tags.LibSay _jspSay = 
      (com.prosyst.tags.LibSay) _jspGetTag(com.prosyst.tags.LibSay.class, 
                                           pageContext, 
                                           parent);
    _jspSay.setTo(to);
    try {
      int eval = _jspSay.doStartTag();
      if (eval != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {
        if (eval == javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {
          while (true) {
            if (!_jspBody(bodyIndex, _jspSay, pageContext, out, _jspWriter)) 
              return javax.servlet.jsp.tagext.Tag.SKIP_PAGE;
            int evalDoAfterBody = _jspSay.doAfterBody();
            if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_TAG) break;
          }
        }
      }
      return _jspSay.doEndTag();
    } finally {
      if (_jspSay != null) {
        _jspSay.release();
        _jspReleaseTag(_jspSay );
      }
    }
  } 

public boolean _jspBody(int index, Object parent, PageContext pageContext, JspWriter out, JspMagicWriter _jspWriter) throws JspException, IOException { switch (index) { case 0 : { _jspDecode(6, 8, _jspWriter); . . . } default: { throw new IllegalArgumentException("Quite strange: no such body index!" + index); } }//switch return true; }
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {   . . .
if ( _jspLibSay3("John", parent, pageContext, out, _jspWriter, 0) == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
return; . . . }
Listing 3.2: Java code, generated for a custom tag with body.

Note: A problem may appear when the JSP uses scriptlets, declarations, or the <jsp:useBean> action. In these cases, the JSP tool may not succeed to compile the JSP implementation class. If the JSP tool reports an error, switch to basic code optimization, which compacts the code less but provides more reliable compilation. The problems in compilation originate when separating content, designed to be in a single method - _jspService, into multiple methods.


References


Framework Tools