BigAdmin System Administration Portal

HowTos

Archived from Sun's Dot-Com Builder Web Site
This content is archived from Sun's Dot-Com Builder Web Site.
These are the Best Practices > How To's archives.

Some of these pages may contain links that are no longer available. If you see these, you can report it through the Suggestions link and we will remove the link and leave the name (for reference).

Back to Dot-Com Builder How-Tos Archive

Enabling Wireless Access to Dynamic Web Content
March 15, 2001

by Iftikhar Ahmed

The proliferation of wireless devices is sending developers scrambling to convert their HTML Web content to wireless device formats (WML, WAP, HDML).

While there are several common ways to do this, the method described in this article has the advantage of using XML/XSLT as a base. This is beneficial for the following reasons:

  • The XML/XSLT base is supported by most wireless middleware.
  • Development time is quick using JavaServer Pages (JSP) technology/servlets.
  • A wireless extension is unnecessary.
  • The method is framework-independent, that is, the code can be used in any wireless application server because it does not depend on the server's particular API.

This coding approach entails three steps, briefly summarized here and described in detail later.

Coding with servlets/JSP technology to implement solutions quickly and easily
When a short time to market is critical, using servlets/JSP technology is the easiest way to convert HTML to wireless formats. Good performance is also assured because each JSP is written specifically for a device, and no conversion or transformation occurs. One disadvantage of this approach is that maintenance can be difficult because of the repetitive code necessary to access the back end for individual devices. However, this can be solved by writing servlets to generate XML output to run above the server's API.

Formatting the data using XML and transforming it to the device tag format using XSLT
Formatting data in this way is the most dependable method because XML/XSLT is used in all major wireless server middleware products.

Back-end data is accessed and formatted in a device-independent format (XML), while a specific XSLT is used (depending on the device) to transform the XML into the device-tag format (WML, WAP, HDML).

Using a style sheet cache and/or an XSLT compiler can improve the decrease in performance caused by the transformation step.

Porting the code from one wireless extension server to another (simple code written in a base servlet class or via middleware)
Almost all the application middleware vendors have added wireless extensions to their products, among them:

  • iPlanet Wireless Server
  • IBM WebSphere Everyplace Suite
  • BEA WebLogic M-Commerce Solution
  • Oracle Portal-to-Go

This arrangement provides an integrated and scalable solution that works best in the long run, balancing out the disadvantage of the high learning curve for these products.

The Approach

The approach begins with an example of how generating wireless content using custom code is normally done. Using this framework-dependent starting point, you can create a framework-independent solution. The process consists of the following:

  • Begin with framework-dependent custom code.
  • Generate framework-independent wireless content using a servlet or JSP script.
  • Apply a style sheet for transformation.
  • Apply a base JSP class for a custom wireless extension.

How generating wireless content using custom code is normally done (framework-dependent)
When developing custom XML/XSLT, you normally add code to each servlet or JSP script to support presentation on multiple devices, as shown in Figure 1. In this figure is an example of how a servlet allows access to bank-account detail. The problem with this code is that it is framework-dependent. Step-by-step instructions on how to change this code to make it work regardless of framework are provided after Figure 1.

Figure 1: Framework-dependent custom code -- the starting point

...... 

import com.atlas.util.CXMLUtility;
import com.atlas.util.CStylerUtility;
import com.acme.acctinfo.wls.beanwrappers.*;
...... 

 public void doGet (HttpServletRequest req, 
                   HttpServletResponse res)
       throws IOException
  {
    try
    {
        HttpSession s = 
         req.getSession(false); 
        String strUSERID = 
         (String)s.getAttribute("USERID");
        IAccountDetail o = 
          Factory.getAccountDetailObject();
         String strAcctList = 
          o.getAccountList(strUSERID) ,

         String strOut=CXMLUtility.transform(strAcctList, 
CStylerUtility.selectStyle( "ACCTLIST", req), req );

         PrintWriter out = res.getWriter();
       out.println(strOut);
       out.close();
    }
    catch(Exception e)
    {
        processError(e,req,res);
    }
 }

