Installation Issues
Consult the README.html that ships with WebMacro, but the main things
you have to get right are:
- Install a Java Virtual Machine and a Servlet engine
- Put webmacro.jar somewhere on your classpath
- Put your servlet engine's .jar file on your classpath
- Make sure WebMacro.properties is on your classpath as well
- Edit WebMacro.properties setting your TemplatePath correctly
Introspection Rules
WebMacro follows the JavaBeans specification when performing class
analysis, but also extends that specification.
JavaBeans is essentially a set of conding conventions for how to
name accessor methods. If you follow those conventions then lots
of tools, including WebMacro, will be able to analyze your class
to learn what properties it has.
Here are examples of the properties that WebMacro can find:
When resolving $foo.Bar.Baz WebMacro can find:
- foo.Bar.Baz -- just field names
- foo.Bar.getBaz() -- a field and a JavaBeans accessor
- foo.getBar().getBaz() -- simple JavaBeans accessors
- foo.get("Bar").getBaz() -- hashtable lookup & accessor
- foo.getBar("Baz") -- Baz is a named property of Bar
In the previous example, using #foreach, WebMacro needed to
extract some kind of Iterator object from $Results. It can
do that in any of these ways:
- results[] -- results is an array already
- results is already a Java2 Iterator
- results is already a Java1 Enumeration
- results.iterator() returns a Java2 Iterator (any Java2 collection)
- results.elements() returns a Java1 Enumeration (Vector, Hashtable)
In cases where WebMacro needs to set a property, say $foo.Bar.Baz,
it can find methods like these:
- foo.Bar.Baz = value -- all fields
- foo.Bar.setBaz(value) -- get a field and simple set accessor
- foo.getBar().setBaz(value) -- get accessor and set accessor
- foo.getBar().put("Baz", value) -- getBar() returns a hashtable?
- foo.setBar("Baz", value) -- eg: response.setHeader(header,value)
NOTE: WebMacro can only access public fields and methods. The
Java security API prevents WebMacro (or any other package) from
gaining access to the private, protected, or package protected
data of your objects. If you want WebMacro to see your method, you
must make a public method.
Round bracket hack
Template writers may need to access data from a Java object
which does not follow the Java beans spec, and does not follow
any of the common extensions listed above that WebMacro can
introspect.
In these cases you can explicitly name a Java method in a
WebMacro template using the round bracket hack:
$foo.name()
$bar.loadValue(10,$arg1,true)
In this case $foo has a badly named accessor: name() should have
been called getName(). On the other hand, $bar has a loadValue
method which cannot easily be translated to a Java Bean method:
it takes three odd arguments.
I call this the round bracket hack because any use of this
syntax implies that the template author has some knowledge of
the exact Java class which implements $foo and $bar. If instead
you could have written $foo.Name the programmer could have provided
either a hashtable, or a method with public fields, or a method with
public accessors. Since the template writer actually refers to the
method by name the programmer winds up being restricted by the
template author.
A better solution would be to wrap the non-bean class in a JavaBean
interface. In the future, when WebMacro's introspector is still
more powerfult han iti s now, the round bracket hack may be
deprecated and eventually removed.
Concurrency Model: Context-per-thread
Multiple threads can execute a WebMacro template simultaneously: the
template is immutable. Once it is loaded and parsed it doesn't change.
Each thread should have its own Context. Think of a Context as
the place where each Thread keeps its local data. Since each
Context is accessible to only one Thread, it does not need to
be locked.
Thus, WebMacro avoid many locks: Templates are not locked because they
are immutable. Contexts are not locked because they are accessed by
only a single thread each.
You will need synchronization locks in a WebMacro based servlet
only when you explicitly share data between multiple threads.
Performance
WebMacro does a lot of work in order to generate your page, so you
might wonder whether it's efficient. Here are some answers:
- Templates are compiled for efficiency. WebMacro runs a two-phase
compile which optomizes out some static content. Unicode
character encoding/decoding is done at template compile time
and cached for re-use on each request.
- Class analysis is cached for efficiency. Analyzing Java
classes is very expensive so WebMacro doesn't do that on
every request. The first time a class is analyzed WebMacro
caches that data for later re-use. It turns out that invoking
a reflected method is quite fast, so if you can avoid the
expense of the analysis there isn't that much of a hit.
- Lock-free design. There are very few synchronization locks
in WebMacro, which helps concurrency a lot. Templates are
immutable and Contexts are accessed one-per-thread. There
are a few locks around various caches but they are constructed
to minimize the time a thread must spend inside the monitor,
the result being that a high degree of concurrency is possible.
It turns out that for typical applications the cost of your back-end
data source will swamp the cost of WebMacro. Generating a page is a
fairly efficient operation. You will need to concentrate on optomizing
the portions of your application which perform I/O and other more
expensive operations--WebMacro will account for only a fraction of
the cost of the page.
Extending the Framework
WebMacro loads almost all of its implementation from a configuration
file at runtime. You can easily override, extend, or change its
behavior by naming your own files in the configuration file
instead of the defaults WebMacro ships with.
Here are some of the things you can plug in via configuration file:
- New directives for the script language (pluggable directives)
- What default variables are available in every template (Tools)
- Where templates are loaded from (template path)
- How and when templates are loaded (template provider)
- How long and whether templates are cached
- How the WebMacro language itself is parsed (pluggable parser)
This is what makes WebMacro an extensible framework: almost every
aspect of its behavior can be easily overridden.
As the developer of an application framework you can take advantage
of these features to customize WebMacro to your particular needs.
|