Skin Emax - An XML/XSLT Architecture for the Web

Java Development News:

Skin Emax - An XML/XSLT Architecture for the Web

By Joe Chandler and Jason Thurow

01 Apr 2003 | TheServerSide.com

Introduction

Problem Domain

The challenge of providing different views of the same data is becoming a more common requirement of web-based applications. This requirement can surface in varying degrees during the inception and elaboration phases in a project. These data representations can vary by actor and role, all the way to providing a completely different look and feel (which will be labeled "skin" in this article) based on the company executing a functional piece of a system designed, hosted and executed by a company offering business services.

A common approach to solving these requirements is through the XML / XSLT technologies using an XSL stylesheet to transform an XML document into the desired view. There is nothing new about this concept and many websites use this technique to accomplish co-branding requirements. Additionally, many websites use this technique to communicate with outside systems returning XML, which then needs to be converted via XSLT into an XML representation that the system can understand and process. When this approach is used to generate HTML for an end user's view the solution becomes more complex due to various constraints of XSL.

The main constraint of XSL is due to the fact that the stylesheet and its included tags must represent a well-formed XML document. This is rather limiting when dealing with HTML for large B2C and B2B sites. After the HTML has been developed and delivered to the construction team it is usually decomposed into reusable files that then get included, used and processed to form a page on a website. XSL does have the mechanism to include and import files, but these files must be well-formed XML. Additionally, include and import declarations can only occur at the top of a file. This implies the stylesheet cannot be decomposed into smaller HTML pieces such as a header and footer, because the header would naturally contain HTML tags that would be closed within another file, thus breaking the well-formed XML rule. Additionally, footers cannot be included at the top of a file by the very fact that they are footers and need to be placed at the end. Another approach that could be used to get around the footer problem would be to use the remote entity concept of XML. This approach still fails because remote entities, which are merely a reference to an external xml file, also fall under the syntactically strict requirements of well-formed XML, thus preventing a footer from closing an html tag that was presumably opened in the header.

This document will provide a simple solution and architecture to solve the problems presented by XSL needing to be well formed XML when working with Entity, import and include mechanisms of XML and XSLT. The solution to the problem makes use of the javax.servlet.Filter class, JSP technology and XML and XSLT. The solution involves processing the XSL as a JSP page. By doing this the developer can utilize the JSP include tags as well as everything else JSP technology has to offer, producing a well-formed XSL file that can then be compiled into a javax.xml.transform.Templates class that can then be used by an XSLT processor.

A proposed architecture for this solution is presented in this document as a means for implementing the solution and detailing a real world example. The architecture that is used makes use of the Struts framework to help provide an implementation, but is not necessary to implement the solution. The Struts framework will not be explained as a part of the document; it is merely being utilized for the Controller in the MVC approach.


Features

Business Benefits

  • Skin eMax provides a market-oriented approach to doing business on the web. Skins are created to the desires and needs of the customer.

  • Enables unlimited co-branding opportunities. Since data is represented in XML, the marriage of the skin to the XML data can occur for an unlimited amount of companies. For example, financial data can be married to a Charles Schwab skin or a Morgan Stanley skin for a co-branded view to the investor.

  • Clear division of skills is a result from this architecture. HTML developers concentrate on HTML and Java developers focus on fitting that HTML into XSL skins ( a simple operation ). This leads to an efficient and cost-effective project team.

  • The simplicity in this design and ease of implementation reduces the time and cost of development.

