WebStringTemplates Previous Next |
This section assumes you are coding a new servlet to implement the Data Interface Definition file shown here and that you have a running servlet server and database as described on the previous page.
This page covers:-
As a first pass at implementing this servlet we will just load the template and the default data and output the web page. This checks that everything is in the correct path and that the Web Page Designer has done his job. The code for this first attempt is shown here. The code is in the serverExamples/bookstore1Servlet sub-directory.
The interesting bit of the code is
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext application = getServletContext(); // load the template 'bookstore.st' and the data 'bookstore.data' from // the 'st' sub-directory of this application. // cache them both in a group called bookstoreGroup. WebStringTemplate wst = WebStringTemplateServer.getInstanceOf(application, "bookstoreGroup", application.getRealPath("/") + "st", "bookstore"); // set content-type header before accessing the Writer response.setContentType("text/html"); // set the buffersize from the default data for this template response.setBufferSize(wst.getOutputBufferSize()); PrintWriter out = response.getWriter(); // then write the data of the response wst.write(out); out.close(); }
WebStringTemplateServer.getInstanceOf( ) creates a group called "bookstoreGroup" if that group does not already exist in this application and loads the template and default data from the /st sub-directory of this application. These are both cached in the application. "bookstore" is the root name of both the template and the data file when using this version of getInstanceOf().
Note: When deploying a template and default data file, drop the .html from the end of the file names, so that bookstore.st.html becomes bookstore.st and bookstore.data.html becomes bookstore.data. WebStringTemplates insists on the template ending in .st and the default data file is often different from the Data Interface Definition file and so should not have the same name. For internationalization, it is your responsibility to request the appropriate template and data files. Another version of getInstanceOf() allows you to specify the data file directly for these cases.
Having loaded the template and data, generating the web page is as easy
as
wst.write(out);
The only other notable bit of code is
response.setBufferSize(wst.getOutputBufferSize());
This sets the response buffersize from the value of the
wst.outputBufferSize attribute in the default data, if there
is one. Otherwise a size of 8192 is used. This allows you to tailor the
buffersize used on a per-page basis by setting this attribute in the default
data. See getOutputBufferSize() for details.
Now that you have a simple example running let's look at the debugging features of WebStringTemplates.
The first debugging feature outputs the template's attributes in a Data Interface Definition format. This is useful, both for checking what attributes have been set by your code, by the default data or by the servlet request, session etc, and as a quick start to writing a Data Interface Definition for the Web Page Designer.
To output the attributes instead of the processing the template, just set the template attribute, WebStringTemplate.OUTPUT_DATA_DEFINITION_FLAG ("wst.outputDataDefinition"), a non-false value. If the attribute has not been defined or is "0" or "false" then it is considered to be logically false. All other values make it logically true.
The sub-directory serverExamples/bookstore2Servlet, contains a modified version of the previous example. The following line has been added.
wst.setAttribute(WebStringTemplate.OUTPUT_DATA_DEFINITION_FLAG,"true"); // then write the data of the response wst.write(out);
When you load and run this servlet, using the url
http://localhost:8080/bookstore2Servlet/
the output page looks like this. Notice that all the data from the Data Interface
Definition file, including the comments, has been included in the output.
Tip: When you add comments to the Data Interface Definition file, roll them back into your default data file as well so that the next time you need to update the Data Interface Definition file due to a server change, all the previous comments are already there.
You may have noticed the attribute wst.outputDataDefinition is not shown in the output. WebStringTemplates uses the following three methods to control which attributes, classes and methods to display:-
skipThisAttibute()
- skips any invalid
attribute names and any names which include '.', except comments which are
output.
skipThisClass()
- skips any class from
javax.servlet, org.apache except
org.apache.taglibs.standard.tag.common.sql.ResultImpl which is output.
skipThisMethod()
- skips getOutputStream(),
getInputStream(), getReader(), getWriter() and getClass()
You may need to modify the skipThisClass()
method if you are
using a servlet server not based on the Apache code. You can over-ride the
effect of skipThisAttribute()
and skipThisClass()
by setting the attribute WebStringTemplate.OUTPUT_SHOW_ALL_FLAG to true.
Bookstore3Sevlet.java sets
WebStringTemplates.OUTPUT_SHOW_ALL_FLAG to true and also adds the request
object to the template under the key "servletRequest". When you call this
servlet using
http://localhost:8080/bookstore3Servlet/bookstore?item=3
you get an output
page like this one. In this page as well as having all the default data,
you can now see the settings for wst.outputDataDefinition
and wst.outputDataDefinition.showAll (at the bottom of the
output page). You can also see a lot of information about the
HttpServletRequest object.
Since this object is not a String, Map or List, it is treated like a bean and introspection is used to find the available get*() and is*() methods and they are called to get an object which is then processed again recursively. The depth of this recursion is limited by the WebStringTemplate.OUTPUT_MAX_DEPTH attribute which defaults to 3 if it is not defined. When the level of recursion is reached the object.toString() is just returned.
At each level, when a 'bean' object is being processed, if .toString() returns something other then the default Object.toString() result, then this is shown as the overall string for this object. As shown for the book object is the output. If the Data Interface Definition file specifies an overall string, then you must ensure that a suitable string is returned by the object's .toString() method.
If you scan down the output page, near the bottom you will find the servletRequest.session data. This is the result of calling the request.getSession() method. This method throw an exception. The exception was caught and returned as the result of this method. This is the string data the template would receive if it tried to access the data path $[servletRequest.session]$
To assist in debugging data filters, you can set the attribute WebStringTemplate.OUTPUT_SHOW_FILTERS_FLAG to true to see
what filter was applied to each data item before it was returned.
Uncommenting
wst.setAttribute(WebStringTemplate.OUTPUT_SHOW_FILTERS_FLAG,"true");
Bookstore3Servlet.java gives this output. Each attribute data is preceded by the class
name of the WSTFilter that was applied to it. At the bottom this page you can
see a table of the filter extension mappings for this template group.
This shows that the wst. attributes are being filtered using the default filter WSTXmlFilter, since no filter was specified.
By default when deployed, WebStringTemplates will return an empty string if the attribute requested by the template is not in the map. For debugging you can call setMissingDataErrorPathReturn(true) to return the requested data path when an attribute is not found. This is the default setting in RunWST, which the Web Page Designer uses.
The completed servlet is Bookstore4Servlet.java. Its url is http://localhost:8080/bookstore4Servlet/
This is only one page not a complete web site so the links don't go anywhere. It uses a support bean Book.java to hold the book details. In this simple example the database connection code has been included in the servlet, however in general you would have a separate class to handle the connection to the data base and lookup and initialization of the book details.
Note that the default data is used to supply the bookId of the featured book. This is an additional data attribute not used in previous examples.
String bookId = ""+wst.get("FeaturedBookId");
The default data is also to supply the urls for the links on the front page. These urls are extracted from the default data, rewritten to add any session details and stored back in the template data for inclusion in the output page.
wst.put("bookcatalogUrl",response.encodeURL(""+wst.get("bookcatalogUrl")));
wst.put("bookdetailsUrl",response.encodeURL(""+wst.get("bookdetailsUrl")));
WebStringTemplates Previous Next |