Home >
Tech Papers >
WebMacro Technical Investigation
Technology Investigation Outline - WebMacro
Introduction
The purpose of this document is to explore the capabilities of WebMacro
in the context of developing web-based applications.
The document provides a broad overview of standard WebMacro technology, including:
- Broad overview of WebMacro operation
- Development steps for a form
- Comparison of WebMacro (and template engines in general) to JavaServer Page
technology
- Consideration of object frameworks based on WebMacro
- Other issues, including software requirements
A list of related online resources is provided at the end of the document.
What is WebMacro?
WebMacro is a free Java servlet development framework, including a template
language and extensible component model. It uses beans and introspection to
make any Java object in your servlet accessible in your template.
WebMacro FAQ
WebMacro, like Sun's JavaServer page (JSP) technology, is an extension of the
Java Servlet API. However, unlike JSPs which must be translated into servlet
classes before being executed, WebMacro pages are essentially templates which
are read in, parsed and displayed via the WebMacro template engine (*rewrite*).
The goal of WebMacro is to separate page design from the application code.
WebMacro is being developed by Semiotek Inc and is available for use under
the GNU Public Licence (GPL). A less restrictive licence can be negotiated with
the developers. More details regarding licensing are contained in the WebMacro
Licensing document.
WebMacro has been designed to fit the biases of the developers (from WebMacro
Readme document):
- it is wrong to use markup for a scripting language
- it is wrong to embed programs on a web page
- it is wrong for web scripts to look like hard programming
- that programming and graphics design are separate tasks
In keeping with it's design philosophy, WebMacro provides two separate interfaces:
- A template language for web page designers to use, into which they can substitute
values from a web program
- A library and framework for web based programming, for use by technical
developers, which is independent of any layout or other graphical concerns
How WebMacro Works
WebMacro consists of an HTML template engine and a framework of back end servlet
classes. WebMacro applications operate within the standard HTTP request/response
paradigm.
In broad terms, a WebMacro application works as follows:
- A WebMacro-based servlet receives a request from a user.
- The servlet processes the request, which may involve interaction with JavaBeans
and other classes on the server.
- The WebMacro template engine loads a template page, executing any WebMacro
Script contained within it.
Note that the first time a template is loaded, WebMacro engine parses it into
an intermediate form for faster execution.
- The resultant HTML document is sent to the user's web browser.
WebMacro technology enforces the separation of page design and application
logic. Therefore, any application based on WebMacro will require at least two
source files: a WebMacro servlet and a WebMacro template. This contrasts with
"pure" servlets which allow the development of servlets that contain
the application logic and generate all the HTML markup. The WebMacro approach
also contrasts with JSPs, which allow developers to embed Java code into pages
alongside HTML markup.
The WebMacro philosophy promotes the Model-View-Controller (MVC) framework.
This framework separates the model (or business logic) from the view logic in
an application, with a controller managing the interaction between the model
and the view. In the context of a Java-based web application, JavaBeans provide
a natural mechanism for implementing the business logic. WebMacro templates
can be used as the view component. And WebMacro servlets can implement the controller
component. This is discussed in the WebMacro
Framework Design Overview.
The diagram below shows how WebMacro technology can be used within an MVC framework.
|
| MVC Framework using WebMacro |
The WebMacro QuickStart
document provides an overview of how to write WebMacro applications. The following
section is based on information contained in that document. More comprehensive
information is contained in the WebMacro
API documentation and in the WebMacro
Script article.
As mentioned earlier, a WebMacro application consists of at least two components:
a WebMacro servlet and a WebMacro template.
WebMacro Servlets
The servlet component involves either implementing the org.webmacro.servlet.Handler
interface, or else subclassing from org.webmacro.servlet.WMServlet.
Since the latter is the preferred approach, this document will focus on that
approach.
Template handle(WebContext) is the primary method that needs to
be implemented by a subclass of WMServlet. Each connection to the server results
in a call to the servlet's handle() method. When WebMacro calls the WMServlet.handle()
method it will pass a WebContext
object. This is basically a big Map which can be used to store other objects.
The WebContext object also has a variety of helper objects within it which can
be used to query things about the state of the application.
Any variable that placed into the WebContext is available as a local variable
to the template. The WebContext is a JDK 1.2 style Map. Objects are placed into
the WebContext by invoking the put() method. For example:
context.put("customer", customerObject);
The handle() method returns a Template
object. It is the responsibility of the handle() method to select which template
will be used to generate the HTML that is returned to the browser.
Templates use "Property Introspection" to access the data stored in the WebContext.
WebMacro uses the introspection/reflection APIs to take a pretty deep look into
the objects in the WebContext. The template language has access to the properties
of the objects contained in the map.
For simple values, it will attempt this in two ways:
- it will use the bean approach and look for public fields or appropriately
named get/set methods
- if it hasn't found a specific method, it will try and view the object as
a collection and use put/get methods
If a list of objects is to be stored in the template there are several options.
The property introspection method is capable of iterating through any of the
following types:
- an array
- anything that has an elements() method that returns an Enumeration
- anything that has an iterator() method that returns an Iterator
WebMacro Templates
Templates contain the output of the application. Each template represents a
one page view in the system.
Any objects placed by the servlet in the WebContext can be accessed by the
template. For example, if the servlet places an object called "customer" in
the WebContext, the object's fields can be accessed as follows:
Customer $customer.name owes $customer.owing
It is possible to loop through list values that may be part of an object:
<ul>
#foreach $customer in $customerList
{
<li> $customer.name owes $customer.owing
}
</ul>
Simple conditionals are also supported. In the current version developers can
only test whether something is defined or not:
#if ($variable)
{
Yes we have variable: $variable
}
#else
{
Sorry, variable is not defined here
}
Other things that can be done using WebMacro Script in templates are:
- #include "someUnparsedFile.txt"
- #set $variable = value
- #parse "includeSomeWebMacroTemplate.wm"
- #include "$variableFile"
- #use 'text' until "--The End--"
Text here is not parsed by WebMacro, up until the line matching the
supplied boundary. Use this to surround sensitive things like JavaScript,
if it can conflict with WebMacro.
--The End--
The WebMacro context includes a collection of convenient variables that can
be accessed. For example
- $Broker allows reading things from the ResourceBroker, an extensible resource
manager which a programmer can plug components into on the back end
- $CGI provides access to CGI-style variables
- $Form provides access to FORM data
- $Config provides access to properties in WebMacro.properties
- $Cookie allows you to get and set cookies from the template
- $Session allows you to get and set things in the JSDK session
- $Request is the HTTP request (HttpServletRequest)
- $Response is the HTTP response (HttpServletResponse)
An example application using WebMacro will be presented and described in the
next section.
Developing a Form Using WebMacro
To demonstrate how to develop a form using WebMacro technology, the following
example HTML template and Java program will be discussed. It's a rather simple
application that prompts the user to enter a string, which is then encoded into
a format that is URL-friendly.
The source code for the application logic of this example is provided in Listing
1: URLEncodingWMPage.java, while the view is given in Listing 2: URLEncodingWMPage.wm.
| Listing 1: URLEncodingWMPage.java
|
1 /**
2 * Sample Java WebMacro Servlet
3 * Name: URLEncodingWMPage.java
4 * Purpose: Present user with a form for entering a single string.
5 * When form is submitted, contents of string are encoded as URL,
6 * which is then returned to the user.
7 * @author: brunoa
8 * Date created: 18 April 2000 14:45
9 * Last modified: 19 April 2000 11:00
10 */
11 import java.net.*;
12 import java.util.*;
13 import org.webmacro.util.*;
14 import org.webmacro.servlet.*;
15 import org.webmacro.engine.*;
16 import org.webmacro.resource.*;
17 public class URLEncodingWMPage extends WMServlet
18 {
19 private String inputString;
20 private String encodedString;
21 private String dateString;
22 private static Log log = new Log("urlencoder", "URLEncodingWMPage");
23 public Template handle(WebContext context)
24 throws HandlerException
25 {
26 Object output = new Object();
27 String templateName = "URLEncodingWMPage.wm";
28 Date date = new Date();
29 dateString = date.toString();
30 context.put("DateString", dateString);
31 // get the user's input
32 try
33 {
34 inputString = (String) context.getForm("inputString");
35 }
36 catch (Exception e)
37 {
38 log.exception(e);
39 }
40 if (inputString == null)
41 {
42 inputString = "";
43 }
44 context.put("InputString", inputString);
45 // encode input string and store into context
46 encodedString = URLEncoder.encode(inputString);
47 context.put("EncodedString", encodedString);
48 // return the template
49 try
50 {
51 return (Template) context.getBroker().getValue(TemplateProvider.TYPE,
52 templateName);
53 }
54 catch (Exception e)
55 {
56 throw new HandlerException("Could not locate template: "
57 + templateName);
58 }
59 }
60 } // URLEncodingWMPage
|
Listing 1 is the WebMacro servlet. A line-by-line description will now be provided.
Lines 1 to 10 contain some comments regarding the servlet.
Lines 11 to 16 contain statements to import the required packages:
- java.net package is required for providing the URL-encoding functionality
- java.util package is required for getting the date
- org.webmacro.util package provides general utilities, such as the Log
class
- org.webmacro.servlet package provides the basic WebMacro servlet classes
- org.webmacro.engine package provides the template rendering code
- org.webmacro.resource package provides modules which are used to locate
resources at runtime in the WebMacro system, such as the Template
class
Line 17 declares that the URLEncodingWMPage class is a subclass of org.webmacro.servlet.WMServlet.
Lines 19 to 21 declare some private variables used within the servlet.
Line 22 declares and initialises a log for the servlet.
Lines 23 to 59 define the handle() method. It accepts a WebContext
object, returns a Template
object and throws a HandlerException
if something goes astray.
Line 27 creates a String object, templateName, and initialises it to the
name of the WebMacro template file.
Lines 28 to 30 get the current date as a string and place it into the context.
This value will then be available for use within the template.
Lines 31 to 39 attempt to extract the user's input to the form:
Line 34 gets the value of the form field "inputString" and stores
it in a private variable.
Line 38 logs any exception raised.
Lines 40 to 44 place the input string (or if there is none, an empty string)
into the context.
Line 46 performs the URL-encoding upon the input string, using the java.net.URLEncoder
class.
Line 47 places the encoded string into the context.
Lines 49 to 58 attempt to instantiate the Template
object and return it:
Line 51 creates a Template object using the filename declared earlier.
Line 56 raises an exception if the template cannot be located.
| Listing 2: URLEncodingWMPage.wm
|
1 <!--
2 -- Sample WebMacro Page
3 -- Name: URLEncodingWMPage.wm
4 -- Purpose: Present user with a form for entering a single string.
5 -- When form is submitted, contents of string are encoded as URL,
6 -- which is then returned to the user.
7 -- @author: brunoa
8 -- Date created: 18 April 2000 14:30
9 -- Last modified: 19 April 2000 11:00
10 -->
11 <HTML>
12 <HEAD><TITLE>URLEncodingWMPage Output</TITLE></HEAD>
13 #set $Response.ContentType = "text/html"
14 <BODY BGCOLOR="gainsboro">
15 ## only want to display results if user entered some input
16 #if ($Form.inputString)
17 {
18 <H2>URLEncodingWMPage Output</H2>
19 <P>Input string: $Form.inputString</P>
20 <P>URL Encoded: $EncodedString</P>
21 <P> </P>
22 <HR>
23 }
24 <!-- here's the actual form -->
25 <H2>URLEncodingWMPage Form</H2>
26 <FORM NAME="URLEncoder" ACTION="URLEncodingWMPage" METHOD="POST">
27 <P>String to encode:
28 <INPUT TYPE="TEXT" NAME="inputString" VALUE="$InputString" SIZE="60">
29 </P>
30 <INPUT TYPE="RESET">
31 <INPUT TYPE="SUBMIT">
32 </FORM>
33 <P> </P>
34 <P><SMALL><I>Script: URLEncodingWMPage 0.1 by Bruno Andrighetto<BR>
35 Date: $DateString</I></SMALL></P>
36 </BODY>
37 </HTML>
|
Listing 2 is the WebMacro template. A line-by-line description will now be
provided.
Lines 1 to 10 contain some comments regarding the template.
Lines 11 to 12 contain HTML markup to begin the page and set the title.
Line 13 contains a WebMacro Script directive which sets the content type of
the page to "text/html".
Line 14 starts the BODY section, setting the background colour.
Line 15 contains a WebMacro Script comment, which will not be visible in the
generated web page.
Lines 16 to 23 contain a WebMacro Script conditional test and the HTML markup
to generate if the condition is met:
Line 16 contains the #if directive to implement a test condition - is inputString
defined in the form? (or: has the form been submitted?).
Lines 18 to 22 contain the HTML markup which is displayed if there is user
input:
Line 19 contains the WebMacro Script term to insert the user's input from
the context.
Line 20 contains the WebMacro Script term to insert the encoded value of
the input string (from the context).
Lines 25 to 32 contain the HTML markup to display the form.
Lines 26 specifies the FORM tag. Note that the action attribute is set to
the WebMacro servlet processing the form (i.e. URLEncodingWMPage - shown in
Listing 1). Also, the form will be submitted using the POST method.
Line 28 contains a WebMacro Script term which sets the value of the form's
inputString field (from the context).
Lines 33 to 37 contain the HTML markup to complete the page.
Line 35 contains a WebMacro Script term which inserts the current date from
the context.
An example application which employs the MVC framework is provided in appendix
1.
Comparing WebMacro to JavaServer Pages
There a several major criticisms put forward regarding JavaServer page technology.
In an article entitled The
Problems with JSP, Jason Hunter identifies several issues, which WebMacro
attempts to address:
- It is too tempting to insert Java code in web pages
WebMacro templates cannot contain Java code; rather WebMacro provides a simple
script language aimed at page designers, with access to all of the underlying
data that may be needed and enough power to lay it out in the desired way.
- Some tasks can only be done using Java code within the page
WebMacro Script contains built-in variables covering requests, responses,
sessions and cookies without the need to resort to embedded Java.
- Some simple tasks are made overly difficult
WebMacro makes including headers and footers simple.
- Looping is unnecessarily difficult
WebMacro's looping directives are less clumsy than JSP-specific tags.
- JSP page syntax errors are cryptic and often useless
WebMacro errors are more meaningful, and a logging capability is provided.
- Unless JSPs are pre-compiled, the web server will need to be equipped
with a compiler
WebMacro classes are compiled, and templates are pre-parsed the first time
accessed.
- JSPs consume both extra hard disk and extra memory space
Template engines such as WebMacro don't need to duplicate the page data into
a second file, so hard drive space is spared. Template engines also give the
programmer full control over how templates are cached in memory.
WebMacro arguably achieves the separation of form and function using a simpler
process and cleaner syntax.
However, template engines generally have some downsides:
- No specification
No specification exists for how a template engine should behave. This is far
less important than with JSP because, unlike JSP, template engines demand
nothing special of the web server -- any server supporting servlets supports
template engines
- Not widely known
Template engines aren't widely known. JSP has had a tremendous amount of marketing
and has gained terrific mind share. Using template engines is a relatively
unknown alternative technique.
- Not yet tuned
Template engines have yet to be highly tuned. No performance numbers have
been taken comparing template engine and JSP performance. Theoretically a
well tuned implementations of a template engine should match a tuned implementation
of JSP; however it is likely that, currently, JSP implementations are better
tuned.
Reader
reaction to Jason Hunter's article is also available online.
Developing Object Frameworks based on WebMacro
WebMacro templates contain most or all of the HTML markup, with a only dynamic
content provided by servlets and/or back end components. It still may be beneficial
to create a framework for generating basic HTML.
An object framework can also be developed to provide an abstraction over database
connectivity. Assuming standard Java is used, it shouldn't be too difficult
to develop object frameworks as JavaBeans which can be used in both JSP- and
WebMacro-based architectures.
Other Relevant Issues
State, Authentication and Chunking
Since WebMacro technology is an extension of Java Servlets, all features available
to servlet programmers are available in applications built using WebMacro. This
includes the standard servlet session and cookie management capabilities.
Performance
Since WebMacro templates will need to be loaded and parsed before being presented,
there will be a performance overhead the first time a page is accessed via the
web server. Subsequent hits however will access the pre-parsed copy of the template.
Software Requirements
WebMacro is 100% pure Java, and is an extension of standard servlet technology.
Once installed and configured, WebMacro should work with any Java-based servlet
engine and/or Java-enabled web server.
Configuring WebMacro to work within a particular servlet environment may not
always be straightforward. And the instructions provided were incomplete and
contained some inaccuracies. A reasonable understanding of the servlet engine,
web server and other components of the system environment is required in order
to get WebMacro working properly.
A support Mailing
List is available to help developers get WebMacro up and running, as well
as to provide assistance with WebMacro development.
JDK Requirement
WebMacro as supplied is immediately usable with JDK 1.1.x. If the development
and deployment environment is based on JDK 1.2, it will be necessary to unpack
the sources and make a handful of simple modifications, before recompiling.
The process is described in the WebMacro
Readme document.
JavaScript Issue
There is a minor issue regarding the use of JavaScript within WebMacro templates.
Specifically, developers need to be careful when using curly brackets to define
blocks. The online documentation demonstrates how to safely incorporate JavaScript
within templates.
Status of WebMacro
It should be noted that WebMacro is currently at version 0.89.1, and is still
undergoing development. However it is a widely-used and well-respected template
engine. Information about the current
status of WebMacro is available online.
Online Resources
Appendix 1: Camtech Intranet front page
Camtech's Intranet front page has been re-written to utilise WebMacro technology
and JavaBeans. The source code for the Java-specific components is provided
here.
Notes:
- WebMacro helps enforce the MVC framework, in this case:
- Model = CurrentDateTime.java, BirthdayNotices.java, Birthday.java
- View = intranet.wm
- Controller = IntranetWMPage.java
- The JavaBeans (Model classes) have been reused, without modification, from
the JSP version.
Date: Friday, April 28, 2000 10:27 AM
Home >
Tech Papers >
WebMacro Technical Investigation