Technical Benefits

  • This architecture uses open standards to solve the problem domain. J2EE components of the design include:

    • XML.
    • XSL.
    • JSP.
    • The Servlet API.

  • A clear separation of data and view not only provide the aforementioned business benefits, but also eliminate a lot of the pain associated with tightly integrated presentation and data. Java logic spattered throughout the JSP is normally required to include or exclude certain presentation features; this now can be accomplished by simply requesting the appropriate XSL (skin) to be married to the data.

  • Multiple presentations of the same data in any format can be accomplished because of the benefits XSL provides. The same data can be presented as HTML, WML, XML, or even in a comma separated text file.

  • The open standards approach of this architecture easily integrates with open source, BEA, ATG, Websphere, or any application server products that support J2EE. A container that can execute a .war file is all that is required.

  • Plugability into existing architectures (i.e. Model 1, Model 2, or Model 2X) can be easily accomplished.

  • The skins are invoked via an HTTP call. Therefore, they can live anywhere. Clients may need control over their presentation because of a frequent need to update their look and feel. They can house the XSL files and update it to their liking as long as it conforms to the Document Type Definition (DTD).

  • Skin eMax creates a transactional interface using DTD to describe the data. This allows the host to publish the interface using the DTD standard to completely and accurately describe the data to any consumer.

Implementation

Concepts and Terms

To understand the implementation of Skin eMax there are a few new terms and concepts requiring explanation. With the first concept, as previously stated in the problem domain, the XSL is compiled and executed as a JSP page whose output will ultimately contain the XSL. Although this technique is used to overcome some of the constraints of XSL, it is not necessary, for the use of Skin eMax. The XSL can live happily in one file and Skin eMax will execute normally.

There are four parameters that Skin eMax uses which are accessed through the request or FIlter initialization parameters. These request and initialization parameters help Skin eMax determine what XSL template to use when processing a request.


Request Parameter Description
skinURL A complete path to the skin.  If this is found on the URL all other parameters are ignored.
skinServer This is the server name  to which an http request will be made to retrieve a skin.  If this is not set in the request or as a config parameter to Skin eMax, the server Skin eMax is running on will be used.
skinContext This is the context used to find a skin.  It is basically an upper level directory that is appended to the skinServer.  If co-branding is being done, this might be a company name.  The Skin eMax Filter will take this as a config parameter for a default skinContext.  If it is passed on the request the default is overridden.
skinPath The path to the skin from within a given skinContext.  This must be passed.


Request Parameter Description
skinURL http://localhost:8080/demo/skins/default/account/viewAccountSummary_xsl.jsp
skinServer http://someserver/skins
skinContext default, company1/project/skins, company2/skins, skins
skinPath account/viewAccountSummary_xsl.jsp

Examples


The Components

Skin eMax at its core is composed of a Filter. This Filter is responsible for intercepting requests that match the url-pattern defined by an entry within the web.xml file. After receiving the request, the filter forwards it to whatever resource was meant to process the request. After the request processes, the SkinEmaxFIlter captures the result, which, hopefully, is XML. The filter then uses the parameters mentioned above to decide what XSL to process against the returned XML.

A very basic use of the SkinEmaxFIlter would be defining an entry within web.xml and making sure the application knows about the SkinEmaxFilter.class. This basic usage is explained below:

Web.xml

The following entry should be placed at the top of web.xml:

 <filter>
        <filter-name>SkinEMax</filter-name>
        <filter-class>com.theserverside.servlet.Filter</filter-class>
        <init-param>
            <param-name>DEBUG</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>skinServer</param-name>
            <param-value>http://localhost:8080/demo/skins</param-value>
        </init-param>
        <init-param>
            <param-name>skinContext</param-name>
            <param-value>/default</param-value>
        </init-param>
 </filter>

    <filter-mapping>
        <filter-name> SkinEMax </filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>

SkinEmaxFilter.java

This brief snapshot of the SkinEmaxFilter does the following:

  • Utilizes the HttpServletResponseWrapper class, providing the ability to access the response data before it is sent to the client.
  • Envokes the doFilter method on the chain causing the end resource to be invoked.
  • Processes the end resource's response, XML, to the desired XSL stylesheet.
  • Delivers the result of the XSL processor to the client in the desired format. (HTML for this example)