In the previous code:

  • IAcctDetail.getAccountList returns an XML representation of Accounts, which is then passed to the CXMLUtility.transform function to perform a transformation.
  • CStylerUtility.selectStyle is used to select a device-specific XSL to perform the transformation.

This approach works well and uses a modular presentation design; however, if you have to port this solution into a more robust framework or to a wireless server later, you will need to rewrite these servlets/JSP scripts to work within the new environment. The solution is to generate wireless content using a servlet, as described in the next section.

How to generate wireless content using a servlet (framework-independent) By using the following simple inheritance approach, you can develop a solution that works in a framework-independent way.

  • Each wireless-enabled servlet extends the XMLBaseServlet instead of the normal HttpServlet.
  • These servlets are responsible for generating an XML output and have no data on any framework within which they are running.

The following code sample -- a rewrite of the sample in Figure 1 -- implements this solution.

Figure 2: Generating framework-independent code (using a servlet)

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

import java.util.*;
import java.net.*;

import com.acme.acctinfo.wls.beanwrappers.*;

public class AcctDetail extends 
com.atlas.wls.servlets.XMLBaseServlet implements 
com.atlas.wls.ILoginRequired {
... .
... .

  public void doGet(HttpServletRequest req, 
   HttpServletResponse res)
       throws IOException
  {
    try
    {
      HttpSession s = req.getSession(false);
      String strUSERID = 
       (String)s.getAttribute("USERID");
      IAccountDetail o = 
       Factory.getAccountDetailObject();

      String strAcctList = o.getAccountList(strUSERID),
      PrintWriter out = res.getWriter();
      out.println(strAcctList);
      out.close();
  }
... .
... .
... .

Note that in the previous code there are no package or function calls to a style sheet. To apply a style sheet for transformation, use the following instructions.

How to apply a style sheet for transformation
Use one of the following ways to apply a style sheet for transformation:

  • Using a a servlet (XMLBaseServlet class)
  • Using a JSP script

Using a servlet to apply a style sheet for transformation
The XMLBaseServlet class contains all the logic necessary to enable a device-specific transformation. The trick used by this servlet is to give a pseudo HttpServletResponse object that buffers the output instead of sending the output to the client browser.

After the "doGet" method of a servlet returns control to the XMLBaseServlet class, the "service" method of XMLBaseServlet can select a style sheet for transformation by using the class name of the servlet and the current device user-agent.

Following is a code sample demonstrating the use of the "service" method of the XMLBaseServlet:

Figure 3: Base servlet class "service" method for a custom wireless extension

  public void service(HttpServletRequest req, 
                     HttpServletResponse res)
       throws ServletException,IOException
  {
         XMLHttpResponse xRes= new XMLHttpResponse(res);

// call super class service method, but pass a pseudo 
// Response object
        do_service(req,xRes); //call do_service
			     //super.service()directly
			     //instead of
                             //to make this work
                             //for JSPs (as in
			     //JSP it is '_jspService'
		    		//that works the way
				//service' works
                                 //in servlet
                                 //the do_service base
				//implementation
				//for servlet
                                 //will call
		         //super.service(req,res).

        Class s = (Class) this.getClass();
        String strClass= removePackages(s.getName());

        try
        {
// get the output XML generated by Servlet
        String strXML = xRes.getResultString();
        System.out.println("XML="+strXML);

// transform
          String strOut=CXMLUtility.transform
                  ( strXML,
                      CStylerUtility.selectStyle(
                             strClass.toUpperCase(),
                             req,res ),
                                                req );
           PrintWriter out = res.getWriter();
           out.println(strOut);
           System.out.println("RESULT="+strOut);
           out.close();
        }
        catch(Exception e)
        {
             processError(e,req,res);

        }

 
}

The preceding example calls do_service instead of the super class service method shown in Figure 2. By default, do_service forwards the call to the super class service method.

Using JSP scripts to apply a style sheet for transformation
Since JSP scripts are simply servlet extensions, the same XMLBaseServlet class also works with JSP scripts using the approach described previously. The do_service executes the _jspService method (shown in Figure 5). The JSP code must return XML as its output, and it must use the "extend" attribute in the page directive, as shown in the following sample code:

Figure 4: Generating framework-independent wireless content (using JSP scripts)

<%@ page extends="com.atlas.wls.jsp.XMLJspPage" %>
<acctdetails>
<acctdetail id="1" name="Interest Checking"
acct_number="33343151" balance_amount="3324"
ledger_amount="2203">
<transactions>
    <transaction ondate="10/10/2000" type="withdrawals"
    amount="60.00">ATM WITHDRAWAL ACMEBANK
    PK39393</transaction>
    <transaction ondate="10/9/2000" type="deposits"
    amount="4093.00">ACH CREDIT 05891835 ATLAS
    SOFTWARE</transaction>
    <transaction ondate="10/9/2000" type="withdrawals"
    checknumber="304"  amount="56.00">CHECK 305
    005867493</transaction>
</transactions>

</acctdetail>
<acctdetail id="2" name="Money Market"
acct_number="33343152" balance_amount="6000"
ledger_amount="6000">
<transactions>
    <transaction ondate="10/10/2000" type="withdrawals"
    amount="60.00">ATM WITHDRAWAL ACMEBANK PK39393 
    </transaction>
</transactions>

</acctdetail>
<acctdetail id="3" name="Savings Account"
acct_number="33343153" balance_amount="1564"
ledger_amount="1564">
<transactions>
    <transaction ondate="10/9/2000" type="withdrawals"
checknumber="304" amount="56.00">CHECK 305
005867493</transaction>
</transactions>

</acctdetail>

</acctdetails>

How to apply a base JSP class for a custom wireless extension
The XMLJspPage JSP base class is used as an extension for JSP scripts (just as XMLBaseServlets are used as a base class for servlets) and follows the JSP base-class specification shown in Figure 5.

Figure 5: Base JSP class for a custom wireless extension

package com.atlas.wls.jsp;
import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import com.atlas.wls.servlets.*;
/**
* Super Class XMLJspPage to do the XSL Transformation 
* from a JSP that generates XML
* to use this class use JSP Page directive with attribute
* "extends"
*/

public abstract class XMLJspPage extends XMLBaseServlet
implements HttpJspPage {

private ServletConfig config;

final public void init(ServletConfig config) throws 
ServletException 
{
this.config = config;
jspInit();
}
// default jspInit method
public void jspInit()
{
}

// default jspDestroy method
public void jspDestroy()
{
}

final public ServletConfig getServletConfig() {
return config;
}

// This one is not final so it can be overridden by 
// a more precise method

public String getServletInfo() {
return "Superclass for an HTTP JSP";
}

final public void destroy() {
jspDestroy();
}

final public void service(ServletRequest req, 
ServletResponse res)
throws ServletException, IOException

{
    super.service(req,res);
}

// do_service is finally called by BaseServlet when 
// all the checks are
  done public void do_service(HttpServletRequest req,
  HttpServletResponse res)
       throws ServletException,IOException
  {
       _jspService(req,res);
  }

/**
* abstract method to be generated by the JSP processor
* in the subclass
* 
*/
abstract public void _jspService(HttpServletRequest 
request, HttpServletResponse response) throws 
ServletException, IOException;

}

This approach allows you to modify and port the code to a new framework or wireless server by changing the XMLBaseServlet only. As it follows the JSP or servlet model, you can implement solutions easily and quickly if you already understand XML and XSLT. The procedure enables porting of a wireless solution from one application server to another, such as from Oracle Portal-to-Go to iPlanet Wireless Server.


BigAdmin