One thing that we’ve been pretty good at since the launch of Alfresco WCM 18 months ago is our eating of the proverbial dog-food, in that we use the product itself to author, review and push out updates to our web site.
The majority of the site is relatively static in nature and is therefore pre-baked by our templates. Where JSP is used it is mostly for simple tasks such as including common header and footer components and looking up message strings, but there are some areas of the site which do have more dynamic data.
Up until now these areas – including our events, press releases and training pages – have leveraged some relatively simple but custom-built Java libraries that allow data from the underlying XML files to be queried and presented as appropriate, similar to the press release example bundled with the Alfresco example site in WCM.
This approach has worked well, but is a barrier to adding new functionality to the site since extra code must be developed to handle new data types. Whereas data can be queried easily at rendering time using the getXMLDocuments() function exposed to Freemarker and Xalan, this is more difficult to do at request time, requiring either an Alfresco runtime environment on the delivery side or extra code, as above.
I wanted to find a way to allow web developers to easily implement this functionality using JSP and JSTL only and the result has been an XML data processing library that can be leveraged by a JSP page to dynamically pull in and process XML data to assemble the page.
As of yet there is no snazzy name, but suggestions are welcome! The library is a single JAR file, plus a tag descriptor to provide the necessary functions to the JSP.
Under the covers, the library uses functionality from J2SE 5.0’s XPath classes to parse XML content and is capable of loading data from within a standalone servlet container or in the context of the Alfresco virtualisation server, via AVMRemote.
Binary downloads are available as a ZIP containing all the files needed, with the Java source also available.
To install this in an existing webapp, you will need to do the following:
Step 1 – Set up the webapp
Drop alfrescowww-xml.jar into your WEB-INF/lib folder and alf-xml.tld into WEB-INF. You will also need to reference the TLD from within the <web-app> element of web.xml as follows to ensure this gets picked up as appropriate.
<taglib> <taglib-uri>http://www.alfresco.org/jsp/alf-xml</taglib-uri> <taglib-location>/WEB-INF/alf-xml.tld</taglib-location> </taglib>
If you are using JSTL you should also have a section like this, with c.tld and jstl.jar installed as above.
<taglib> <taglib-uri>http://jakarta.apache.org/taglibs/core</taglib-uri> <taglib-location>/WEB-INF/c.tld</taglib-location> </taglib>
Step 2 – Set up the JSP
Add the namespace to your JSP page to allow it to reference the data functions, as follows.
<jsp:root version="1.2" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:alfxml="http://www.alfresco.org/jsp/alf-xml">
This assumes you are using XML syntax within your JSPs and also that you are also using JSTL‘s core components on your page with these fully installed. If not, you will need to modify this code appropriately.
Step 3 -Get XML data
Assuming your webapp starts OK at this stage, you should now be able to use the alfxml:getXMLDocuments() function to pull in XML data from the JSP, using something like the following.
<c:forEach items="${alfxml:getXMLDocuments(pageContext, '/media/releases', false, '/alfdotcom:pressrelease', '/alfdotcom:pressrelease/alfdotcom:launch_date', 2)}" var="pr"> <div class="list-item"> <h3> <a href="/media/releases/${pr['$xml_file_name']}.jsp"> <c:out value="${pr['/alfdotcom:pressrelease/alfdotcom:title']}" /> </a></h3> <p class="summary"><c:out value="${pr['/alfdotcom:pressrelease/alfdotcom:abstract']}" /></p> </div> </c:forEach>
In order, the arguments to the function are as follows: the implicit JSP pageContext object; the virtual directory path to search for XML assets under; a boolean value indicating whether or not the search should be deep (i.e. descend into subdirectories); an XPath condition which must match true (e.g. to only match documents with a alfdotcom:pressrelease root element); an XPath expression, the value of which is used to sort documents (use null or an empty string if no sorting is needed); and lastly an integer indicating the desired sort order (1=increasing, 2=decreasing).
Here I’ve used JSTL’s c:forEach element to iterate over the collection of items returned, but other mechanisms are obviously possible. The code above is a pretty simple example of what can be output using EL to fetch field values from the XML based on simple XPath expressions, but more complex expressions can obviously be built up. I’ll post more examples another time.