public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {

      SkinEMaxFilterResponseWrapper rw =
         new SkinEMaxFilterResponseWrapper((HttpServletResponse)response);
      chain.doFilter(request, rw);

      String writerString = rw.getStringWriter().toString();
      if(writerString.length() <= 0)
         return;
      try {
         XMLReader reader = ParserFactory.getSAXParser().getXMLReader();
         TransformerHandler transformerHandler =
            getTransformerHandler((HttpServletRequest)request);
         reader.setContentHandler(transformerHandler);
         transformerHandler.setResult(new StreamResult(response.getWriter()));
         InputSource inputSource = new InputSource(new StringReader(writerString));
         reader.parse(inputSource);
      } catch (Exception e) {
         throw new ServletException("Exception while processing JSP output", e);
      }
   }

Other Skin eMax Classes

Class Description
SkinEMaxFilterResponseWrapper A private inner class contained within the SkinEmaxFilter class.  This class extends the HttpServletResponseWrapper to hook a StringWriter to the PrintWriter associated with the ServletResponse.
ParserFactory A  class that is used to create a SAXParser.
TemplateFactory A singleton that is used by the SkinEmaxFilter class to create Templates based on the XSL and cache these Templates.
TransformerHandlerFactory A singleton that is used to create TransformerHandler classes.


A Real World Example

Description

For the real world Skin eMax example we will look inside the financial industry to a company which provides the infrastructure and system resources to manage investment money for firms that employ financial representatives responsible for individual investor's savings. When these representatives use the system, they should feel as though the system is provided and operated through their company. This can be achieved through co-branding the application. Additionally when the individual investor logs onto the system it should look and feel as though the system is being hosted and operated by their financial representative's company who is managing their money.

The following diagram illustrates this situation:


Struts as the controller

For this example, the Struts framework will be utilized to provide the controller in the MVC application. Some example action-mapping entries found in the struts-config file are shown to illustrate how different skins can be applied to form the resulting HTML ultimately delivered to the client.


Example 1:

In this example a user is calling the viewAccountSummary use case. The viewAccountSummary.jsp produces XML as its output (this is the data view of the transaction). The success-skin /account/viewAccountSummary_xsl.jsp is applied to the XML to form the resulting HTML. The action class the Struts framework forwards control to perform the work, com.theserverside.action.ViewAccountSummaryAction, forwards to success, sets the skinContext to the appropriate investment house based on the user's logon information and then sets the skinPath to the success-skin entry. The SKinEmaxFIlter retrieves these parameters off the request and performs the desired transformations.


struts-config.xml entry:

    <action    path="/account/viewAccountSummary"
               type="com.theserverside.action.ViewAccountSummaryAction"
               name="acntForm"
              scope="request"
              validate="false"
              input="/account/viewAccountSummary.jsp">
    <forward   name="success"              path="/account/viewAccountSummary.jsp"/>
    <forward   name="error-skin"           path="/account/accountSearchError_xsl.jsp"/>
    <forward   name="success-skin"         path="/account/viewAccountSummary_xsl.jsp"/>

    </action>

Key Points:

  • No entries within the struts-config need to be changed based on the user or the investment house. The skinContext is used to differentiate the firm for co-branding.

  • If a firm wanted for some reason to provide their own XSL template to the viewAccountSummary use case they could simply pass a skinURL along with the request. This would override the entries found within the struts-config and the desired template would be applied.

  • The JSP which ultimately produces the XML could be tied to a DTD. This DTD could be used to define the transaction for all that execute it. That JSP could then be used to handle more than just presentation for the user.

Example 2:

This is an example of a user calling the downloadAccountSummary use case. The important thing to note about this example is that the same JSP that services the viewAccountSummary.jsp is servicing this use case as well because these JSPs are producing XML, not the resulting view.


struts-config.xml entry:

    <action    path="/account/downloadAccountSummary"
               type="com.theserverside.action.ViewAccountSummaryAction"
               name="acntForm"
              scope="request"
              validate="false"
              input="/account/viewAccountSummary.jsp">
    <forward   name="success"              path="/account/viewAccountSummary.jsp"/>
    <forward   name="error-skin"           path="/account/accountSearchError_xsl.jsp"/>
    <forward   name="success-skin"         path="/account/downloadAccountSummary_xsl.jsp"/>

    </action>

