14.5 Tea Applications

Java Servlet Programming, 2nd Edition > 14. The Tea Framework > 14.5 Tea Applications

 
< BACKCONTINUE >

14.5 Tea Applications

So far we've been looking at Tea templates alone, and they are very weak intentionally weak. But Tea templates are like frontline infantry soldiers when alone they are weak but when teamed with advanced backend air support, they become extremely powerful. Here are some ways to make Tea templates more powerful.

Templates may access any function from any "application" installed into the TeaServlet via the TeaServlet.properties file. (Each web application can have a different TeaServlet.properties file and thus a different set of installed applications.) Templates call functions by specifying within a Tea code block the function name followed by open and close parentheses. Functions may accept parameters and may return values:

<% list = getRecords() %> <% removeRecord(8086) %>

The TeaServlet administration screen shows a list of all available functions from all installed applications. Should two applications declare the same function, a template can prefix the function call with the application name to remove the ambiguity:

<% list = RecordListApp.getRecords() %>

There's a set of utility functions available across all templates intended to help with basic text-processing chores. The following sections list some of the most frequently called utility functions.

14.5.1 Text Processing

Here are some common text-processing functions.

Date currentDate()

Returns the current date.

void dateFormat(String format)

Alters the format of all dates later output by this template.

void numberFormat(String format)

Alters the format of all numbers later output by this template (not including string literal numbers).

void nullFormat(String format)

Assigns a string to be used in place of null when printing a variable with a null value.

void setLocale(String language, String country)

Alters the locale for all dates, numbers, and so forth later output by this template.

boolean startsWith(String str, String prefix)

Returns true if the string starts with the prefix specified.

boolean endsWith(String str, String suffix)

Returns true if the string ends with the suffix specified.

String substring(String str, int startIndex, int endIndex)

Returns the section of the string from the start index to the end index (exclusive).

String trim(String str)

Returns the string with leading and trailing whitespace removed.

int[] find(String str, String search)
int[] find(String str, String search, int fromIndex)

Return the indexes at which the given string contains the search string, with an optional starting index.

String replace(String source, String pattern, String replacement)
String replace(String source, String pattern, String replacement, int fromIndex)
String replace(String source, String pattern, String replacement, int fromIndex, int toIndex)

Replace all exact matches of the pattern within the source with the given replacement string, with an optional starting and ending index.

14.5.2 Content Handling

Here are some common content-handling methods.

void insertFile(String filename)

Inserts the contents of the given file into the page output. Inserts nothing if the file can't be read. The filename can be relative or absolute. If absolute, the path is offset from the template root (usually the web application document root).

void insertURL(String url)

Inserts the contents of the URL into the page output. If the URL can't be read, it inserts nothing. The URL can be relative or absolute.

boolean fileExists(String filename)

Returns true if a file by the given name exists.

boolean URLExists(String url)

Returns true if the given URL exists.

14.5.3 Request/Response Handling

In addition, here are some frequently-used request/response methods.

com.go.teaservlet.HttpContext.Request getRequest()
com.go.teaservlet.HttpContext.Request getRequest(String encoding)

Get an object that contains request information, with an optional encoding to allow automatic parameter value conversion.

void setContentType(String contentType)

Sets the content type of the response.

void setHeader(String name, String value)

Sets a response header.

void setStatus(int sc)

Sets the status code of the response.

void sendRedirect(String url)

Redirects the request to the given URL.

void sendError(int sc)
void sendError(int sc, String message)

Send an error page for the given status code with an optional error message.

The template in Example 14-5 demonstrates how a template may call on the utility functions to print an ad-click-through percentage for a given day. The date and percentage are formatted in the French style.

Example 14-5. French Clicks
<% template clicks() %> <HTML><HEAD><TITLE>Testing the Tea Built-In Functions</TITLE></HEAD><BODY> <% // Set the locale; it remains for all later template output setLocale("fr", "CA")  // Quebec // Specify how time and numbers should be formatted dateFormat("d MMMM yyyy") numberFormat("#0.00%") // Some fake data clicks = 485.0 accesses = 7673.0 %> <H2><% currentDate() %></H2> Le pourcentage: <% clicks/accesses %> </BODY></HTML>

The template writes something like this, with the date and percentage appropriate for someone living in Quebec:

16 juillet 2000 Le pourcentage: 6,32%

14.5.4 Writing a Tea Application