Key Points:

  • The downloadAccountSummary use case is utilizing the same JSP as the viewAccountSummary use case.

  • The download requirements for the investment firm could be different ( a text file, a csv file, a pdf file... ) but only the XSL should have to change. (the pdf might be a stretch!)
Class Diagram - SkinEmaxFilter

Sequence Diagram

Part 1

The following sequence diagram illustrates the sequence of messages sent up to and including the JSP that returns XML: (high level sequence diagram)

Figure - Sequence Diagram Part 1

Part 2

The following sequence diagram illustrates the sequence of messages sent after the result XML was delivered back to the SkinEmaxFilter. (high level sequence diagram)

Figure - Sequence Diagram Part 2


An XMLC Comparison

There are other available APIs that essentially do the same thing as Skin eMax. One such tool is XMLC. The advantages of XMLC include:

  • Productive UI development by using leading HTML editing tools, such as GoLive or Dreamweaver, with HTML pages that include dynamic content.

  • Productive business logic development by not requiring changes to source code for every UI change.

  • Enabling a high degree of concurrent development between page designers working on the presentation (HTML/WML/cHTML/XHTML) layer and engineers working on the back-end business logic (Java).

  • Content delivery to any client, including HTML, WML, XHTML, cHTML, VoiceXML, Flash, and Java™ 2 Platform, Micro Edition (J2ME™ ) devices.

  • Easily create localized versions of a site by providing easy to load presentation skins that differ based on the preferred language. Although not stated as an advantage, XMLC would be a great candidate for co-branding a site. A developer could decide which class to load based on some subset of data associated with a user, thus providing a different co-brand.

Although not stated as an advantage, XMLC would be a great candidate for co-branding a site. A developer could decide which class to load based on some subset of data associated with a user, thus providing a different co-brand.

The main drawback to using XMLC for a large production site with potentially hundreds of dynamic pages is the fact that HTML is almost always broken down into smaller files that when put together represent the page. Luckily, XMLC does support the include feature, enabling the HTML to be decomposed. The drawback to this however, is it is a compile time include. Whenever HTML snippets change, the code including those snippets must be regenerated and recompiled. If these included files presented dynamic content the problem can be compounded if the data is now represented in a different manner on the page and HTML DOM is being used to manipulate the page. The class that manipulates the XMLC generated source could be forced to change.

Another element of XMLC that can be challenging is the class hierarchy that must be built to get a set of pages to share functionality. With the dynamic nature of HTML and the frequency and unbounded degree of change, the hierarchy can become very brittle. It seems that too much thought, planning and Java needs to go into XMLC just to display HTML.


Conclusion

The sample has shown that the SkinEmaxFilter enables the developer to perform the marriage of the XML data with the XSL presentation for the customized or co-branded presentation. By creating the XSL template via a JSP file it further enhances the capability of XSL by leveraging the JSP include mechanism along with all the other JSP features. Additionally, this technique successfully navigates the well-formed XML barrier that would exist if using XSL imports or includes.

In summary, this architecture enables development to clearly separate data from the presentation. This separation leads to successful deployment of systems that require intensive co-branding because presentations can be easily added or modified without changing the underlying business layer. Moreover, by separating the data from the view in a clean manner, Java developers and HTML developers have a clearer view of their responsibilities within the software development lifecycle. Also, Skin eMax aids in soothing the common headache developers have with maintaining smattered Java code in the presentation tier.


About the Authors

Joe Chandler is a Senior Engineer at eForce in Denver, CO. He has over 10 years of experience in design and development, with senior programming positions at Sun Microsystems, IBM and AT&T. He holds a bachelor of science degree in CIS from University of CO, Boulder and a MS in IS from University of Denver. http://www.eforceglobal.com

Jason Thurow is a senior engineer with eForce in Denver, CO. He has have worked in systems consulting for over seven years focusing on enterprise-wide solutions. He has developed solutions for a wide-range of industries including Financial Services, Media and Entertainment, and Hi-Tech. Jason graduated from Ohio State in 1995.