Now let's look at how to write a custom Tea application. It's easy: just write an application class and a context class. All application classes implement the com.go.teaservlet.Application interface. Just like a servlet, the Application interface has init( ) and destroy( ) methods to handle lifecycle issues. Instead of a service( ) method the Application has a createContext( ) and getContextType( ) pair of methods. The createContext( ) method returns a context object whose methods are made available to templates as functions. The getContextType( ) method returns the java.lang.Class of the object returned by createContext( ) to facilitate type checking.

The following two examples show a simple application that attempts to determine the name of the user through various means. The NameApp class is the application class (Example 14-6); the NameContext class is the context object created by NameApp and made available to templates (Example 14-7).

Example 14-6. The NameApp Class
import com.go.teaservlet.*; import javax.servlet.*; public class NameApp implements Application {   // Both init(ApplicationConfig) and destroy() must be implemented because   // they are declared in the Application interface.  They can be left empty.   public void init(ApplicationConfig config) throws ServletException {   }   // Creating a context provides functions accesible from the templates.   public Object createContext(ApplicationRequest request,                               ApplicationResponse response) {     // You often pass on the request and response even if     // they are not used, since they may be used later     return new NameContext(request, response);   }   // This method must be implemented to return the class of the object   // returned by createContext()   public Class getContextType() {     return NameContext.class;   }   public void destroy() {   } }

The TeaServlet calls the init( ) method a single time when the application is first loaded to give the application an opportunity to perform initialization. It calls destroy( ) a single time on shutdown to give the application a chance to clean up. The init( ) method accepts an ApplicationConfig parameter, which is a subinterface of ServletConfig with three additional methods getLog( ) , getName( ), and getProperties( ) to retrieve the application log, name, and initialization properties.

The TeaServlet calls the createContext( ) method before request handling and makes available all the methods of the returned context object as functions for the requested Tea template. If there needs to be a different context per user, that can be easily managed using standard session-tracking code in the createContext( ) method. The createContext( ) method accepts ApplicationRequest and ApplicationResponse as parameters. These are subinterfaces of HttpServletRequest and HttpServletResponse with the addition of a few Tea methods.

Example 14-7. The NameContext Class
import com.go.teaservlet.*; import javax.servlet.*; import javax.servlet.http.*; public class NameContext {   ApplicationRequest request;   ApplicationResponse response;   String name;   public NameContext(ApplicationRequest request,                      ApplicationResponse response) {     this.request = request;     this.response = response;   }   public String getName() {     // If we already determined the user's name, return it     if (name != null) {        return name;     }     // Try to determine the name of the user     name = request.getRemoteUser();     // If the login name isn't available, try reading a parameter     if (name == null) {       name = request.getParameter("name");     }     // If the name isn't available as a parameter, try the session     if (name == null) {       name = (String) request.getSession().getAttribute("name");     }     // If the name isn't in the session, try a cookie     if (name == null) {       Cookie[] cookies = request.getCookies();       for (int i = 0; i < cookies.length; i++) {         if (cookies[i].getName().equals("name")) {           name = cookies[i].getValue();         }       }     }     // If the name isn't in a cookie either, give up     return name;   } }

The getName( ) method attempts to determine the name of the client user by searching the client's login credentials, parameter list, session data, and request cookies. It returns null if no name information could be found. Templates access the name by calling the getName( ) function. Notice the context calculates the client's name in getName( )and not in the constructor. This is a performance trick. If the logic were in the constructor it would be executed during the handling of each request, whether or not any template actually called getName( ).

To make the NameApp application available requires the following short addition to the TeaServlet.properties file:

"NameApp" {     class = NameApp }

You can verify the application was properly loaded by browsing the Applications link of the TeaServlet administration application.[2]

[2] If the application classes aren't found even though it appears they should be, the cause may be a class loader issue. There can be problems if the TeaServlet.jar and application classes are loaded by different class loaders. Either put both in the system classpath where they'll be found by the primordial class loader or put both under the WEB-INF directory where they'll be found by the web application class loader. (Put TeaServlet.jar in the WEB-INF/lib directory; put the application classes in the WEB-INF/classes directory.) Also remember that because of class loader issues, support classes aren't necessarily reloaded even when selecting Reload All from the TeaServlet administration page.

With this application loaded, any template can display the client's name using the getName( ) function:

<% template names() %> <% setContentType("text/plain") nullFormat("Unknown") %> Your name is <% getName() %>.


Last updated on 3/20/2003
Java Servlet Programming, 2nd Edition, © 2001 O'Reilly

< BACKCONTINUE >


Java servlet programming
Java Servlet Programming (Java Series)
ISBN: 0596000405
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net